{"id":2287,"date":"2023-09-26T00:33:43","date_gmt":"2023-09-26T00:33:43","guid":{"rendered":"https:\/\/writingagame.com\/?p=2287"},"modified":"2024-02-06T19:53:08","modified_gmt":"2024-02-06T19:53:08","slug":"chapter-9-gltf-glb-format","status":"publish","type":"post","link":"https:\/\/writingagame.com\/index.php\/2023\/09\/26\/chapter-9-gltf-glb-format\/","title":{"rendered":"Chapter 9. GLTF\/GLB format"},"content":{"rendered":"\n<p>We now have a <strong>graphics engine<\/strong> capable of generating and displaying 3D models. However, it uses its own model format (XML files). Of course, it would be great to use other (standard) 3D formats as well, that can be downloaded from the Internet. <\/p>\n\n\n\n<p>After some research I settled on <strong>GLTF\/GLB <\/strong>(GL Transfer Format, GLB is just a binary form) which looks like the main today&#8217;s choice. It can handle 3D model geometry, materials and textures, as well as animations, and is widely supported by various 3D editors, including <em>Blender<\/em>.<\/p>\n\n\n\n<p>The topic is quite complex, so I had to resort to the <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/syoyo\/tinygltf\" target=\"_blank\">tinygltf<\/a>, a beautiful compact header-only library by <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/syoyo\" data-type=\"link\" data-id=\"https:\/\/github.com\/syoyo\" target=\"_blank\">Syoyo Fujita<\/a>. It converts GLTF (GLB) file into JSON structure.<\/p>\n\n\n\n<p>For my part, I added a set of related classes to <em>engine\/gltf<\/em>, that are responsible for parsing and converting these JSON data into GL readable\/renderable form &#8211; into VBOs, EBOs, VAOs, and so on, including new shaders for skinned mesh animations.<\/p>\n\n\n\n<p>Download current project from&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/writingagame.com\/index.php\/2023\/05\/11\/github\/\" target=\"_blank\">GitHub<\/a> link:&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/bkantemir\/_wg_409\" target=\"_blank\">https:\/\/github.com\/bkantemir\/_wg_409<\/a><\/p>\n\n\n\n<p>This is how it looks like:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b04\/c09\/01.jpg\"><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Pretty realistic, isn&#8217;t it? Plus it is ANIMATED:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<iframe loading=\"lazy\" width=\"100%\" height=\"400\" src=\"https:\/\/www.youtube.com\/embed\/G-d1Yq5xeag?controls=0&amp;autoplay=1&amp;loop=1&amp;playlist=G-d1Yq5xeag\" title=\"GLTF demo\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen=\"\"><\/iframe>\n\n\n\n<p><\/p>\n\n\n\n<p>The car and Marlboro pack are from previous chapters, while the man is a nicely built animated GLB  model by <a rel=\"noreferrer noopener\" href=\"https:\/\/sketchfab.com\/360SMS\" data-type=\"link\" data-id=\"https:\/\/sketchfab.com\/360SMS\" target=\"_blank\">360SMS<\/a>.<\/p>\n\n\n\n<p>This is how it is called in <em>TheApp::getReady()<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-syntaxhighlighter-code\">    int rootNodeN = GLTFparser::loadModel(&amp;sceneSubjs, NULL, NULL, filesRoot + \"\/dt\/models\/people\/999_oldman.glb\", \"\", pPBar);\n    GLTFparser::loadAnimations(filesRoot + \"\/dt\/models\/people\/999_oldman.glb\", pPBar);\n    pSS = sceneSubjs.at(rootNodeN);\n     pSS->scaleMe(7);\n    v3set(pSS->ownCoords.pos, -4, pTable->groundLevel, 0);\n    pSS->ownCoords.setEulerDg(0, -30, 0);\n    GLTFnode* pN0 = (GLTFnode*)sceneSubjs.at(rootNodeN + 1);\n    GLTFnode::startAnimation(pN0, 0, 2); \/\/ 2-back-and-forth<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>First 2 lines are loading the model and animation, the last 2 lines &#8211; assigning the animation to the model and starting it.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>Another important addition here is an <em>engine\/<\/em><strong><em>TheTable<\/em>  <\/strong>class, which describes the &#8220;game table&#8221; or game space (world), the rectangular area where all the action will ultimately take place. It helps to calculate visible\/renderable area, which allows to calculate the best reasonable z-buffer depth for rendering and for shadow mapping. Functions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Camera::reset(..)<\/li>\n\n\n\n<li>Shadows::resetShadowsFor(..)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>However, there is one problem: the huge file size. This sample has 2.5 MB (which is actually not that much compared to other models). So I doubt I&#8217;ll use them often. Although having such an option certainly won\u2019t hurt..<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p class=\"mb-2\">We now have a graphics engine capable of generating and displaying 3D models. However, it uses its own model format (XML files). Of course, it would be great to use other (standard) 3D formats as well, that can be downloaded from the Internet. After some research I settled on GLTF\/GLB (GL Transfer Format, GLB is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2294,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-2287","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cross-platform-3d"],"_links":{"self":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/2287","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/comments?post=2287"}],"version-history":[{"count":24,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/2287\/revisions"}],"predecessor-version":[{"id":2378,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/2287\/revisions\/2378"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/media\/2294"}],"wp:attachment":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/media?parent=2287"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/categories?post=2287"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/tags?post=2287"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}