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.


#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


// 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;
}

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!