Thread: Caught a problem MS3D structure setup.

  1. #1
    Absent Minded Programmer
    Join Date
    May 2005

    Caught a problem MS3D structure setup.

    Centralizing a renderer, but using glBegin/glEnd, I have finally noticed that this is, hm... Impossible. Unless you do some fancy polymorphism tricks, or some type switching, you cannot centralize a renderer without using vertex arrays. Why?

    All vertex arrays draw the same way, glDrawElements(), done, any type of geometry can be put in a vertex array, however, not every type of geometry glbegin/glend's the same way. Unless I have like, a virtual draw method in a base object class, and have each type of renderable object override that base function, which would be decentralizing the renderer, I must switch my MS3D structure to create a vertex array.

    This simply will not do!
    class MS3DModel
    	virtual ~MS3DModel();
    	struct Vertex
    		char BoneID;
    		float Location[3];
    	int NumVertices;
    	Vertex *Vertices;
    	struct Triangle
    		float VertexNormals[3][3];
    		float Textures1[3], Textures2[3];
    		int VertexIndices[3];
    	int NumTriangles;
    	Triangle *Triangles;
    	struct Mesh
    		int MaterialIndex;
    		int NumTriangles;
    		int *TriangleIndices;
    	int NumMeshes;
    	Mesh *Meshes;
    	struct Material
    		float Ambient[4], Diffuse[4], Specular[4], Emissive[4];
    		float Shininess;
    		GLuint Texture;
    		char *TextureFilename;
    	int NumMaterials;
    	Material *Materials;
    	bool Load( const std::string & name );
    	void ReloadTextures();
    	void Draw();
    I have to change this structure, so I have one vertex structure, the vertex structure should contain of course, vertices, and then tex coords, then normals, maybe even an rgb. I also need an index struct.

    I need to throw all of these into a vertex array, setting the stride correctly for each type of array.

    And then bam, one function call, draw an indexed MS3D Model with a VA. Now I can easily add support for other geometry types, and throw them in VA's, and then draw them all in the same way!

    But, I digress, can someone please demonstrate throwing a struct of the right vertex information into a VA, as well as an index..

    I know I need to modify the loading code for my ms3d file as well, this will be a huge task to undertake.

    Remember, I need Normals, Tex Coords, Vertices, as well as an index.

    I've done so much research on this topic, all I'm really missing is the syntax. Anyone willing to demonstrate?
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  2. #2
    Absent Minded Programmer
    Join Date
    May 2005
    I've gotten this much done so far, I'll put this structure in the MS3DModel class and cut out all the other structural information, and in the loading code I'll copy everything to this structure instead of to all the other ones...

    	struct Vertex
    		float vx;
    		float vy;
    		float vz;
    		float nx;
    		float ny;
    		float nz;
    		float s;
    		float t;
    		unsigned char r,g,b,a;
    		int BoneID;
    	int NumVertices;
    	Vertex * Vertices;
    I changed the loading code to fill out the vertex information correctly..

    	int nVertices = *( word* )pPtr; 
    	NumVertices = nVertices;
    	Vertices = new Vertex[nVertices];
    	pPtr += sizeof( word );
    	int i;
    	for ( i = 0; i < nVertices; i++ )
    		MS3DVertex * pVertex = ( MS3DVertex* )pPtr;
    		MS3DTriangle *pTriangle = ( MS3DTriangle* )pPtr;
    		Vertices[i].BoneID = pVertex->m_boneID;
    		Vertices[i].vx = pVertex->m_vertex[0];
    		Vertices[i].vy = pVertex->m_vertex[1];
    		Vertices[i].vz = pVertex->m_vertex[2];
    		pPtr += sizeof( MS3DVertex );
    My question is, how do I convert things that are structured in the file as triangles to being structured in my code as vertices?

    This is what I have to work on next..

    	int nTriangles = *( word* )pPtr;
    	m_numTriangles = nTriangles;
    	m_pTriangles = new Triangle[nTriangles];
    	pPtr += sizeof( word );
    	for ( i = 0; i < nTriangles; i++ )
    		MS3DTriangle *pTriangle = ( MS3DTriangle* )pPtr;
    		int vertexIndices[3] = { pTriangle->m_vertexIndices[0], pTriangle->m_vertexIndices[1], pTriangle->m_vertexIndices[2] };
    		float t[3] = { 1.0f-pTriangle->m_t[0], 1.0f-pTriangle->m_t[1], 1.0f-pTriangle->m_t[2] };
    		memcpy( m_pTriangles[i].m_vertexNormals, pTriangle->m_vertexNormals, sizeof( float )*3*3 );
    		memcpy( m_pTriangles[i].m_s, pTriangle->m_s, sizeof( float )*3 );
    		memcpy( m_pTriangles[i].m_t, t, sizeof( float )*3 );
    		memcpy( m_pTriangles[i].m_vertexIndices, vertexIndices, sizeof( int )*3 );
    		pPtr += sizeof( MS3DTriangle );

    I need all this information to be in my one vertex struct, this is going to be iffy..

    Can anyone give me a push in the right direction? It seems like converting the normals and such is going to be the trickiest..
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  3. #3
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Instead of using 3 floats like that why not encapsulate them into a Vector3 class?

    I posted the start of a Vector3 class on here some time ago for you. Perhaps a board search will turn it up.

  4. #4
    Absent Minded Programmer
    Join Date
    May 2005
    I just found out I gotta unshare MS3D Vertices, what a pain!!! I have to create normals/tex coords for all the vertices the file structure doesn't cover!

    How lame!!!

    Bleh, heres code..

    Here's what I did:

    void TriangleMesh::UnshareVertices()
      int verx, trix, i;
      int nTriangles;
      int _numVertices = this->numVertices;
      float s, t;
      int material;
      for (verx=0; verx<this->numVertices; verx++)
        nTriangles = 0;
        for (trix=0; trix<this->numTriangles; trix++)
          for (i=0; i<3; i++)
            if (verx == triangles [trix].vIndices [i])
              if (nTriangles == 1)
                arrayBone [verx] = vertices [verx].boneID;
                arrayVertex [verx] = vertices [verx].v;
                arrayVertexSkel [verx] = vertices [verx].vSkel;
                // Save s/t and material# for later reference
                s = triangles [trix].s [i];
                t = triangles [trix].t [i];
                material = groups [triangles [trix].groupIndex].materialIndex;
                // Set s/t, normal and skeleton normal from triangle to this vertex array element
                arrayTexCoord [(verx*2)] = triangles [trix].s [i];
                arrayTexCoord [(verx*2)+1] = triangles [trix].t [i];
                arrayNormal [verx] = triangles [trix].vNormals [i];
                arrayNormalSkel [verx] = triangles [trix].vNormalsSkel [i];
                if ((triangles [trix].s [i] != s || triangles [trix].t [i] != t) &&
                    (groups [triangles [trix].groupIndex].materialIndex == material))
                  // Create new Vertex: 
                  // * Update vertex index for this triangle
                  triangles [trix].vIndices [i] = _numVertices;
                  // * Add bone ID, x/y/z, skeleton x/y/z, s/t, normal and skeletion normal to vertex array
                  arrayBone [_numVertices] = vertices [verx].boneID;
                  arrayVertex [_numVertices] = vertices [verx].v;
                  arrayVertexSkel [_numVertices] = vertices [verx].vSkel;
                  arrayTexCoord [(_numVertices*2)] = triangles [trix].s [i];
                  arrayTexCoord [(_numVertices*2)+1] = triangles [trix].t [i];
                  arrayNormal [_numVertices] = triangles [trix].vNormals [i];
                  arrayNormalSkel [_numVertices] = triangles [trix].vNormalsSkel [i];
                  // * Increment max vertex index 
      this->numVertices = _numVertices;
    For each group in the MS3D file, I create an array of indexes, with the size of the # of triangles in that group * 3, and fill those with the list of vertices I just created in the code above.

      for (int i=0; i<numGroups; i++)
        groups[i].indexArray = new unsigned short[groups[i].numTriangles * 3];
        for (int j=0; j<groups [i].numTriangles; j++)
          TriangleMesh::Triangle *tri = &triangles[groups[i].triangleIndices[j]];
          groups[i].indexArray[(j*3)] = tri->vIndices[0];
          groups[i].indexArray[(j*3)+1] = tri->vIndices[1];
          groups[i].indexArray[(j*3)+2] = tri->vIndices[2];
    Then, before I start rendering, I:

        glTexCoordPointer(2, GL_FLOAT, 0, arrayTexCoord);
        glNormalPointer(GL_FLOAT, 0, (GLfloat *)arrayNormal);
        glVertexPointer(3, GL_FLOAT, 0, (GLfloat *)arrayVertex);
    THEN, for each group, I render with:

        glDrawElements(GL_TRIANGLES, groups[grpx].numTriangles * 3, GL_UNSIGNED_SHORT, groups[grpx].indexArray);
    I need to change it so I'm loading it all intoa super vertex struct so I can centralize that rendering function..

    The only reason I'm not using classes or anything is because I'd like to make it alot simpler to interleave the arrays and set the stride and do pointer math correctly.
    Last edited by Shamino; 03-25-2006 at 06:09 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Structure problem
    By lolguy in forum C Programming
    Replies: 4
    Last Post: 12-18-2008, 10:32 PM
  2. Replies: 1
    Last Post: 06-07-2006, 09:42 AM
  3. Pointer to structure problem
    By unregistered in forum C Programming
    Replies: 3
    Last Post: 12-24-2001, 07:54 AM
  4. C structure within structure problem, need help
    By Unregistered in forum C Programming
    Replies: 5
    Last Post: 11-30-2001, 05:48 PM
  5. Structure problem
    By mattz in forum C Programming
    Replies: 10
    Last Post: 11-30-2001, 01:19 PM