Problem with my model loader?

Jason Dietrich
  • Problem with my model loader? Jason Dietrich

    I'm trying to load MD2 models (stolen from Cube) and my loader seems to be loading the models fine, but I can't say the same for the drawing of the model. Here's my code:

    typedef float vec3_t[3];
    
    struct md2_t
    {
        int ident;
        int version;
    
        int skinwidth;
        int skinheigh;
        int framesize;
    
        int num_skins;
        int num_xyz;
        int num_st;
        int num_tris;
        int num_glcommands;
        int num_frames;
    
        int ofs_skins;
        int ofs_st;
        int ofs_tris;
        int ofs_frames;
        int ofs_glcommands;
        int ofs_end;
    };
    
    struct md2_vertex_t
    {
        unsigned char v[3];
        unsigned char index_normal;
    };
    
    typedef short md2_textcoord_t[2];
    
    struct md2_frame_t
    {
        float scale[3];
        vec3_t translate;
        char name[16];
        md2_vertex_t vertices[1]; // First vertex of this frame.
    };
    
    
    struct md2_triangle_t
    {
        short index_xyz[3];
        short index_st[3];
    };
    
    struct md2_anim_t
    {
        int first_frame, last_frame, fps;
    };
    
    struct md2_animstate_t
    {
        md2_anim_t* animation;
        float current_time, old_time, interpol;
        int type, current_frame, next_frame;
    };
    
    struct md2_glcmd_t
    {
        float s;
        float t;
        int index;
    };
    
    #define MD2_IDENT (('2'<<24) + ('P'<<16) + ('D'<<8) + 'I')
    #define MD2_VERSION 8
    
    class MD2 : public VertexModel
    {
        public:
            MD2(const std::string& Path);
            ~MD2();
    
            void Draw(timestep_t Time);
    
        private:
            md2_t m_MD2Header;
            md2_animstate_t m_MD2AnimState;
            md2_anim_t* m_MD2Animations;
            vec3_t* m_Vertices;
            vec3_t* m_InterpolatedVertices;
            int* m_Commands;
            int* m_Normals;
    
            unsigned int m_TextureID;
            float m_Scale;
    
            void Interpolate(vec3_t* Vertices);
    };
    
    
    #include <helpers/md2.h>
    #include <iostream>
    #include <fstream>
    #include <exception>
    
    MD2::MD2(const std::string& Path) : m_TextureID(0), m_Scale(1.0f)
    {
        std::ifstream File(Path.c_str(), std::iostream::in | std::ifstream::binary);
        if(!File.is_open())
        {
            Debugging::Debugf("Unable to open the file: %s", Path.c_str());
            exit(0);
        }
    
        // Get the filesize.
        File.seekg (0, std::ios::end);
        int Size = File.tellg();
        File.seekg (0, std::ios::beg);
    
        if(Size < sizeof(md2_t))
        {
            Debugging::Debugf("Incorrect header for the file: %s", Path.c_str());
            exit(0);
        }
    
        // Get the header.
        memset((void*)&m_MD2Header, 0, sizeof(md2_t));
        File.read((char*)&m_MD2Header, sizeof(md2_t));
    
        // Check if the file is actually a MD2 model.
        if(m_MD2Header.ident != MD2_IDENT || m_MD2Header.version != MD2_VERSION)
        {
            Debugging::Debugf("The file %s is not a MD2 model.", Path.c_str());
            exit(0);
        }
    
        // Allocate memory for the data.
        m_Vertices = new vec3_t[m_MD2Header.num_xyz * m_MD2Header.num_frames];
        m_InterpolatedVertices = new vec3_t[m_MD2Header.num_xyz];
        m_Normals = new int[m_MD2Header.num_xyz * m_MD2Header.num_frames];
        m_Commands = new int[m_MD2Header.num_glcommands];
        char* Buffer = new char[m_MD2Header.framesize * m_MD2Header.num_frames];
    
        // Read the frame data.
        File.seekg(m_MD2Header.ofs_frames, std::ios::beg);
        File.read(Buffer, m_MD2Header.framesize * m_MD2Header.num_frames);
    
        // Read the command data.
        File.seekg(m_MD2Header.ofs_glcommands, std::ios::beg);
        File.read((char*)m_Commands, m_MD2Header.num_glcommands * sizeof(int));
    
        // Read all the data.
        for(int i = 0; i < m_MD2Header.num_frames; ++i)
        {
            md2_frame_t* Frame = (md2_frame_t*)&Buffer[m_MD2Header.framesize * i];
            vec3_t* Vertices = &m_Vertices[m_MD2Header.num_xyz * i];
            int* Normals = &m_Normals[m_MD2Header.num_xyz * i];
    
            for(int vertex = 0; vertex < m_MD2Header.num_xyz; ++vertex)
            {
                Vertices[i][0] = (Frame->vertices[i].v[0] * Frame->scale[0]) + Frame->translate[0];
                Vertices[i][1] = (Frame->vertices[i].v[1] * Frame->scale[1]) + Frame->translate[1];
                Vertices[i][2] = (Frame->vertices[i].v[2] * Frame->scale[2]) + Frame->translate[2];
                Normals[i] = Frame->vertices[i].index_normal;
            }
        }
    
        // Free unused memory and close the file.
        delete[] Buffer;
        File.close();
    
        memset((void*)&m_MD2AnimState, 0, sizeof(m_MD2AnimState));
    }
    
    MD2::~MD2()
    {
        delete[] m_MD2Animations;
        delete[] m_Vertices;
        delete[] m_InterpolatedVertices;
        delete[] m_Commands;
        delete[] m_Normals;
    }
    
    void MD2::Draw(timestep_t Time)
    {
        glPushMatrix();
            // Transform the model coordinates into OpenGL coordinates.
            glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
            glRotatef(-90.0f, 0.0f, 0.0f, 1.0f);
    
            // Reverse the orientation of front-facing polygons.
            glPushAttrib(GL_POLYGON_BIT);
            glFrontFace(GL_CW);
            glEnable(GL_CULL_FACE);
            glCullFace(GL_BACK);
    
            // Bind the texture.
            //glEnable(GL_TEXTURE_2D);
            //glBindTexture(GL_TEXTURE_2D, m_TextureID);
    
            // Interpolate between frames.
            Interpolate(m_InterpolatedVertices);
    
            // Draw the model.
            int* Commands = m_Commands;
            while(int i = *(Commands++))
            {
                if(i < 0)
                {
                    glBegin(GL_TRIANGLE_FAN);
                    i = -i;
                }
                else
                {
                    glBegin(GL_TRIANGLE_STRIP);
                }
    
                for(; i > 0; --i, Commands += 3)
                {
                    md2_glcmd_t* Command = (md2_glcmd_t*)Commands;
    
                    glColor3f(1.0f, 1.0f, 1.0f);
                    glTexCoord2f(Command->s, Command->t);
                    glVertex3fv(m_InterpolatedVertices[Command->index]);
                }
    
                glEnd();
            }
    
            // Use the original orientation.
            glDisable(GL_CULL_FACE);
            glPopAttrib();
    
        glPopMatrix();
    }
    
    void MD2::Interpolate(vec3_t* Vertices)
    {
        for(int i = 0; i < m_MD2Header.num_xyz; ++i)
        {
            Vertices[i][0] = m_Vertices[i + (m_MD2Header.num_xyz * m_MD2AnimState.current_frame)][0] * m_Scale;
            Vertices[i][1] = m_Vertices[i + (m_MD2Header.num_xyz * m_MD2AnimState.current_frame)][1] * m_Scale;
            Vertices[i][2] = m_Vertices[i + (m_MD2Header.num_xyz * m_MD2AnimState.current_frame)][2] * m_Scale;
        }
    }
    

  • The drawing code looks fine - are you sure the loading is?

    // Read all the data.
    for(int i = 0; i < m_MD2Header.num_frames; ++i)
    {
        md2_frame_t* Frame = (md2_frame_t*)&Buffer[m_MD2Header.framesize * i];
        vec3_t* Vertices = &m_Vertices[m_MD2Header.num_xyz * i];
        int* Normals = &m_Normals[m_MD2Header.num_xyz * i];
    
        for(int vertex = 0; vertex < m_MD2Header.num_xyz; ++vertex)
        {
            Vertices[i][0] = (Frame->vertices[i].v[0] * Frame->scale[0]) + Frame->translate[0];
            Vertices[i][1] = (Frame->vertices[i].v[1] * Frame->scale[1]) + Frame->translate[1];
            Vertices[i][2] = (Frame->vertices[i].v[2] * Frame->scale[2]) + Frame->translate[2];
            Normals[i] = Frame->vertices[i].index_normal;
        }
    }
    

    To me it looks as if the indexing is wrong - shouldn't you index Vertices[vertex][0] rather than Vertices[i][0]?

    Besides: you don't need to take the OpenGL command list from the MD2 file - MD2 files also contain a regular list of triangles with indexes into the texture coordinate and vertex arrays.

    I mention it because I took this path when I wrote a MD2 loader. I found this data much more convinient than a pre-optimized OpenGL stream, but it surely depends on the application.

Tags
c++ opengl 3d models
Related questions and answers
  • ); // Set The Color Of The Model ( NEW ) // ORIGINAL DRAWING CODE //Draw the model as an interpolation between the two frames glBegin(GL_TRIANGLES); for(int i = 0; i &lt; numTriangles; i++) { MD2Triangle* triangle = triangles + i; for(int j = 0; j &lt; 3; j++) { MD2Vertex* v1 = frame1-&gt;vertices + triangle-&gt;vertices[j..., In); // Get The Current Line ( NEW ) shaderData[i][0] = shaderData[i][1] = shaderData[i][2] = float(atof (Line)); // Copy Over The Value ( NEW ) } fclose

  • memcpy(pVoid, OurVertices, sizeof(OurVertices)); // copy the vertices to the buffer pBuffer-&gt;Unmap(); // create the index buffer out of DWORDs DWORD OurIndices[] = { 0, 1, 2, // side 1...) * 8; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; bd.MiscFlags = 0; device-&gt;CreateBuffer(&amp;bd, NULL, &amp;pBuffer); void* pVoid; // the void pointer pBuffer-&gt;Map(D3D10_MAP_WRITE_DISCARD, 0, &amp;pVoid); // map the vertex buffer memcpy(pVoid, OurVertices, sizeof(OurVertices)); // copy the vertices to the buffer pBuffer-&gt;Unmap

  • at the same time: glBegin(GL_TRIANGLES); for(int i = 0; i &lt; numTriangles; i++) { MD2Triangle* triangle = triangles + i; for(int j = 0; j &lt; 3; j++) { MD2Vertex* v1...; for(int j = 0; j &lt; 3; j++) { MD2Vertex* v1 = frame1-&gt;vertices + triangle-&gt;vertices[j]; MD2Vertex* v2 = frame2-&gt;vertices + triangle-&gt;vertices[j...(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glNormalPointer(GL_FLOAT, 0, indices); glTexCoordPointer(2, GL_FLOAT, sizeof(float)*3, indices); glVertexPointer(3, GL

  • : float m_Position[3]; // x, y, z // offset 0, size = 3*sizeof(float) float m_TexCoords[2]; // u, v // offset 3*sizeof(float), size = 2*sizeof(float) float m_Normal[3..._TRIANGLES, m_nNumIndices, GL_UNSIGNED_INT, ((char*)NULL + 0) ); glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY... ); glEnableClientState( GL_NORMAL_ARRAY ); glEnableClientState( GL_COLOR_ARRAY ); glVertexPointer( 3, GL_FLOAT, sizeof(CustomVertex), ((char*)NULL + 0) ); glTexCoordPointer(3, GL_FLOAT, sizeof

  • }; // for the old/new screen command // Some nCurses setup int r = 0, c = 0; // current row and column (upper-left is (0,0)) const int nrows = 56, // number of rows in window ncols = 79...--; cspace++;}} for(int s= 0; s &lt;sspace; s++) buff[buff.size()-1].push_back(' '); // cwall2 //if(cwall2!= 0){ // if(cwall2&gt;0... /////////////////////////////////////////////////////////////////////////////////////////////////////////////// class Sprite { private: string name; char symbol; float shield; int location[2]; bool alive; public: ///////////////////// Get and SET all the privates

  • (GL_LIGHT0); glEnable(GL_LIGHT1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(0.0f, 0.0f, 0.0f); int vertexIndex = 0, normalIndex; glRotatef(90, 0, 1, 0); glPushMatrix(); for(int a = 0; a &lt; (int)groups.size(); a++) { if(groups[a].type == "prop") { //Code for rotation glPopMatrix(); glPushMatrix(); float x,y,z; x = y = z = 0; int...++) { glBegin(GL_POLYGON); for(int c = 0; c &lt; (int)groups[a].faces[b].vertices.size(); c++) { vertexIndex = groups[a].faces[b].vertices[c]; glVertex3d

  • structure contains the the indices of the vertices positions, normals, and texture coords. I haven't implemented texture coords yet, though. struct FaceDefinition { int vertexIndexes[3]; int... part, creating the vertex list... bool isDuplicate; for(int i = 0; i &lt; polygonCount; i++) { for(int i2 = 0; i2 &lt; 3; i2++) { isDuplicate = false... = indices; return modelData; } This is there sphere models file: #Vertex Info VERTEX_COUNT:62 NORMAL_COUNT:62 FACE_COUNT:120 VERTEX 0 19.5 0 VERTEX 0 -19.5 0 VERTEX 9.75 -16.887495 0 VERTEX

  • i wanna walk to terrain... first i created the terrain void desenha_terreno(float px, float pz){ for (int z = 0; z &lt; iwidth-1; z++) { glBegin(GL_TRIANGLE_STRIP); for (int x = 0; x &lt..., 1.0f); glVertex3f(terreno[x+1][z+1][0], terreno[x+1][z+1][1], terreno[x+1][z+1][2]); } glEnd(); } } I can move the camera with the functions: void keyboard (unsigned char key, int... are drawn in this order: 0 ---&gt; 1 / / |/ 2 ---&gt; 3 */ // draw vertex 0 glColor3f(terreno[x][z][1]/255.0f

  • Dear all, this is going to be tough: I have created a game object factory that generates objects of my wish. However, I get memory leaks which I can not fix. Memory leaks are generated by return new Object(); in the bottom part of the code sample. static BaseObject * CreateObjectFunc() { return new Object(); } How and where to delete the pointers? I wrote bool ReleaseClassType(). Despite the factory works well, ReleaseClassType() does not fix memory leaks. bool ReleaseClassTypes() { unsigned int nRecordCount = vFactories.size(); for (unsigned int nLoop = 0; nLoop &lt

Data information