Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 2 of 2

Thread: loading md2 model dll

  1. #1
    Junior Member Newbie
    Join Date
    Apr 2012
    Posts
    4

    loading md2 model dll

    Hello, I hope I'm not breaking any rules with this topic.
    I'm developing a dll that loads md2 models at high speed.
    I am using an example of opengl.

    I want to do this in order to load md2 models in other languages​​.

    the problem is that I'm not aware identify the vertices of triangles.

    Code :
    #define NUMVERTEXNORMALS		162
     
    // precalculated normal vectors
    #define SHADEDOT_QUANT			16
     
    // magic number "IDP2" or 844121161
    #define MD2_IDENT				(('2'<<24) + ('P'<<16) + ('D'<<8) + 'I')
     
    // model version
    #define	MD2_VERSION				8
     
    // maximum number of vertices for a MD2 model
    #define MAX_MD2_VERTS			2048
     
    #include	<list>
    #include	<string>
    #include <math.h>
     
    #define GML __declspec(dllexport)
     
    using namespace std;
     
    // ==============================================
    // CTexture - texture class object.
    // ==============================================
     
    class CTexture
    {
    public:
    	// constructors/destructor
    	CTexture( void ) { }
    	CTexture( const char *texname ) { m_name = texname; }
    	CTexture( unsigned int texid, const char *texname )	{ m_id = texid; m_name = texname; }
     
    	unsigned int	GetTexId( void ) { return m_id; }
    	const char		*GetName( void ) { return m_name.c_str(); }
     
     
    public:
    	// members variables
    	unsigned int	m_id;			// texture id
    	std::string		m_name;			// texture name
     
    };
     
     
     
    // ==============================================
    // CTextureManager - OpenGL texture manager.
    // ==============================================
     
    class CTextureManager
    {
    protected:
    	// constructor/destructor
    	CTextureManager( void ) { Initialize(); }
    	virtual ~CTextureManager( void ) { CleanAllTextures(); }
     
    public:
    	// singleton functions
    	static CTextureManager	*GetInstance( void );
    	static void				FreeInstance( void );
     
     
    	// functions
    	void			Initialize( void );
    	unsigned int	LoadTexture( const char *filename );
    	void			DeleteTexture( unsigned int id );
    	void			CleanAllTextures( void );
     
     
    private:
    	// linked texture list
    	typedef std::list<CTexture *>	TextureList;
    	typedef TextureList::iterator	TListItor;
     
    	TextureList						m_texlist;
     
    	// singleton
    	static CTextureManager			*m_singleton;
     
    };
     
     
     
    // global function using the texture manager
     
     
    typedef float vec3_t[3];
     
    // md2 header
    typedef struct
    {
    	int		ident;				// magic number. must be equal to "IPD2"
    	int		version;			// md2 version. must be equal to 8
     
    	int		skinwidth;			// width of the texture
    	int		skinheight;			// height of the texture
    	int		framesize;			// size of one frame in bytes
     
    	int		num_skins;			// number of textures
    	int		num_xyz;			// number of vertices
    	int		num_st;				// number of texture coordinates
    	int		num_tris;			// number of triangles
    	int		num_glcmds;			// number of opengl commands
    	int		num_frames;			// total number of frames
     
    	int		ofs_skins;			// offset to skin names (64 bytes each)
    	int		ofs_st;				// offset to s-t texture coordinates
    	int		ofs_tris;			// offset to triangles
    	int		ofs_frames;			// offset to frame data
    	int		ofs_glcmds;			// offset to opengl commands
    	int		ofs_end;			// offset to the end of file
     
    } md2_t;
     
     
     
    // vertex
    typedef struct
    {
    	unsigned char	v[3];				// compressed vertex' (x, y, z) coordinates
    	unsigned char	lightnormalindex;	// index to a normal vector for the lighting
     
    } vertex_t;
     
     
     
    // frame
    typedef struct
    {
    	float		scale[3];		// scale values
    	float		translate[3];	// translation vector
    	char		name[16];		// frame name
    	vertex_t	verts[1];		// first vertex of this frame
     
    } frame_t;
     
     
     
    // animation
    typedef struct
    {
    	int		first_frame;			// first frame of the animation
    	int		last_frame;				// number of frames
    	int		fps;					// number of frames per second
     
    } anim_t;
     
     
     
    // status animation
    typedef struct
    {
    	int		startframe;				// first frame
    	int		endframe;				// last frame
    	int		fps;					// frame per second for this animation
     
    	float	curr_time;				// current time
    	float	old_time;				// old time
    	float	interpol;				// percent of interpolation
     
    	int		type;					// animation type
     
    	int		curr_frame;				// current frame
    	int		next_frame;				// next frame
     
    } animState_t;
     
     
     
    // animation list
    typedef enum {
    	STAND,
    	RUN,
    	ATTACK,
    	PAIN_A,
    	PAIN_B,
    	PAIN_C,
    	JUMP,
    	FLIP,
    	SALUTE,
    	FALLBACK,
    	WAVE,
    	POINT,
    	CROUCH_STAND,
    	CROUCH_WALK,
    	CROUCH_ATTACK,
    	CROUCH_PAIN,
    	CROUCH_DEATH,
    	DEATH_FALLBACK,
    	DEATH_FALLFORWARD,
    	DEATH_FALLBACKSLOW,
    	BOOM,
     
    	MAX_ANIMATIONS
     
    } animType_t;
     
     
     
    // ==============================================
    // CMD2Model - MD2 model class object.
    // ==============================================
     
    class CMD2Model
    {
    public:
    	// constructor/destructor
    	CMD2Model( void );
    	~CMD2Model( void );
     
     
    	// functions
    	bool	LoadModel( const char *filename );
    	bool	LoadSkin( const char *filename );
     
    	void	DrawModel( float time );
    	void	DrawFrame( int frame );
     
    	void	SetAnim( int type );
    	void	ScaleModel( float s ) { m_scale = s; }
     
    	void	Animate( float time );
    	void	ProcessLighting( void );
    	void	Interpolate( vec3_t *vertlist );
    	void	RenderFrame( void );
     
     
    public:
    	// member variables
    	static vec3_t	anorms[ NUMVERTEXNORMALS ];
    	static float	anorms_dots[ SHADEDOT_QUANT ][256];
     
    	static anim_t	animlist[21];		// animation list
     
     
    private:
    	int				num_frames;			// number of frames
    	int				num_xyz;			// number of vertices
    	int				num_glcmds;			// number of opengl commands
     
    	vec3_t			*m_vertices;		// vertex array
    	int				*m_glcmds;			// opengl command array
    	int				*m_lightnormals;	// normal index array
     
    	unsigned int	m_texid;			// texture id
    	animState_t		m_anim;				// animation
    	float			m_scale;			// scale value
     
    };
     
    #include	<fstream>
     
    // precalculated normal vectors
    vec3_t	CMD2Model::anorms[ NUMVERTEXNORMALS ] = {
    #include	"main.h"
    };
     
    // precalculated dot product results
    float	CMD2Model::anorms_dots[ SHADEDOT_QUANT ][256] = {
    #include	"anormstab.h"
    };
     
     
    static float	*shadedots = CMD2Model::anorms_dots[0];
    static vec3_t	lcolor;
     
     
    /////////////////////////////////////////////////
     
    vec3_t			g_lightcolor	= { 1.0, 1.0, 1.0 };
    int				g_ambientlight	= 32;
    float			g_shadelight	= 128;
    float			g_angle			= 0.0;
     
    /////////////////////////////////////////////////
     
     
     
    // ----------------------------------------------
    // constructor - reset all data.
    // ----------------------------------------------
     
    CMD2Model::CMD2Model( void )
    {
    	m_vertices		= 0;
    	m_glcmds		= 0;
    	m_lightnormals	= 0;
     
    	num_frames		= 0;
    	num_xyz			= 0;
    	num_glcmds		= 0;
     
    	m_texid			= 0;
    	m_scale			= 1.0;
     
    	SetAnim( 0 );
    }
     
     
     
    // ----------------------------------------------
    // destructeur - free allocated memory.
    // ----------------------------------------------
     
    CMD2Model::~CMD2Model( void )
    {
    	delete [] m_vertices;
    	delete [] m_glcmds;
    	delete [] m_lightnormals;
    }
     
     
     
    // ----------------------------------------------
    // LoadModel() - load model from file.
    // ----------------------------------------------
    ofstream OUTPUT;
    bool inline CMD2Model::LoadModel( const char *filename )
    {
    	std::ifstream	file;			// file stream;
    	OUTPUT.open("output.gml");
    	md2_t			header;			// md2 header
    	char			*buffer;		// buffer storing frame data
    	frame_t			*frame;			// temporary variable
    	vec3_t			*ptrverts;		// pointer on m_vertices
    	int				*ptrnormals;	// pointer on m_lightnormals
     
     
    	// try to open filename
    	file.open( filename, std::ios::in | std::ios::binary );
     
    	if( file.fail() )
    		return false;
     
    	// read header file
    	file.read( (char *)&header, sizeof( md2_t ) );
     
     
    	/////////////////////////////////////////////
    	//		verify that this is a MD2 file
     
    	// check for the ident and the version number
     
    	if( (header.ident != MD2_IDENT) && (header.version != MD2_VERSION) )
    	{
    		// this is not a MD2 model
    		OUTPUT<<"FAILED!"<<endl;
    		file.close();
    		return false;
    	}
     
    	/////////////////////////////////////////////
     
     
    	// initialize member variables
    	num_frames	= header.num_frames;
    	num_xyz		= header.num_xyz;
    	num_glcmds	= header.num_glcmds;
    	OUTPUT<<"framenum="<<num_frames<<endl;
    	OUTPUT<<"vertexnum="<<num_xyz<<endl;
     
     
    	// allocate memory
    	m_vertices		= new vec3_t[ num_xyz * num_frames ];
    	m_glcmds		= new int[ num_glcmds ];
    	m_lightnormals	= new int[ num_xyz * num_frames ];
    	buffer			= new char[ num_frames * header.framesize ];
     
     
    	/////////////////////////////////////////////
    	//			reading file data
     
    	// read frame data...
    	file.seekg( header.ofs_frames, std::ios::beg );
    	file.read( (char *)buffer, num_frames * header.framesize );
     
    	// read opengl commands...
    	file.seekg( header.ofs_glcmds, std::ios::beg );
    	file.read( (char *)m_glcmds, num_glcmds * sizeof( int ) );
     
    	/////////////////////////////////////////////
     
     
    	// vertex array initialization
    	for( int j = 0; j < num_frames; j++ )
    	{
    		// ajust pointers
    		frame		= (frame_t *)&buffer[ header.framesize * j ];
    		ptrverts	= &m_vertices[ num_xyz * j ];
    		ptrnormals	= &m_lightnormals[ num_xyz * j ];
            OUTPUT<<"_M_=d3d_model_create();MODEL["<<j<<"]=_M_;"<<endl;
            OUTPUT<<"d3d_model_primitive_begin(_M_,4);"<<endl;
    		for( int i = 0; i < num_xyz; i++ )
    		{
    			ptrverts[i][0] = (frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0];
    			ptrverts[i][1] = (frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1];
    			ptrverts[i][2] = (frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2];
    			OUTPUT<<"d3d_model_vertex(_M_,"<<round(ptrverts[i][0])<<","<<round(ptrverts[i][1])<<","<<round(ptrverts[i][2])<<");"<<endl;
                OUTPUT<<"d3d_model_vertex(_M_,"<<round(ptrverts[i][0])<<","<<round(ptrverts[i][1])<<","<<round(ptrverts[i][2])<<");"<<endl;
    			ptrnormals[i] = frame->verts[i].lightnormalindex;
    		}
    		OUTPUT<<"d3d_model_primitive_end(_M_);"<<endl;
    	}
     
     
    	// free buffer's memory
    	delete [] buffer;
     
    	// close the file and return
    	file.close();
        return true;
    }
     
     
    // ----------------------------------------------
    // DrawModel() - draw the model.
    // ----------------------------------------------
     
    void CMD2Model::DrawModel( float time )
    {
    	// animate. calculate current frame and next frame
    	if( time > 0.0 )
    		Animate( time );
     
    /*	glPushMatrix();
    		// rotate the model
    		glRotatef( -90.0, 1.0, 0.0, 0.0 );
    		glRotatef( -90.0, 0.0, 0.0, 1.0 );
     
    		// render it on the screen
    		RenderFrame();
    	glPopMatrix();*/
    }
     
     
     
    // ----------------------------------------------
    // Animate() - calculate the current frame, next
    // frame and interpolation percent.
    // ----------------------------------------------
     
    void CMD2Model::Animate( float time )
    {
    	m_anim.curr_time = time;
     
    	// calculate current and next frames
    	if( m_anim.curr_time - m_anim.old_time > (1.0 / m_anim.fps) )
    	{
    		m_anim.curr_frame = m_anim.next_frame;
    		m_anim.next_frame++;
     
    		if( m_anim.next_frame > m_anim.endframe )
    			m_anim.next_frame = m_anim.startframe;
     
    		m_anim.old_time = m_anim.curr_time;
    	}
     
    	// prevent having a current/next frame greater
    	// than the total number of frames...
    	if( m_anim.curr_frame > (num_frames - 1) )
    		m_anim.curr_frame = 0;
     
    	if( m_anim.next_frame > (num_frames - 1) )
    		m_anim.next_frame = 0;
     
    	m_anim.interpol = m_anim.fps * (m_anim.curr_time - m_anim.old_time);
    }
     
     
     
    // ----------------------------------------------
    // ProcessLighting() - process all lighting calculus.
    // ----------------------------------------------
     
    void CMD2Model::ProcessLighting( void )
    {
    	float lightvar = (float)((g_shadelight + g_ambientlight)/256.0);
     
    	lcolor[0] = g_lightcolor[0] * lightvar;
    	lcolor[1] = g_lightcolor[1] * lightvar;
    	lcolor[2] = g_lightcolor[2] * lightvar;
     
    	shadedots = anorms_dots[ ((int)(g_angle * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1) ];
    }
     
     
     
    // ----------------------------------------------
    // Interpolate() - interpolate and scale vertices
    // from the current and the next frame.
    // ----------------------------------------------
     
    void CMD2Model::Interpolate( vec3_t *vertlist )
    {
    	vec3_t	*curr_v;	// pointeur to current frame vertices
    	vec3_t	*next_v;	// pointeur to next frame vertices
     
    	// create current frame and next frame's vertex list
    	// from the whole vertex list
    	curr_v = &m_vertices[ num_xyz * m_anim.curr_frame ];
    	next_v = &m_vertices[ num_xyz * m_anim.next_frame ];
     
    	// interpolate and scale vertices to avoid ugly animation
    	for( int i = 0; i < num_xyz ; i++ )
    	{
    		vertlist[i][0] = (curr_v[i][0] + m_anim.interpol * (next_v[i][0] - curr_v[i][0])) * m_scale;
    		vertlist[i][1] = (curr_v[i][1] + m_anim.interpol * (next_v[i][1] - curr_v[i][1])) * m_scale;
    		vertlist[i][2] = (curr_v[i][2] + m_anim.interpol * (next_v[i][2] - curr_v[i][2])) * m_scale;
    	}
    }
     
     
     
    // ----------------------------------------------
    // RenderFrame() - draw the current model frame
    // using OpenGL commands.
    // ----------------------------------------------
     
    void CMD2Model::RenderFrame( void )
    {
    	static vec3_t	vertlist[ MAX_MD2_VERTS ];	// interpolated vertices
    	int				*ptricmds = m_glcmds;		// pointer on gl commands
     
     
    	// reverse the orientation of front-facing
    	// polygons because gl command list's triangles
    	// have clockwise winding
    /*	glPushAttrib( GL_POLYGON_BIT );
    	glFrontFace( GL_CW );
     
    	// enable backface culling
    	glEnable( GL_CULL_FACE );
    	glCullFace( GL_BACK );*/
     
     
    	// process lighting
    	ProcessLighting();
     
    	// interpolate
    	Interpolate( vertlist );
     
    	// bind model's texture
    //	glBindTexture( GL_TEXTURE_2D, m_texid );
    	// draw each triangle!
    	//OUTPUT<<"PTRICMDS:"<<ptricmds<<endl;
    	/*
    	while( int i = *(ptricmds++) )
    	{
    		if( i < 0 )
    		{
    //			glBegin( GL_TRIANGLE_FAN );
                //OUTPUT<<"BEGIN FAN";
    			i = -i;
    		}
    		else
    		{
    //			glBegin( GL_TRIANGLE_STRIP );
                //OUTPUT<<"BEGIN STRIP";
    		}
     
     
    		//for(; i > 0; i--, ptricmds += 3 ){
    			// ptricmds[0] : texture coordinate s
    			// ptricmds[1] : texture coordinate t
    			// ptricmds[2] : vertex index to render
     
    			//float l = shadedots[ m_lightnormals[ ptricmds[2] ] ];
     
    			// set the lighting color
    //			glColor3f( l * lcolor[0], l * lcolor[1], l * lcolor[2] );
     
    			// parse texture coordinates
    //			glTexCoord2f( ((float *)ptricmds)[0], ((float *)ptricmds)[1] );
     
    			// parse triangle's normal (for the lighting)
    			// >>> only needed if using OpenGL lighting
    //			glNormal3fv( anorms[ m_lightnormals[ ptricmds[2] ] ] );
     
    			// draw the vertex
    //			glVertex3fv( vertlist[ ptricmds[2] ] );
            //OUTPUT<<vertlist[0][0]<<vertlist[0][1]<<vertlist[0][2]<<endl;}
    		//for(int F=0;F<num_frames;F++){
    		//}
        //OUTPUT<<"END"<<endl;
    	//	glEnd();
    	}*/
    }
     
     
     
    // ----------------------------------------------
    // RenderFrame() - draw one frame of the model
    // using gl commands.
    // ----------------------------------------------
     
    void CMD2Model::DrawFrame( int frame )
    {
    	// set new animation parameters...
    	m_anim.startframe	= frame;
    	m_anim.endframe		= frame;
    	m_anim.next_frame	= frame;
    	m_anim.fps			= 1;
    	m_anim.type			= -1;
     
    	// draw the model
    	DrawModel( 1.0 );
    }
     
     
     
    // ----------------------------------------------
    // initialize the 21 MD2 model animations.
    // ----------------------------------------------
     
    anim_t CMD2Model::animlist[ 21 ] =
    {
    	// first, last, fps
     
    	{   0,  39,  9 },	// STAND
    	{  40,  45, 10 },	// RUN
    	{  46,  53, 10 },	// ATTACK
    	{  54,  57,  7 },	// PAIN_A
    	{  58,  61,  7 },	// PAIN_B
    	{  62,  65,  7 },	// PAIN_C
    	{  66,  71,  7 },	// JUMP
    	{  72,  83,  7 },	// FLIP
    	{  84,  94,  7 },	// SALUTE
    	{  95, 111, 10 },	// FALLBACK
    	{ 112, 122,  7 },	// WAVE
    	{ 123, 134,  6 },	// POINT
    	{ 135, 153, 10 },	// CROUCH_STAND
    	{ 154, 159,  7 },	// CROUCH_WALK
    	{ 160, 168, 10 },	// CROUCH_ATTACK
    	{ 196, 172,  7 },	// CROUCH_PAIN
    	{ 173, 177,  5 },	// CROUCH_DEATH
    	{ 178, 183,  7 },	// DEATH_FALLBACK
    	{ 184, 189,  7 },	// DEATH_FALLFORWARD
    	{ 190, 197,  7 },	// DEATH_FALLBACKSLOW
    	{ 198, 198,  5 },	// BOOM
    };
     
     
     
    // ----------------------------------------------
    // SetAnim() - initialize m_anim from the specified
    // animation.
    // ----------------------------------------------
     
    void CMD2Model::SetAnim( int type )
    {
    	if( (type < 0) || (type > MAX_ANIMATIONS) )
    		type = 0;
     
    	m_anim.startframe	= animlist[ type ].first_frame;
    	m_anim.endframe		= animlist[ type ].last_frame;
    	m_anim.next_frame	= animlist[ type ].first_frame + 1;
    	m_anim.fps			= animlist[ type ].fps;
    	m_anim.type			= type;
    }
     
    CMD2Model TEMPLATE;
    extern "C" GML double GMLOAD(const char *filename)
    {
        TEMPLATE.LoadModel(filename);
        TEMPLATE.RenderFrame();
    	OUTPUT.close();
    return(1);
    }

    I'm using CodeBlocks IDE and the mingw compiler.

    what the dll does is load the template and write the vertices in a text file in an organized way.
    I am using a program called GameMaker to test the dll because it is very easy and fast test dlls with it.

    i am sorry if I was not clear, but please try to help me.

    this is the important part I think
    Code :
    // vertex array initialization
    for( int j = 0; j < num_frames; j++ ){
    // ajust pointers
    frame= (frame_t *)&buffer[ header.framesize * j ];
    ptrverts	= &m_vertices[ num_xyz * j ];
    ptrnormals= &m_lightnormals[ num_xyz * j ];
    OUTPUT<<"_M_=d3d_model_create();MODEL["<<j<<"]=_M_;"<<endl;
    OUTPUT<<"d3d_model_primitive_begin(_M_,4);"<<endl;
          for( int i = 0; i < num_xyz; i++ ){
          ptrverts[i][0] = (frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0];
          ptrverts[i][1] = (frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1];
          ptrverts[i][2] = (frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2];
          OUTPUT<<"d3d_model_vertex(_M_,"<<round(ptrverts[i][0])<<","<<round(ptrverts[i][1])<<","<<round(ptrverts[i][2])<<");"<<endl;
          OUTPUT<<"d3d_model_vertex(_M_,"<<round(ptrverts[i][0])<<","<<round(ptrverts[i][1])<<","<<round(ptrverts[i][2])<<");"<<endl;
          ptrnormals[i] = frame->verts[i].lightnormalindex;
          }
    OUTPUT<<"d3d_model_primitive_end(_M_);"<<endl;
    }
    Last edited by Washiro; 04-25-2012 at 01:47 PM.

  2. #2
    Senior Member OpenGL Pro BionicBytes's Avatar
    Join Date
    Mar 2009
    Location
    UK, London
    Posts
    1,170
    This isn't really an OpenGL question is it?
    Secondly what does this mean?
    the problem is that I'm not aware identify the vertices of triangles
    You ask questions in a forum about something unrelated and then can't formulate your question? People have to understand you inorder to answer you!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •