Rendering .obj Model in DirectX 11

This topic is 1098 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hello,

I'm trying to render a box model (.obj file) but I don't see anything, I have attached the project file.

Share on other sites

@fastcall22: What do you mean?

Share on other sites
What is it you think is going to happen here? Do you think someone is going to download your project, set it up on their system, investigate and fix the issue then send back the fixed project, all from the goodness of their hearts?

What have you tried? What isn't working? Specific questions will get answers.

Share on other sites

@Aardvajk: The problem is: I don't see the model on the screen even I'm loading the vertices and setting up the vertex and index buffer

So, the best thing here is to post the code that I'm using.

FYI: This is just a simple project and it won't take 5 minutes to look it up.

Do you think someone is going to download your project, set it up on their system, investigate and fix the issue then send back the fixed project, all from the goodness of their hearts?

Yes, I'm expecting people here will help.

Edited by Medo3337

Share on other sites

If you would like someone to help you need to list what you've tried already, and what you think the problem might be. Narrow down the code shared to just the part where you think the problem is, and maybe try isolating problem parts in a stand alone test case.

Finally, voting down people for stating the brutally honest truth is a bit low, i wouldn't do it if I were you because the mods can see it...

Edited by braindigitalis

Share on other sites

@braindigitalis: What If I don't know where the problem is?

The only thing I see is that dev->CreateBuffer() is returning false when creating vertex or index buffer even both buffers was created successfully.

However, I'm not sure if the box is drawn or not (I see nothing on the screening)

int indexCount = vertexCount;
// Create vertex buffer
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(D3D11_BUFFER_DESC));
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.ByteWidth = vertexCount * sizeof(VertexType);
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bool r = dev->CreateBuffer(&bd, NULL, &pVertexBuffer);

D3D11_MAPPED_SUBRESOURCE ms;
memcpy(ms.pData, &vertices, sizeof(vertices));
devcon->Unmap(pVertexBuffer, NULL);

// Create index buffer
D3D11_BUFFER_DESC indexBufferDESC;
//ZeroMemory(&indexBufferDESC, sizeof(indexBufferDESC));
indexBufferDESC.Usage = D3D11_USAGE_DEFAULT;
indexBufferDESC.ByteWidth = sizeof(unsigned long) * indexCount;
indexBufferDESC.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDESC.CPUAccessFlags = 0;
indexBufferDESC.MiscFlags = 0;
indexBufferDESC.StructureByteStride = 0;

D3D11_SUBRESOURCE_DATA indexData;
indexData.pSysMem = indices;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;

// Create the index buffer
result = dev->CreateBuffer(&indexBufferDESC, &indexData, &pIndexBuffer);
Edited by Medo3337

Share on other sites

Thanks, any idea why the zeromemory call is commented out? There are other fields in the index buffer you aren't filling that should all be zeroed. Does uncommenting that help at all?

Share on other sites

@braindigitalis: The 6 structure properties are filled, I even tried to uncomment the ZeroMemory() call but still nothing happens.

Share on other sites

You removed most of temp files from your project, I'll give you that. Usually people are unable to do even that.

I am unable to compile your project because I don't have D3DX, but there is something I have noticed:

1. you aren't doing any transformations in your vertex shader, meaning it's not being transformed into the screen;
2. your box is relatively far from (0, 0, 0) point, it won't be visible with 'default' camera transform.

Share on other sites

@Zaoshi Kaba: I tried to create a small box in 3Ds Max and set its position to 0.0, 0.0, 0.0

I still see nothing, how do I debug to find out if the box is being drawn or not?

Share on other sites

You should use a Graphics Debugger to be able to see the data as it goes through the rendering Pipeline.

I Highly recommend Renderdoc, as its trivial to setup, and relatively intuitive to use.

http://renderdoc.org

Share on other sites

@Zaoshi Kaba: I tried to setup world, view and projection matrices.

When I render a triangle as the following, it works perfectly:

VERTEX vertices[] =
{
{0.0f, 0.5f, 0.0f, D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f)},
{0.45f, -0.5f, 0.0f, D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f)},
{-0.45f, -0.5f, 0.0f, D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)}
};

However, if I changed the vertices to the vertices of the box that I loaded from the .obj file, I don't see anything rendered on the screen

I even tried to move the camera around, but still I don't see anything.

Share on other sites

After trying to solve the problem for awhile, I can now see the mesh, however I see 2 triangles instead of a box (incomplete box)

I guess the problem is with the indices, I have 8 vertices, how do I calculate the indices for the box?

Share on other sites

how do I calculate the indices for the box?

First, the obj file format supports indices for each face. Does your file already contain face definitions? If so, import and use them.

If you're given 8 vertices without indices provided, you have to hard code the indices, rather than calculate them.

A box is comprised of 6 faces, each face defined by 4 vertices at the corners. Each face is comprised of 2 triangles, each triangle defined by 3 of the 4 face vertices.

Assuming you're rendering with a DrawIndexed call, and using a primitive topology type of TRIANGLELIST, there will be 12 triangles ( 2 tris for each of 6 faces ), and, therefore 36 indices, 3 for each triangle.

Examine the list of vertices in the order they will be placed in the vertex buffer, and determine which 3 vertices by index number (zero-based) are used in each triangle. Add 3 indices for each triangle to the list of indices. Those 3 indices must be added in the correct winding order for the topology used, commonly clockwise.

Share on other sites

After trying to solve the problem for awhile, I can now see the mesh, however I see 2 triangles instead of a box (incomplete box)

I guess the problem is with the indices, I have 8 vertices, how do I calculate the indices for the box?

// Read in the faces.
if(input == 'f')
{
fin.get(input);
if(input == ' ')
{
// Read the face data in backwards to convert it to a left hand system from right hand system.
fin >> faces[faceIndex].vIndex3 >> input2 >> faces[faceIndex].tIndex3 >> input2 >> faces[faceIndex].nIndex3
>> faces[faceIndex].vIndex2 >> input2 >> faces[faceIndex].tIndex2 >> input2 >> faces[faceIndex].nIndex2
>> faces[faceIndex].vIndex1 >> input2 >> faces[faceIndex].tIndex1 >> input2 >> faces[faceIndex].nIndex1;
faceIndex++;
}
}


Which assumes 3 vertices per face, aka. triangle, however in your .obj file:

g Box001
usemtl Material__26
s 2
f 1/1/1 2/2/1 3/3/1 4/4/1
s 4
f 5/4/2 6/1/2 7/2/2 8/3/2
s 8
f 1/4/3 4/1/3 6/2/3 5/3/3
s 16
f 4/4/4 3/1/4 7/2/4 6/3/4
s 32
f 3/4/5 2/1/5 8/2/5 7/3/5
s 64
f 2/4/6 1/1/6 5/2/6 8/3/6
# 6 polygons


each face (polygon) contains 4 vertices.

You have 2 choices here:

1. load correct number of vertices for each face / polygon and triangulate them;
2. when you export .obj file there should be an option to triangulate meshes / faces / polygons, use it to generate triangles instead of arbitrary polygons.

Share on other sites

EDIT: (Duplicated Post)

Edited by Medo3337

Share on other sites

@Zaoshi Kaba: I have changed the faces property to "Triangles" instead of Quads, now I'm getting the following .obj contents:

# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 15.01.2015 19:32:59

mtllib box_obj.mtl

#
# object Box001
#

v  -3.9184 -2.6713 3.3765
v  -3.9184 -2.6713 -3.3765
v  3.9184 -2.6713 -3.3765
v  3.9184 -2.6713 3.3765
v  -3.9184 2.6713 3.3765
v  3.9184 2.6713 3.3765
v  3.9184 2.6713 -3.3765
v  -3.9184 2.6713 -3.3765
# 8 vertices

vn 0.0000 -1.0000 -0.0000
vn 0.0000 1.0000 -0.0000
vn 0.0000 0.0000 1.0000
vn 1.0000 0.0000 -0.0000
vn 0.0000 0.0000 -1.0000
vn -1.0000 0.0000 -0.0000
# 6 vertex normals

vt 1.0000 0.0000 0.0000
vt 1.0000 1.0000 0.0000
vt 0.0000 1.0000 0.0000
vt 0.0000 0.0000 0.0000
# 4 texture coords

g Box001
usemtl wire_228214153
s 2
f 1/1/1 2/2/1 3/3/1
f 3/3/1 4/4/1 1/1/1
s 4
f 5/4/2 6/1/2 7/2/2
f 7/2/2 8/3/2 5/4/2
s 8
f 1/4/3 4/1/3 6/2/3
f 6/2/3 5/3/3 1/4/3
s 16
f 4/4/4 3/1/4 7/2/4
f 7/2/4 6/3/4 4/4/4
s 32
f 3/4/5 2/1/5 8/2/5
f 8/2/5 7/3/5 3/4/5
s 64
f 2/4/6 1/1/6 5/2/6
f 5/2/6 8/3/6 2/4/6
# 12 faces

Here is how I'm creating the index buffer:

indexCount = 36;

D3D11_BUFFER_DESC indexBufferDESC;
ZeroMemory(&indexBufferDESC, sizeof(D3D11_BUFFER_DESC));
indexBufferDESC.Usage = D3D11_USAGE_DEFAULT;
indexBufferDESC.ByteWidth = sizeof(FaceType) * 3 * 12;
indexBufferDESC.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDESC.CPUAccessFlags = 0;
indexBufferDESC.MiscFlags = 0;
indexBufferDESC.StructureByteStride = 0;

D3D11_SUBRESOURCE_DATA indexData;
indexData.pSysMem = faces;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;

// Create the index buffer
hr = dev->CreateBuffer(&indexBufferDESC, &indexData, &pIndexBuffer);
assert(SUCCEEDED(result));

For Drawing:

// ...
// ...
// ...
UINT stride = sizeof(VertexType);
UINT offset = 0;
devcon->IASetVertexBuffers(0, 1, &pVertexBuffer, &stride, &offset);
devcon->IASetIndexBuffer(pIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
devcon->DrawIndexed(indexCount, 0, 0);

swapchain->Present(0, 0);

Now, I'm getting weird results, here is what I'm getting on the screen:

[attachment=25505:box.png]

Share on other sites

Most likely indices are incorrect.

Are you sure you loaded them correctly?

s 2
f 1/1/1 2/2/1 3/3/1
f 3/3/1 4/4/1 1/1/1
s 4
f 5/4/2 6/1/2 7/2/2
f 7/2/2 8/3/2 5/4/2


should have these indices:

1, 2, 3

3, 4, 1

5, 6, 7

7, 8, 5

But array will be indexed from 0, so you need to subtract 1 from each of them:

0, 1, 2

2, 3, 0

4, 5, 6

6, 7, 4

But this is assuming you don't need normals and/or texture coordinates.

Share on other sites

indices are definitely wrong. from the image above, you can see that the triangle in the foreground is actually the lower left triangle of the front face of the cube, except that its bottom left vertex has been moved to the back corner of the cube. other tri's aren't showing due to back face culling - very common when indices are wrong. draw a 3d sketch of a cube on paper and number the corners (zero based). that will tell you what tri uses which indices.

Share on other sites

@Zaoshi Kaba: Here is how the indices look like:

[attachment=25508:faces.png]

And here is how I'm filling the variable 'faces':

// Read in the faces.
if(input == 'f')
{
fin.get(input);
if(input == ' ')
{
// Read the face data in backwards to convert it to a left hand system from right hand system.
fin >> faces[faceIndex].vIndex3 >> input2 >> faces[faceIndex].tIndex3 >> input2 >> faces[faceIndex].nIndex3
>> faces[faceIndex].vIndex2 >> input2 >> faces[faceIndex].tIndex2 >> input2 >> faces[faceIndex].nIndex2
>> faces[faceIndex].vIndex1 >> input2 >> faces[faceIndex].tIndex1 >> input2 >> faces[faceIndex].nIndex1;
faceIndex++;
}
}

Share on other sites

@Zaoshi Kaba: Here is how the indices look like:

But array will be indexed from 0, so you need to subtract 1 from each of them:

Doesn't look like you're doing that.

Share on other sites

@phil_t: I changed the code to:

// Read in the faces.
if(input == 'f')
{
fin.get(input);
if(input == ' ')
{
// Read the face data in backwards to convert it to a left hand system from right hand system.
fin >> faces[faceIndex].vIndex3 >> input2 >> faces[faceIndex].tIndex3 >> input2 >> faces[faceIndex].nIndex3
>> faces[faceIndex].vIndex2 >> input2 >> faces[faceIndex].tIndex2 >> input2 >> faces[faceIndex].nIndex2
>> faces[faceIndex].vIndex1 >> input2 >> faces[faceIndex].tIndex1 >> input2 >> faces[faceIndex].nIndex1;
faces[faceIndex].vIndex3 -= 1;
faces[faceIndex].vIndex2 -= 1;
faces[faceIndex].vIndex1 -= 1;
faces[faceIndex].tIndex3 -= 1;
faces[faceIndex].tIndex2 -= 1;
faces[faceIndex].tIndex1 -= 1;
faces[faceIndex].nIndex3 -= 1;
faces[faceIndex].nIndex2 -= 1;
faces[faceIndex].nIndex1 -= 1;

faceIndex++;
}
}

Now, I don't see anything on the screen.

Share on other sites

That's not how index buffer works.

Not sure if I'll be able to explain this correctly though.

Currently your buffer contains indexes for position, normal, texture coordinate separately, but all these are properties of vertex and they're impossible to index separately.

If you wish to include color your vertex structure might look like this:

struct Vertex {
float x, y, z; // position
float nx, ny, nz; // normal
float tx, ty; // texture coordinates
float r, g, b, a; // color
};


Now Vertex* vertices = new Vertex[countVertex]; should contain all unique combinations of position/normal/texcoord/color.

In cube case there will be 24 unique combinations.

It appears you have 8 different vertices, but no, you have 8 different positions.

Lets take front top right vertex - it'll have same position for all 3 walls (top, right, front), but these walls have different normal vector, which results in these combinations:

(position1, normal1)
(position1, normal2)
(position1, normal3)

And that is 3 vertices in your vertex buffer. If you do same for 7 other vertices you'll have 24 unique vertex combinations. Adding color and texture coordinate won't increase number of vertices in this case.

s 2
f 1/1/1 2/2/1 3/3/1
f 3/3/1 4/4/1 1/1/1
s 4
f 5/4/2 6/1/2 7/2/2
f 7/2/2 8/3/2 5/4/2


you need to track all unique combinations of faces, generate vertices from position, normal, texcoord indexes, and generate index buffer from these combinations.

Ex.: combination (1/1/1) will have index 0 ( vertices[0] ), which mean you add to your index buffer value 0. If later on you encounter (1/1/1) again, you'll be adding value 0 again.

Hopefully I managed to explain it.