13

So, in both D3D and OpenGL there's ability to draw from an index buffer.

The OBJ file format however does something weird. It specifies a bunch of vertices like:

v -21.499660 6.424470 4.069845
v -25.117170 6.418100 4.068025
v -21.663851 8.282170 4.069585
v -21.651890 6.420180 4.068675
v -25.128481 8.281520 4.069585

Then it specifies a bunch of normals like..

vn 0.196004 0.558984 0.805680
vn -0.009523 0.210194 -0.977613
vn -0.147787 0.380832 -0.912757
vn 0.822108 0.567581 0.044617
vn 0.597037 0.057507 -0.800150
vn 0.809312 -0.045432 0.585619

Then it specifies a bunch of tex coords like

vt 0.1225 0.5636
vt 0.6221 0.1111
vt 0.4865 0.8888
vt 0.2862 0.2586
vt 0.5865 0.2568
vt 0.1862 0.2166

THEN it specifies "faces" on the model like:

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

Where we're v/t/n the first number is an index into the vertices array, the second an index into the tex coord array, the third, into the normals array.

So, in trying to render this with vertex buffers,

In OpenGL I can use glVertexPointer, glNormalPointer and glTexCoordPointer to set pointers to each of the vertex, normal and texture coordinate arrays respectively.. but when it comes down to drawing with glDrawElements, I can only specify ONE set of indices, namely the indices it should use when visiting the vertices.

Ok, then what? I still have 3 sets of indices to visit.

In d3d its much the same - I can set up 3 streams: one for vertices, one for texcoords, and one for normals, but when it comes to using IDirect3DDevice9::DrawIndexedPrimitive, I can still only specify ONE index buffer, which will index into the vertices array.

So, is it possible to draw from vertex buffers using different index arrays for each of the vertex, texcoord, and normal buffers (EITHER d3d or opengl!), or must I create a single interleaved array and then visit IT?

bobobobo
  • 57,855
  • 58
  • 238
  • 337
  • possible duplicate of [Rendering meshes with multiple indices](http://stackoverflow.com/questions/11148567/rendering-meshes-with-multiple-indices) – Nicol Bolas Jan 06 '13 at 07:45

2 Answers2

8

OBJ was not designed to map to OpenGL or DirectX.

Everything you said is true, and no, it's not possible to use per-attribute indices.

You have to convert the OBJ representation to something that only uses a single index per vertex (possibly duplicating some vertex data along the way).

Bahbar
  • 16,994
  • 38
  • 60
  • So, as a follow up, __can I assume__ an obj file will __never__ switch vertex format midway? – bobobobo Apr 23 '10 at 13:50
  • @bobobobo: Well, it's been a long while I did not deal with OBJ files, but I think there were weird cases where a texture was only applied to parts of the model. As a result, I think only parts of the vertices had corresponding texture coordinates. That was about 10 years ago, though, so don't trust me on it. – Bahbar Apr 23 '10 at 15:45
  • Ha ha. What do you deal with now? – bobobobo Apr 23 '10 at 18:23
  • @bobobobo: part of my background is on the other side of the fence, in the implementation of GL. I wrote client code before that. – Bahbar Apr 24 '10 at 08:27
  • 1
    @bobobobo You *cannot* assume that it will not switch vertex format midway. In fact, using Lightwave this past summer (2012) I exported an OBJ/MTL and it used different combinations of f pos/tex/norm to specify vertex attributes for different faces (although each individual face has a consistent format), so don't expect nice behavior in "new" OBJs either. – GraphicsMuncher Nov 14 '12 at 20:57
2

What you really want to be doing (speaking from the D3D side of the fence, I don't know OpenGL sorry) is loading the OBJ in to an array of custom vertex format--that way you have a struct with the index, vertex, normal and tex coord in it and you can just render it using one DrawIndexedPrimtive.

Am I misunderstanding your problem definition here? I think you need to give a little more detail--you shouldn't need multiple index buffers to render a single OBJ file (unless you are deliberately batching it). If that is the case, that you are deliberately batching it, then you should take a look at the arguments to DrawIndexedPrimitive which allow you to specify an offset in to the VB to use.

Josh Atkins
  • 223
  • 1
  • 8
  • The reason I need multiple index buffers is the vertex, normal and texcoords are actually indexed at "different rates" in the face specification. In `f 1/3/5 2/8/1 4/2/2`, the first vertex uses index 1 from the vertices array, index 3 from the tex array, and index 5 from the normals array. – bobobobo Apr 23 '10 at 13:43
  • Yes--you need to load the OBJ data in to custom structs to render correctly in D3D. Part of this process requires duplicating vertices to correctly reference the face format. There is an example included in the DirectX SDK (depending on the version you are using). It can be found at \Samples\C++\Direct3D10\MeshFromOBJ10 – Josh Atkins Apr 24 '10 at 03:57
  • @JoshuaAtkins That was a good place to see the implementation, I went with a couple for loops out of laziness. – Rashid Ellis Nov 18 '14 at 06:15