PDA

View Full Version : loading md2 model dll



Washiro
04-25-2012, 01:44 PM
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;
}

BionicBytes
04-26-2012, 01:10 AM
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!