Shamino, I never showed you my implementation of ms3d vertex arrays. I decided to post it in public in case anybody else wanted to see what it might look like.
As usual, my code is messy, but it works.
Instead of trying to explain each aspect of the code, I will just wait for any questions.
In general, the idea is to only store a single copy of each vertex, then create parallel index arrays so OpenGL can render it fast and efficiently.
This can very easily be used as the only centralized format, where anything else must get converted to this before it can be used.
In the screenshot at the folder, the model being rendered with the red sphere around it is rendering a ms3d model (in its inefficient format), whilst the other one without the red thing around it is being rendered as a tightly packed vertex array.
ihatenature.thejefffiles.com/shamino
Once all of that stuff is compiled, here are some constructs that I use to render it.
Code:
struct NT_MODEL_CONTAINER
{
NT_MODEL_CONTAINER(NT_MODEL & mdl) : mdl_ref(mdl) {}
float mat[16];
NT_MODEL &mdl_ref;
};
...
void AddNTModelToRenderer(NT_MODEL & mdl,Matrix4x4 & mat)
{
NT_MODEL_CONTAINER *temp = new NT_MODEL_CONTAINER(mdl);
mat.FillGLMatrix(temp->mat);
mvNTModels.push_back(temp);
}
...
void GLRenderer::RenderNTModels()
{
if(!mvNTModels.size())
{
return;
}
NT_GL(glDisable(GL_LIGHTING))
NT_GL(glColor3f(1.0f,1.0f,1.0f))
NT_GL(glDepthFunc(GL_LESS))
gpNTGLAPI->glActiveTextureARB(GL_TEXTURE1_ARB);
NT_GL(glDisable(GL_TEXTURE_2D)) //disable second texture unit
gpNTGLAPI->glActiveTextureARB(GL_TEXTURE0_ARB);
NT_GL(glEnable(GL_TEXTURE_2D)) //enable first texture unit
NT_GL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)) //enable texture coord array for the first texture unit
NT_GL(glEnable(GL_CULL_FACE))
R_NormalCullMode();
NT_GL(glEnableClientState(GL_VERTEX_ARRAY))
NT_GL(glEnableClientState(GL_TEXTURE_COORD_ARRAY))
gpNTGLAPI->glClientActiveTextureARB(GL_TEXTURE0_ARB)
NT_GL(glEnableClientState(GL_TEXTURE_COORD_ARRAY))
std::vector<NT_MODEL_CONTAINER*>::iterator ptr;
NT_MODEL_CONTAINER *pObject = 0;
for(ptr = mvNTModels.begin(); ptr != mvNTModels.end(); ptr++)
{
pObject = *ptr;
NT_MODEL & mdl_ref = pObject->mdl_ref;
NT_GL(glPushMatrix())
NT_GL(glMultMatrixf(pObject->mat)) //transform the model
//render each mesh
for(int i = 0; i < mdl_ref.mNumMeshes; i++)
{
NT_MODEL::NT_MESH & mesh_ref = mdl_ref.mpMeshes[i];
gpTextureManager->BindTexture(GL_TEXTURE_2D,mdl_ref.mpTextures[mesh_ref.mTextureIndex]);
#define USE_NT_INDEX_ARRAY 1
#if USE_NT_INDEX_ARRAY
int start_index = mdl_ref.mpIndexArray[mesh_ref.mStartVertIndex];
int start_index = mesh_ref.mStartVertIndex;
NT_GL(glVertexPointer(3,GL_FLOAT,sizeof(NT_VERTEX),&mdl_ref.mpVertices[start_index].vertex))
NT_GL(glTexCoordPointer(2,GL_FLOAT,sizeof(NT_VERTEX),&mdl_ref.mpVertices[start_index].tex_coord))
NT_GL(glDrawElements(GL_TRIANGLES,mesh_ref.mNumMeshVerts,GL_UNSIGNED_INT,&mdl_ref.mpIndexArray[mesh_ref.mStartMeshIndex]))
#else
//alternative to the method above (immediate mode, both work)
gpNTGLAPI->ntglBegin(GL_TRIANGLES);
//I've used this method of accessing data for immediate mode rendering, works fine
for(int tri = 0; tri < mesh_ref.mNumMeshVerts; tri += 3) //reference to NT_MODEL::NT_MESH
{
for(int vert = 0; vert < 3; vert++) //3 verts in a triangle
{
int index = mdl_ref.mpIndexArray[tri + vert + mesh_ref.mStartMeshIndex];
NT_VERTEX & vert_ref = mdl_ref.mpVertices[index];
gpNTGLAPI->ntglTexCoord2fv(vert_ref.tex_coord);
gpNTGLAPI->ntglVertex3fv(vert_ref.vertex);
}
}
gpNTGLAPI->ntglEnd();
#endif //use nt vertex array
}
NT_GL(glPopMatrix())
}
}