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 just a binary form) which looks like the main today's choice. It can handle 3D model geometry, materials and textures, as well as animations, and is widely supported by various 3D editors, including Blender.
The topic is quite complex, so I had to resort to the tinygltf, a beautiful compact header-only library by Syoyo Fujita. It converts GLTF (GLB) file into JSON structure.
For my part, I added a set of related classes to engine/gltf, that are responsible for parsing and converting these JSON data into GL readable/renderable form - into VBOs, EBOs, VAOs, and so on, including new shaders for skinned mesh animations.
Download current project from GitHub link: https://github.com/bkantemir/_wg_409
This is how it looks like:
Pretty realistic, isn't it? Plus it is ANIMATED:
The car and Marlboro pack are from previous chapters, while the man is a nicely built animated GLB model by 360SMS.
This is how it is called in TheApp::getReady():
int rootNodeN = GLTFparser::loadModel(&sceneSubjs, NULL, NULL, filesRoot + "/dt/models/people/999_oldman.glb", "", pPBar); GLTFparser::loadAnimations(filesRoot + "/dt/models/people/999_oldman.glb", pPBar); pSS = sceneSubjs.at(rootNodeN); pSS->scaleMe(7); v3set(pSS->ownCoords.pos, -4, pTable->groundLevel, 0); pSS->ownCoords.setEulerDg(0, -30, 0); GLTFnode* pN0 = (GLTFnode*)sceneSubjs.at(rootNodeN + 1); GLTFnode::startAnimation(pN0, 0, 2); // 2-back-and-forth
First 2 lines are loading the model and animation, the last 2 lines - assigning the animation to the model and starting it.
Another important addition here is an engine/TheTable class, which describes the "game table" 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:
- Camera::reset(..)
- Shadows::resetShadowsFor(..)
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'll use them often. Although having such an option certainly won’t hurt..