dev.nlited.com

>>

Importing Models

<<<< prev
next >>>>

2017-12-01 02:25:30 chip Page 2075 📢 PUBLIC

Nov 30 2017

Tiger tank model

Today's task is to load a "real" 3D model.

I downloaded a free model of a German Tiger tank and saved it in Tutorials\Models\Tank\Tiger\. The zipfile contained the model in various formats and the textures as a collection of BMP bitmaps. The ".obj" is a text file containing all the vertices, faces, and texture maps and is the lingua franca that is best supported by the tools.

DirectXMesh is a project by Chuck Walbourn (the author of DirectXTK) to convert OBJ files to binary-optimized CMO, VBO, or SDKMESH files that can be loaded directly into a DirectXTK Model object. I cloned the git repo into DirectX/DX11/DirectXMesh/:
git clone https://github.com/Microsoft/DirectXMesh.git .
The solution contains two projects, the DirectXMesh library and a command line utility meshconvert. Both projects built (using the DirectXMesh_Desktop_2015 target) without any problems. I copied meshconvert.exe to a convenient location (DirectX/Bin/).

I converted the Tiger.obj file to Tiger.sdkmesh:
meshconvert -n -y Tiger.obj
The -n creates the vertex normals. -y overwrites any existing file.

I didn't want to spend much time, if any, writing new code for this experiment so I leveraged the RenderModel example from the DirectXTK tutorials. I simply copied Tiger.sdkmesh into the source directory with cup._obj and replaced "cup.cmo" with "Tiger.sdkmesh" in the code.
//m_model= Model::CreateFromCMO(m_d3dDevice.Get(),L"cup.cmo",*m_fxFactory); m_model= Model::CreateFromSDKMESH(m_d3dDevice.Get(),L"Tiger.sdkmesh",*m_fxFactory);

A quick scan of the original Tiger.obj file let me know that the vertices were generally in the range of +/- 2000. I updated the camera location and projection values to move the camera outside the model and make sure the model was within the clipping planes. The model is centered on (0,0,0).
// TODO: Initialize windows-size dependent objects here. m_view= Matrix::CreateLookAt(Vector3(2500.0f,2500.0f,2500.0f),Vector3::Zero,Vector3::UnitY); m_proj= Matrix::CreatePerspectiveFieldOfView(XM_PI/4.0f,float(backBufferWidth)/float(backBufferHeight),100.0f,5000.0f);

I recompiled the project, ran it, and saw nothing but cauliflower blue. :(

There were no error messages or warnings, and the program was happily rendering 60 frames per second. The number of things that could be wrong are legion:

I spent quite a while playing around with the camera position and FoV parameters without any hint. I removed the textures from the problem by setting the wireframe flag in the model->Draw() call.

Then I remembered the problems I had turning on the lights (Direct3D Lighting). The model simply disappeared when I tried to enable lights without setting the input layout correctly. I commented out the code that enabled the lighting and fog effects and was rewarded with a spinning wireframe tank! It even rendered as a solid (with no texture)!


NoLights: m_model= Model::CreateFromSDKMESH(m_d3dDevice.Get(),L"Tiger.sdkmesh",*m_fxFactory); m_world= Matrix::Identity; #if 0 m_model->UpdateEffects([](IEffect *effect) { auto lights= dynamic_cast<IEffectLights*>(effect); if(lights) { lights->SetLightingEnabled(true); lights->SetPerPixelLighting(true); lights->SetLightEnabled(0,true); lights->SetLightDiffuseColor(0,Colors::Gold); lights->SetLightEnabled(1,false); lights->SetLightEnabled(2,false); } auto fog= dynamic_cast<IEffectFog*>(effect); if(fog) { fog->SetFogEnabled(true); fog->SetFogColor(Colors::CornflowerBlue); fog->SetFogStart(3.0f); fog->SetFogEnd(4.0f); } }); #endif

Direct3D simple grid Direct3D simple grid

Comparing the Tiger.obj file to the simple Cup._obj file from the RenderModel example makes me think the Tiger model is not complete. The textures are present but not linked into the model. The cup has a "mtllib" line that references the "cup.mtl" file, which contains a reference to the image file "cup.jpg". The Tiger file has no mtllib line and the texture file names do not appear anywhere in the file. This makes me think I need to use some external CAD program (Blender? Alibre?) to attach one of the skins to the model.

Braynzarsoft.net has a tutorial explaining how to read an OBJ model directly.

Rather than diving into the gory details of writing yet another OBJ parser or learning how to use a CAD program, I am trying another model. I can buy a small model with the assumption that a commercially produced model will be more complete, or I can try another free one.

This firetruck model compiled using meshconvert and crashed during load with
"EffectFactory could not find texture file 'Opengreen.dds'"
There is a file named "Opengreen.tga" in the model package.

I built texconv, converted OpelGreen.tga to OpelGreen.dds
texconv OpenGreen.tga
and copied OpelGreen.dds to the RenderModel directory. Repeated this for "aufbau_dl_rund.jpg", "kotfluegel_lf_rund.jpg", "reifen.tga", "kasten_dl.jpg", "leiter_park.jpg", "kabine_dl_rund.jpg", "geraete.tga", "details_dl_rund.tga". I was rewarded with a skinned but slightly messed up firetruck.

Direct3D simple grid

This proves that I can read textured models. I need to run meshconvert on the OBJ to generate the SDKMESH (vertices, normals, faces, and texture references), texconv on each referenced texture image to generate the DDS, and copy the SDKMESH and DDS files into the working directory.

Using the dl_rund.obj firetruck as a guide, I revisted my original Tiger model and hacked the OBJ file (all source data files should be text!). First I created a new "Tiger_Snow.mtl" materials file, copying from dl_run.mtl. The fact that all the parts use the same values tells me the information is about color and not space. Reading the Braynzarsoft tutorial confirms this. "K" is color information, "Ka" is ambient color, "Kd" is diffuse color, "Ks" is specular color, and "Ns" is specular strength. The "map_Kd" is the reference to the diffused color texture map. The texture maps are stored separately from the mesh definition, so the path in the map_Kd line should be the relative path from the working directory when my program is running. I am putting everything in the same directory to make life simpler during these experiments.

Tiger_Snow.mtl: newmtl MG_Body Ka 0.501961 0.501961 0.501961 Kd 1.000000 1.000000 1.000000 Ks 0.000000 0.000000 0.000000 Ns 781.250000 map_Kd MG_body.bmp newmtl Tank_Body Ka 0.501961 0.501961 0.501961 Kd 1.000000 1.000000 1.000000 Ks 0.000000 0.000000 0.000000 Ns 781.250000 map_Kd Tank_Body_Snow.bmp newmtl Track Ka 0.501961 0.501961 0.501961 Kd 1.000000 1.000000 1.000000 Ks 0.000000 0.000000 0.000000 Ns 781.250000 map_Kd Track.bmp

I add the reference to the new material library to the top of the Tiger.obj file:
mtllib Tiger_Snow.mtl
Then I search the OBJ file for all lines beginning with "usemtl" and make sure I have a matching "newmtl" section in the library.

I rebuild the sdkmesh file:
meshconvert Tiger.obj
Convert all the referenced texture files:
texconv tex\MG_body.bmp texconv tex\Tank_Body_Snow.bmp texconv tex\Track.bmp
Note that the original BMP textures are in a tex subdirectory while the converted DDS files are written to the current directory. I then copy the mesh "Tiger.sdkmesh" and all the DDS files (*.DDS) to the RenderModel directory.

I changed the model name back to "Tiger.sdkmesh" and now I have a fully realized Tiger!

Direct3D simple grid  Direct3D simple grid 

Unfortunately, meshconvert does not preserve the path to the texture file and DirectXTK EffectFactory only looks in the current directory which forces me to put everything in the working directory. I will need to modify EffectFactory.cpp to let me specify a path to the DDS files.

This provides my "Known Good Reference" point to start exploring. I was able to enable the lighting model, it was the fog effect that was causing problems. This was because the original "cup" model was scaled to 1.0 while the Tiger is about 2000 units long. I moved the fog parameters out to SetFogStart(100.0f) and SetFogEnd(5000.0f) and the Tiger emerged.

Direct3D Models


Models

Now I just need a model that works...

Mars rover $5.00
Unity3D mars rover
Tanks $16.09
CGTrader tangs
Colony Structures $24.50
CGTrader Colony Structures
Colony Structures $26.60
Colony structures

The prices at CGTrader change every time I look at the page.



WebV7 (C)2018 nlited | Rendered by tikope in 107.470ms | 3.147.205.19