{"id":9,"date":"2025-04-13T17:44:13","date_gmt":"2025-04-13T17:44:13","guid":{"rendered":"https:\/\/blog.metu.edu.tr\/e264325\/?p=9"},"modified":"2025-04-13T17:44:15","modified_gmt":"2025-04-13T17:44:15","slug":"haunted-library-ceng469","status":"publish","type":"post","link":"https:\/\/blog.metu.edu.tr\/e264325\/2025\/04\/13\/haunted-library-ceng469\/","title":{"rendered":"Haunted Library &#8211; CENG469"},"content":{"rendered":"\n<p>Welcome, dear Computer Graphics enjoyers!<\/p>\n\n\n\n<p>In this blog, I will talk about some details of my implementation for CENG469 Computer Graphics II homework and the challenges I faced.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Curved Path Generation<\/h1>\n\n\n\n<p>I decided to start with this part as it seemed to be the easiest one. I implemented <code>BezierCurve<\/code> class. Throughout the whole program, I keep one global instance of <code>BezierCurve<\/code> class, which is  instantiated with hardcoded control points at the beginning of the program. Each frame the <code>t<\/code> parameter of the curve is increased by a hardcoded delta value. When the end of the curve is reached, we update the control points of the <code>BezierCurve <\/code>class instance with the newly generated random control points, ensuring that the path is C1 continuous and stays in the scene bounds. The range of <code>x<\/code>, <code>y<\/code> and <code>z<\/code> coordinates, in which the control points are generated, was found experimentally.<\/p>\n\n\n\n<p>In the later stage of implementation &#8211; when I already aligned the model to the path &#8211; I faced the following problem: despite being C1 continuous, the path didn&#8217;t feel smooth. I minimized this by regenerating control points which are too close to each other.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Alignment and Rolling<\/h1>\n\n\n\n<p>The part I continued with was making Armadillo follow the path.<\/p>\n\n\n\n<p>At each frame, Armadillo is translated by the current point of the curve. Then I aligned the gaze of Armadillo with the current tangent of the curve as described in the specification 11 of the homework text. However, I faced the following problem: while following the path, Armadillo gradually &#8220;falls&#8221; to one side:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"637\" height=\"476\" src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image.png\" alt=\"\" class=\"wp-image-13\" srcset=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image.png 637w, https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-300x224.png 300w\" sizes=\"auto, (max-width: 637px) 100vw, 637px\" \/><\/figure>\n\n\n\n<p>The interesting part is that this issue wasn&#8217;t present when I was calculating <code>right<\/code> vector as a cross-product of the tangent and the world&#8217;s up, in contrast with calculating <code>right<\/code> as a cross-product of the tangent and the previous point&#8217;s up (the up vector calculated in the previous frame). Neither was this solution suitable as Armadillo was often flipping, while following the path.<\/p>\n\n\n\n<p>I decided to combine these two solutions: using world&#8217;s up by default and <code>prevUp<\/code> when the tangent and the world&#8217;s up are close to being parallel. This approach seemed to resolve the issue. Nevertheless, the ghost didn&#8217;t have this problem, so I used only <code>prevUp<\/code> in the final implementation.<\/p>\n\n\n\n<p>Alternating rolling motion was done using glm&#8217;s built-in quaternions.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Ghost<\/h1>\n\n\n\n<p>I designed ghost using five surfaces: four identical rotated surfaces and one <strong>concave <\/strong>bottom-surface (no holes in the mesh). Here are screenshots from MATLAB:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"475\" height=\"250\" src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/thumbnail_ghost-mesh-2.png\" alt=\"\" class=\"wp-image-14\" style=\"width:645px;height:auto\" srcset=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/thumbnail_ghost-mesh-2.png 475w, https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/thumbnail_ghost-mesh-2-300x158.png 300w\" sizes=\"auto, (max-width: 475px) 100vw, 475px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"457\" height=\"250\" src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/GetAttachmentThumbnail.png\" alt=\"\" class=\"wp-image-15\" style=\"width:645px;height:auto\" srcset=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/GetAttachmentThumbnail.png 457w, https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/GetAttachmentThumbnail-300x164.png 300w\" sizes=\"auto, (max-width: 457px) 100vw, 457px\" \/><\/figure>\n\n\n\n<p>Each surface was rendered separately using the pipeline implemented in the template code.<\/p>\n\n\n\n<p>s=t=1<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"307\" height=\"136\" src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-1.png\" alt=\"\" class=\"wp-image-16\" style=\"width:645px;height:auto\" srcset=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-1.png 307w, https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-1-300x133.png 300w\" sizes=\"auto, (max-width: 307px) 100vw, 307px\" \/><\/figure>\n\n\n\n<p>s=t=2<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"305\" height=\"137\" src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-2.png\" alt=\"\" class=\"wp-image-17\" style=\"width:645px;height:auto\" srcset=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-2.png 305w, https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-2-300x135.png 300w\" sizes=\"auto, (max-width: 305px) 100vw, 305px\" \/><\/figure>\n\n\n\n<p>s=t=3<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"298\" height=\"128\" src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-3.png\" alt=\"\" class=\"wp-image-18\" style=\"width:641px;height:auto\" \/><\/figure>\n\n\n\n<p>s=t=5<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"301\" height=\"117\" src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-4.png\" alt=\"\" class=\"wp-image-19\" style=\"width:645px;height:auto\" \/><\/figure>\n\n\n\n<p>s=t=10<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"291\" height=\"112\" src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-5.png\" alt=\"\" class=\"wp-image-20\" style=\"width:642px;height:auto\" \/><\/figure>\n\n\n\n<p>s=t=25<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"290\" height=\"104\" src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-6.png\" alt=\"\" class=\"wp-image-21\" style=\"width:645px;height:auto\" \/><\/figure>\n\n\n\n<p>s=t=50<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"294\" height=\"120\" src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-7.png\" alt=\"\" class=\"wp-image-22\" style=\"width:645px;height:auto\" \/><\/figure>\n\n\n\n<p>s=t=100<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"289\" height=\"98\" src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/image-8.png\" alt=\"\" class=\"wp-image-23\" style=\"width:645px;height:auto\" \/><\/figure>\n\n\n\n<p>Here is the final video showing all keyboard interactions:<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"476\" style=\"aspect-ratio: 636 \/ 476;\" width=\"636\" controls src=\"https:\/\/blog.metu.edu.tr\/e264325\/files\/2025\/04\/20250413-1719-08.9431575.mp4\"><\/video><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Conclusion<\/h1>\n\n\n\n<p>In overall, it was a very satisfying experience. Many thanks to O\u011fuz Hocam and Kadir Hocam for such a great learning opportunity. The template code was very helpful.<\/p>\n\n\n\n<p>Thanks for reading and see you in the upcoming homework!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Welcome, dear Computer Graphics enjoyers! In this blog, I will talk about some details of my implementation for CENG469 Computer Graphics II homework and the challenges I faced. Curved Path Generation I decided to start with this part as it seemed to be the easiest one. I implemented BezierCurve class. Throughout the whole program, I [&hellip;]<\/p>\n","protected":false},"author":9370,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[1],"tags":[],"class_list":["post-9","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blog.metu.edu.tr\/e264325\/wp-json\/wp\/v2\/posts\/9","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.metu.edu.tr\/e264325\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.metu.edu.tr\/e264325\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.metu.edu.tr\/e264325\/wp-json\/wp\/v2\/users\/9370"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.metu.edu.tr\/e264325\/wp-json\/wp\/v2\/comments?post=9"}],"version-history":[{"count":0,"href":"https:\/\/blog.metu.edu.tr\/e264325\/wp-json\/wp\/v2\/posts\/9\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.metu.edu.tr\/e264325\/wp-json\/wp\/v2\/media?parent=9"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.metu.edu.tr\/e264325\/wp-json\/wp\/v2\/categories?post=9"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.metu.edu.tr\/e264325\/wp-json\/wp\/v2\/tags?post=9"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}