left-icon

Direct3D Succinctly®
by Chris Rose

Previous
Chapter

of
A
A
A

CHAPTER 5

Loading a Model

Loading a Model


Hand coding models is not difficult if the models are very simple, like the triangle from the previous chapter. Using this technique to create complex models is not practical. It is far better to create models using a 3-D modeling application. The examples in this book were created using Blender 2.66, which is an open source 3-D modeling application available from http://www.blender.org/. Models can be created using Blender, or many other 3-D modelers, and exported to various 3-D file formats. The files can then be loaded into our applications. This allows for much more complex models since visually creating models is far simpler than working with the vertices themselves.

Object Model File Format

There are many 3-D file formats, each having advantages and disadvantages over the others. In this chapter, we will examine a simple but flexible format that is fairly universal and standardized. It is called the object file format, and it was originally developed by Wavefront Technologies. Object files have an “obj” file extension. We will write a class that parses object files and creates meshes from the vertex information in them.

Note: A mesh is a collection of triangles that forms a 3-D model. Mesh and model are interchangeable terms in the current context. In past versions of DirectX there was a mesh interface, but DirectX 11 does not contain this interface, so meshes must be loaded and manipulated manually. This is a little extra work, but it is a lot more flexible.

There are several advantages to the object file format. It is plain text and easy to read and parse. The files are human readable and writable; they are not binary. Human readable plaint text requires more storage space and is generally slower for the computer to parse than binary formats. For instance, the value 3.14159f takes 8 bytes in plaint text, but only 4 bytes in binary as a 32 bit float. The size of the data is negligible for the small models we will be working with, as is the time the CPU needs to parse the text into variables. For larger projects where the models are more complicated or there are a lot of them, you might think about either using a binary file format or writing your own format.

The file format we will be using is also a simplified version of the entire object file specification. We will write a class that loads only object files specifically designed for it. Object file parsers can be written to ignore any of the unknown syntaxes within the file. We can write an object file with texture coordinates and normal information, along with the vertex positions, and our program can ignore whatever specifications it does not need until we examine texturing and lighting.

Another downside to the format is that the vertex buffers are not indexed in an efficient manner. In a previous book, we looked at using index buffers to reference vertices multiple times on the GPU and it saved us some GPU memory. The method we will be examining is not recommended for complex geometry, because without using an indexed topology, the GPU must store many times more vertices than is actually necessary. For instance, we need only 8 vertices to store a cube on the GPU. We can efficiently index the vertices using an index buffer. However, the object files we will be loading store a cube as 12 vertices: 3 vertices per triangle, 2 triangles per face, and 6 faces.

Note: When you feel comfortable with this simple text based OBJ format, you could develop your own format specifically for storing the models in a manner best suiting the unique circumstance. We are examining the OBJ file format as an example of reading basic models. You can easily write your own custom 3-D file format which stores the information exactly as you need it, and which is far smaller and faster to parse than the OBJ format.

Adding a Model to the Project

Object files are stored using a small scripting language with a very simple syntax. It is a plain text file with lists or arrays of vertex positions and other information. Each element of the arrays is specified on its own line. There are arrays of vertex positions, texture coordinates, vertex normal, and faces. A face in this context is a flat surface. Faces are defined by a collection of indices that reference values in each of the arrays (the vertex position, texture coordinate, or normal arrays). A face definition can reference any of the values in each of the arrays, allowing for great flexibility. There are many other keywords that can be used in object files. The following is only a brief description of the ones we will be using in our program.

Spaceship in Blender

Figure 5.1: Spaceship in Blender

Figure 5.1 is a cropped screen shot of the spaceship model we will load as it appears in Blender. You can see a light source and a camera as well as the model. The light source and camera will not be exported to the object file, only the spaceship itself.

The following code is the object file for the spaceship in Figure 5.1 as exported by Blender 2.66. The spaceship model is very simple, but even this simple mode creates a rather lengthy object file. The following code table shows the code for the spaceship.

# Blender v2.66 (sub 0) OBJ File: 'spaceship.blend'

# www.blender.org

v 0.245036 -0.277313 -3.008238

v 1.000000 -0.277313 0.638722

v -1.000000 -0.277313 0.638721

v -0.245036 -0.277313 -3.008238

v 0.332394 0.200748 -0.653899

v 0.999999 0.200748 0.638722

v -1.000000 0.200748 0.638721

v -0.332394 0.200748 -0.653899

v 0.924301 -0.171645 0.476444

v 0.294592 -0.171645 -1.523556

v 2.173671 -0.171645 0.066711

v 2.173671 -0.171645 0.476444

v 0.924301 -0.071908 0.476444

v 0.294592 -0.071908 -1.523556

v 2.173671 -0.071908 0.066711

v 2.173671 -0.071908 0.476444

v -0.921304 -0.073625 0.467630

v -0.288946 -0.073625 -1.532370

v -2.170674 -0.073627 0.057897

v -2.170674 -0.073627 0.467630

v -0.921304 -0.173363 0.467630

v -0.288946 -0.173363 -1.532370

v -2.170674 -0.173364 0.057897

v -2.170674 -0.173364 0.467630

vt 0.585247 0.203295

vt 0.000325 0.320701

vt 0.000323 0.000323

vt 0.800338 0.208366

vt 0.693343 0.208366

vt 0.585894 0.000324

vt 0.606542 0.475453

vt 0.219632 0.475452

vt 0.027282 0.321348

vt 0.929796 0.869160

vt 0.929795 0.946102

vt 0.607903 0.869160

vt 0.007848 0.968632

vt 0.000323 0.892059

vt 0.607257 0.968632

vt 0.585894 0.213707

vt 0.972548 0.227766

vt 0.972548 0.306642

vt 0.607189 0.747112

vt 0.810796 0.747112

vt 0.608702 0.773718

vt 0.577718 0.698455

vt 0.577718 0.477807

vt 0.606542 0.476099

vt 0.465133 0.534562

vt 0.399188 0.534562

vt 0.399188 0.518510

vt 0.557042 0.517863

vt 0.400036 0.517863

vt 0.399188 0.497305

vt 0.819439 0.606656

vt 0.999676 0.321348

vt 0.999677 0.717546

vt 0.626993 0.719207

vt 0.607189 0.656306

vt 0.818792 0.658818

vt 0.607189 0.719854

vt 0.810834 0.719854

vt 0.812349 0.746465

vt 0.830351 0.868513

vt 0.609613 0.868513

vt 0.828641 0.839677

vt 0.531725 0.534562

vt 0.465780 0.534562

vt 0.531725 0.518510

vt 0.399188 0.476099

vt 0.556194 0.476099

vt 0.557042 0.496658

vt 0.153905 0.688352

vt 0.439413 0.868513

vt 0.000323 0.818146

vt 0.000323 0.495980

vt 0.063200 0.476099

vt 0.060943 0.687706

vt 0.584527 0.121258

vt 0.907786 0.000323

vt 0.000323 0.393413

vt 0.607903 0.946102

vt 0.233352 0.869160

vt 0.585894 0.320701

vt 0.812309 0.773718

vt 0.606542 0.696746

vt 0.465133 0.518510

vt 0.556194 0.497305

vt 0.949339 0.760147

vt 0.818792 0.321348

vt 0.608703 0.746465

vt 0.607903 0.839677

vt 0.465780 0.518510

vt 0.400036 0.496658

vt 0.042889 0.868513

vt 0.398542 0.687706

vn 0.000000 -1.000000 -0.000000

vn -0.000000 1.000000 0.000000

vn 0.757444 0.633792 -0.156800

vn -0.000000 -0.000001 1.000000

vn -0.979238 -0.000001 -0.202714

vn 0.000000 0.980001 -0.198995

vn -0.953839 0.000000 0.300320

vn 0.646008 0.000000 -0.763331

vn 1.000000 -0.000000 0.000000

vn 0.000000 0.000000 1.000000

vn 0.953476 0.000000 0.301469

vn -0.645477 0.000000 -0.763779

vn -1.000000 -0.000000 -0.000000

vn -0.000001 1.000000 -0.000000

vn 0.000001 -1.000000 0.000000

vn 0.888496 0.000002 -0.458885

vn -0.382358 0.902665 -0.197479

s off

f 1/1/1 2/2/1 3/3/1

f 5/4/2 8/5/2 7/6/2

f 1/7/3 5/8/3 2/9/3

f 2/10/4 6/11/4 3/12/4

f 3/13/5 7/14/5 4/15/5

f 5/16/6 1/17/6 4/18/6

f 13/19/7 14/20/7 9/21/7

f 14/22/8 15/23/8 11/24/8

f 15/25/9 16/26/9 12/27/9

f 16/28/10 13/29/10 9/30/10

f 9/31/1 10/32/1 11/33/1

f 16/34/2 15/35/2 13/36/2

f 21/37/11 22/38/11 18/39/11

f 22/40/12 23/41/12 18/42/12

f 23/43/13 24/44/13 19/45/13

f 24/46/10 21/47/10 17/48/10

f 17/49/14 18/50/14 20/51/14

f 24/52/15 23/53/15 21/54/15

f 4/55/1 1/1/1 3/3/1

f 6/56/2 5/4/2 7/6/2

f 5/8/16 6/57/16 2/9/16

f 6/11/10 7/58/10 3/12/10

f 7/14/17 8/59/17 4/15/17

f 8/60/6 5/16/6 4/18/6

f 14/20/7 10/61/7 9/21/7

f 10/62/8 14/22/8 11/24/8

f 11/63/9 15/25/9 12/27/9

f 12/64/10 16/28/10 9/30/10

f 12/65/1 9/31/1 11/33/1

f 15/35/2 14/66/2 13/36/2

f 17/67/11 21/37/11 18/39/11

f 23/41/12 19/68/12 18/42/12

f 24/44/13 20/69/13 19/45/13

f 20/70/10 24/46/10 17/48/10

f 18/50/14 19/71/14 20/51/14

f 23/53/15 22/72/15 21/54/15

There are several methods for adding this code to your project. You could add a text file to your solution and copy the above code, but usually models are added as references to external files. Copy the above code and save it to a text file called spaceship.obj. Right-click on the project name in the solution explorer and select Add existing item. Find the spaceship.obj file and add it to the project.

Visual Studio will assume the file is a regular relocatable machine code object file, because of the obj extension. This is no good, our file is a model, and it is not a binary code file. Right-click on the spaceship.obj file in your solution explorer and select Properties from the context menu. You will see the file properties form where you can change the Item Type value from Object to Text (see Figure 5.2).

Change Object File Item Type

Figure 5.2: Change Object File Item Type

If you do not change the file type, Visual Studio will think the file is corrupted, as it clearly does not contain the information that a standard binary object file should contain. Click Apply after you change the item type setting, then click OK.

OBJ File Syntax

Comments: Any line that begins with the cross hatch or hash symbol (#) is a comment. The first line in the spaceship.obj file is a comment that Blender 2.66 wrote to identify the modelling application and the second line is a comment with Blender’s website.

Vertices: Lines beginning with the “v” keyword specify vertex positions. The spaceship.obj file above has the vertices specified directly after the initial comments, but the actual order is irrelevant. Vertices could be mixed in with faces, normal, and texture coordinates. The “v” is followed by a space delimited series of three or four floating point values. The values specify the location of the vertex in 3-D space using the order X, Y, Z with an optional W component. For instance, the following specification is a vertex positioned at X=0.245036; Y=-0.277313; and Z=-3.008238:

v 0.245036 -0.277313 -3.008238

If there is a W component, our model reader will ignore it. The W is usually included to assist in matrix multiplication and other manipulations. Modern computers process four floating point values as easily as three, since they do so in a SIMD manner. If the W component is included, it will almost always be set to either all 1.0f or all 0.0f.

Texture Coordinates: Texture coordinates are specified using the “vt” keyword. The “vt” is followed by two or three values that represent U, V, and the optional W coordinate of the texture. For our purposes, textures use only the (U, V) coordinates, and they will be standard normalized UV texture space. These values will range from 0.0f to 1.0f. We will look in detail at UV coordinates and texturing later. The texture coordinates have been included in this file, even though we will not wrap a texture around our model in this chapter. The following line specifies a texture coordinate with U=0.585247 and V=0.203295:

vt 0.585247 0.203295

Vertex Normals: Vertex normals are specified using the “vn” keyword. The “vn” is followed by three floating point values delimited with spaces. We will examine what normals are and a very common use of them when we look into lighting a little later. The values are in the order (X, Y, Z) so the following line specifies a normal which points in the direction of X=0.757444; Y=0.633792; and Z=-0.156800:

vn 0.757444 0.633792 -0.156800

The values from a normal definition in the object file format specify a vertex normal, or the direction in which a vertex is pointing. They are not face or surface normals. The value is normalized and will define a normal with length 1.0f. A common strategy for extracting a face normal from a collection of vertex normals is to average the normals of the vertices that define the face. The normalized average of the vertex normals is used as the face normal.

Faces: Faces are defined on lines beginning with the “f” keyword. Lines beginning with the “f” keyword can be broken into space delimited vertices, each described with a slash delimited list of references into the above mentioned arrays. The order that attributes are defined is position, texture, and normal. A face can be described using three or more of these specifications, but for our purposes we will assume all faces are triangles. That means there will be three specifications per “f” keyword:

f 16/34/2 15/35/2 13/36/2

The above line specifies three vertices, each with its own position, texture coordinate, and normal. These vertices create a single 3-D triangle in our model. The first element, which I have colored blue, 16/34/2, means the 16th vertex position, the 34th texture coordinate, and the 2nd normal specified.

Note: The indices reference the arrays using a “1” based counting system. The first element in each array has a subscript of 1. C++ references arrays use a “0” based system, so when our program reads these lines, we must can subtract one from each index to convert between the two systems. Alternatively, we could add a dummy value to the C++ arrays at position 0, which is never referenced by the faces.

Note: Object files can be accompanied by a material file with an MTL extension. This file describes the material used by each of the objects described in the OBJ file. For our purposes, the materials will be hardcoded except for the UV texture coordinates.

Blender Export Settings

If you are using Blender 2.66, or a similar version with the same OBJ exporter, you might like to export your own models with the same settings as I have used to export this spaceship. Selecting similar options for an OBJ file export will create models that can be loaded using our ModelReader class. Figure 5.3 shows a screen shot of the Blender OBJ exporter. The left panel is where these settings are changed.

 Setting OBJ Model Export Options

Figure 5.3: Setting OBJ Model Export Options

The following table (Table 5.1) shows the settings I chose to export the spaceship model.

Table 5.1: Blender OBJ Export Settings

Setting

Value

Selection Only

False

Animation

False

Apply Modifiers

False

Include Edges

False

Include Normals

True

Include UVs

True

Write Materials

False

Triangulate Faces

True

Write Nurbs

False

Polygroups

False

Objects as OBJ Objects

False

Objects as OBJ Groups

False

Material Groups

False

Keep Vertex Order

False

Scale

1.00

Forward

-Z Forward

Up

Y Up

Path Mode

Auto

Note: Object files can contain more than one object. In our example, there is only the spaceship model, but the format allows for many models to be defined in a single file. Each object in a file is given a name, and each object has its own list of vertices, normals, texture coordinates, and faces. If there is more than one object, each is specified after the “o” keyword. The “o” keyword is followed by the particular object’s name. All vertex information until the next “o“ keyword correspond to the last named object.

Note: The OBJ file syntax allows for nontriangular faces to be specified. For instance, square faces can be constructed using four vertices, or pentagonal faces can be made from five. This format allows for more succinct face definitions. When a model is loaded using this capability, the faces must be converted to a collection of triangles, since DirectX renders meshes using triangles lists. In the following examples, I have assumed the faces are all triangles and I have exported models using the “Triangulate Faces” option that will be available in many 3-D modeling applications.

Model Class

Now that we have examined the basics of the object file format, we can write a class that loads and parses these files to create the mesh for a Model object in our application. I have called the new class ModelReader, and it can be added to the project as we left it at the end of the previous chapter. Add two files to your project, ModelReader.h and ModelReader.cpp. The following two code tables show the code for this new class.

// ModelReader.h

#pragma once

#include <Windows.h>

#include <string>

#include "Model.h"

using namespace DirectX;

class ModelReader

{

     // Reads and returns the data from a text file in the current folder

     // this method also returns the size of the file in bytes

     static char* ReadFile(char* filename, int& filesize);

     

     // Methods for reading an int or float from a string

     static float ReadFloat(std::string str, int &start);

     static int ReadInt(std::string str, int &start);

public:

     static Model* ReadModel(ID3D11Device* device, char* filename);

     

     static std::string ReadLine(char* data, int length, int &start);

};

// ModelReader.cpp

#include "pch.h"

#include "ModelReader.h"

#include <fstream>

#include <vector>

using namespace DirectX;

// Reads a 32 bit float from a substring starting from character index &start

float ModelReader::ReadFloat(std::string str, int &start)

{

std::string t;

while(str.data()[start] != ' ' && str.data()[start] != '/' &&

     str.data()[start] != '\n' && start < (int) str.length())

     t.push_back(str.data()[start++]);

     

start++;

// Parse to float and return

return (float)atof(t.data());

}

// Reads an int from a substring starting from the character index &start

int ModelReader::ReadInt(std::string str, int &start)

{

std::string t;

while(str.data()[start] != ' ' && str.data()[start] != '/' &&

     str.data()[start] != '\n' && start < (int) str.length())

     t.push_back(str.data()[start++]);

start++;

// Parse to int and return

return atoi(t.data());

}

char* ModelReader::ReadFile(char* filename, int &filesize)

{

filesize = 0;

std::ifstream filestream;

// Open the file for reading

filestream.open(filename, std::ifstream::in);

// If the file could not be opened, return NULL

if(!filestream.is_open()) return NULL; // The file could not be opened

// Find the file's length

filestream.seekg(0, std::ios::end);

filesize = (int) filestream.tellg();

// Allocate space for the file's data in RAM

char* filedata = new char[filesize]; // Throws bad_alloc if there's problems

// Read the data from the file into the array

filestream.seekg(0, std::ios::beg);   // Reset the file back to the start

filestream.read(filedata, filesize); // Read the whole file

filestream.close();

return filedata;

}

Model* ModelReader::ReadModel(ID3D11Device* device, char* filename)

{

// Read the file

int filesize = 0;

char* filedata = ReadFile(filename, filesize);

// Parse the data into vertices and indices

int startPos = 0;

std::string line;

std::vector<float> vertices;

std::vector<int> vertexIndices;

int index; // The index within the line we're reading

while(startPos < filesize) {

     line = ReadLine(filedata, filesize, startPos);

     if(line.data()[0] == 'v' && line.data()[1] == ' ')

          {

          index = 2;

          // Add to vertex buffer

          vertices.push_back(ReadFloat(line, index)); // Read X

          vertices.push_back(ReadFloat(line, index)); // Read Y

          vertices.push_back(ReadFloat(line, index)); // Read Z

          // If there's a "W" it will be ignored

          }

     else if(line.data()[0] == 'f' && line.data()[1] == ' ')

          {

          index = 2;

          // Add triangle to index buffer

          for(int i = 0; i < 3; i++)

               {

               // Read position of vertex

               vertexIndices.push_back(ReadInt(line, index));

               

               // Read and ignore the texture and normal indices:

               ReadInt(line, index);

               ReadInt(line, index);

               }

          }

     }

delete[] filedata;   // Deallocate the file data

// Subtract one from the vertex indices to change from base 1

// indexing to base 0:

for(int i = 0; i < (int) vertexIndices.size(); i++)

     {

     vertexIndices[i]--;

     }

     

// Create a collection of Vertex structures from the faces

std::vector<Vertex> verts;

int j = vertexIndices.size();

int qq = vertices.size();

for(int i = 0; i < (int) vertexIndices.size(); i++)

     {

     Vertex v;

     

     // Create a vertex from the referenced positions

     v.position = XMFLOAT3(

          vertices[vertexIndices[i]*3+0],

          vertices[vertexIndices[i]*3+1],

          vertices[vertexIndices[i]*3+2]);

     // Specify random colors for our vertices:

     v.color = XMFLOAT3(

          (float)(rand()%10) / 10.0f,

          (float)(rand()%10) / 10.0f,

          (float)(rand()%10) / 10.0f

          );

     verts.push_back(v); // Push to the verts vector

     }

// Create a an array from the verts vector.

// While we're running through the array reverse

// the winding order of the vertices.

Vertex* vertexArray = new Vertex[verts.size()];

for(int i = 0; i < (int) verts.size(); i+=3)

     {

     vertexArray[i] = verts[i+1];

     vertexArray[i+1] = verts[i];

     vertexArray[i+2] = verts[i+2];

     }

// Construct the model

Model* model = new Model(device, vertexArray, verts.size());

// Clear the vectors

vertices.clear();

vertexIndices.clear();

verts.clear();

// Delete the array/s

delete[] vertexArray;

return model; // Return the model

}

// This method reads and returns a single '\n' delimited line

// from the *data array beginning at the index start. It reads

// the line and advances the start index.

std::string ModelReader::ReadLine(char* data, int length, int &start)

{

std::string str;

int index = 0;

while(data[start] != '\n')

     {

     // Ignore whitespace at the start of the string:

     if((data[start] == ' ' || data[start] == '\t') && index == 0)

          {

          start++;

          if(start == length) break;

          else continue;

          }

     

     index = 1;

     str.push_back(data[start++]);

     if(start == length) break;

     }

start++;

return str;

}

The ModelReader class is designed to be used statically; models are read from files using the ReadModel method. It is a helper class that loads text from a file and parses it into a simple array of Vertex structures, which are then used to generate a Model object. The spaceship.obj file contains texture coordinates and normal, but these are presently ignored by ModelLoader, and only the vertex positions are read from the file. The ReadModel method returns a new Model object that has the vertices specified in the file. At present, our vertex structure (defined in the Model class) contains positions as well as colors. We will look at texturing shortly, but for the moment I have used the rand() method to generate random colors and ignored the UV coordinates. This will allow us to see our object’s shape without reading and mapping the texture.

There are a few interesting things to note about the code for the ModelReader::ReadModel method that may help you write a custom model reading class. It reads the model’s vertices into a std::vector because we do not know how many vertices are in the file and they are dynamically sized. After the vertices and indices are read from the file, all the indices must be reduced by 1, because OBJ files use a base 1 counting system to reference elements in the arrays, and C++ uses a base 0 counting system as mentioned.

After this, I have made an additional temporary vector called verts, which is used to convert the separate arrays of positions, UV’s, and normal into instances of our Vertex structure. This step and the next could be combined into a single for loop. I have kept them separate for clarity in the example code.

Finally, something to be very careful of is the winding order of the 3-D program and the 3-D file format. DirectX uses a clockwise winding order to know which face is the front and which face is the back for each of the triangles in a mesh. The OBJ file format uses the reverse, a counter-clockwise winding order. For this reason, if we wish to render the OBJ file properly, we must reverse the winding order of the triangles. This is a simple matter of swapping any two of the points that create each triangle. I chose to swap them during the for loop of the final copy from the verts std::vector to the Vector structure array. If we do not do this, DirectX will think the backs of the triangles are facing the viewer, and it will cull the triangles and render black for the model.

To load a model, first include the ModelReader.h header in the SimpleTextRenderer.h file, see the following code table.

// SimpleTextRenderer.h

#pragma once

#include "DirectXBase.h"

#include "Model.h"

#include "VertexShader.h"

#include "PixelShader.h"

#include "ModelReader.h"

// This class renders simple text with a colored background.

ref class SimpleTextRenderer sealed : public DirectXBase

In the SimpleTextRenderer::LoadDeviceResources method of the SimpleTextRenderer.cpp file, we can create our model. I have removed the code that we used to hard code our triangle and replaced it with new code that calls the ModelReader::ReadModel method. The following code table shows the changes to the code. I have commented out the code to be replaced, but this code can actually be deleted.

void SimpleTextRenderer::CreateDeviceResources()

{

     DirectXBase::CreateDeviceResources();

     // Define the vertices with the CPU in system RAM

     //Vertex triangleVertices[] =

     //   {

     //        { XMFLOAT3(-1.0f,0.0f, 0.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) },

     //        { XMFLOAT3(0.0f, 1.0f, 0.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) },

     //        { XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }

     //   };

     // Create the model instance from the vertices:

     //m_model = new Model(m_d3dDevice.Get(), triangleVertices, 3);

     // Read the spaceship model

     m_model = ModelReader::ReadModel(m_d3dDevice.Get(), "spaceship.obj ");

     

      // Create the constant buffer on the device

You should be able to run the application at this point and see a colored spaceship model; it will not look like a spaceship, because the camera is rather close and looking directly at the back of the model. Let’s raise the camera a little so we can get a better view of the mesh. The camera’s position is set in the SimpleTextRenderer::Update method; change the Y value to 5.0f so the camera is above and behind the mesh looking down. This change is highlighted in the following code table.

     // View matrix defines where the camera is and what direction it is looking in

     XMStoreFloat4x4(&m_constantBufferCPU.view, XMMatrixTranspose(

          XMMatrixLookAtRH(

               XMVectorSet(0.0f, 5.0f, 2.0f, 0.0f),// Position

               XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f),// Look at

               XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f)   // Up vector

               )));

Now when you run the application you should see the colored spaceship in Figure 5.4. It looks a little strange because it’s being rendered with random colored triangles. Only the vertices from the original model are actually being applied.

Spaceship Model with Vertices

Figure 5.4: Spaceship Model with Vertices

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.