I'd like to import obj models into my opengl program. I have a class / data format that I use to pass attribute data into shaders:
class CustomVertex : public IVtxFmt
{
public:
float m_Position[3]; // x, y, z offset 0, size = 3*sizeof(float)
float m_Normal[3]; // nx, ny, nz; offset 3
float m_TexCoords[2]; // u, v offset 6
float m_Colour[4]; // r, g, b, a offset 8
float m_Tangent[3]; // r, g, b offset 12
float m_Bitangent[3]; // r, g, b offset 15
};
So I'm working with a model of a log cabin I downloaded from the Internet.
The log cabin has several vertices, normals, and texture coord definitions, followed by a list of face definitions.
So my first instinct was to parse the obj file and end up with
vector<vertex>
vector<Normal>
vector<TexCoord>
That's not straightforward to translate into my CustomVertex format, since there might be 210 vertices, 100 tex coords and 80 normals defined in the file.
After a list of ~390 faces in this format:
f 83/42/1 67/46/1 210/42/1
I encounter the following in the file:
#
# object tile00
#
followed by more vertex definitions.
So from this, I have inferred that a model might consist of several sub objects, each defined by a number of faces; each face defined by 3 x vertex / normal / texcoord index values.
So in order to arrive with a vector of CustomVertex, I'm thinking that I need to do the following:
create and populate:
vector <vertex>
vector <normal>
vector <texcoord>
vector <indices>
I need to create a CustomVertex for each unique v/vn/vt triple in the face definitions.
So I thought about creating a map:
std::vector<CustomVertex> and
std::map< nHashId, CustomVertex_index >
So my idea is that for each v/vn/vt I encounter, I create a hash of this string e.g. nHashId = hash("80/50/1")* and search the map for the hash. If none exists, I create a CustomVertex and add it to the vector, then I add the newly created hash and the CustomVertex_index into the map.
*: By creating a hash of the v/vn/vt string, I'm creating a unique numeric value that corresponds to that string, which I'm hoping is faster to search/compare in the map than the equivalent text.
If I come across a match to the hash, I consider that the customvertex already exists and instead of creating a new CustomVertex, I just add the CustomVertex_index entry to the indices vector and move on.
Since this seems like a computationally expensive exercise, I guess I'll be dumping my CustomVertex arrays (and corresponding indices arrays) to disk for later retrieval, rather than parse the obj file every time.
Before I ask my questions, may I point out that due to time constraints and not wanting to have to redesign my Vbo class (a non-trivial task), I'm stuck with the CustomVertex format - I know its possible to supply attributes in separate arrays to my shaders, but I had read that interleaving the data like I have with CustomVertex can enhance performance.
So to my questions: 1. Does my method seem sound or crazy? If crazy, please point out where I'm going wrong.
Can you spot any potential issues?
Has anyone done this before and can recommend a simpler way to achieve what I'm trying to?