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

Threaded View

  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.

Posting Permissions

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