www.pudn.com > coolMEMORY.rar > AS_MD2.cpp
//-----------------------------------------------------------------------------
// File: AS_MD2.cpp
//-----------------------------------------------------------------------------
#include "AS_Engine.h"
// Functions: *****************************************************************
AS_MD2_MODEL *ASLoadMd2Model(char *);
void ASDrawMd2Frame(AS_MD2_MODEL *, int);
void ASDrawMd2FrameInt(AS_MD2_MODEL *, int, int, float);
void ASPrecomputeMd2FrameInt(AS_MD2_MODEL *, int, int, float);
void ASDrawPrecomputedMd2Frame(AS_MD2_MODEL *);
void ASFreeMd2Model(AS_MD2_MODEL *);
AS_MD2_ANI ASMakeMd2Ani(AS_MD2_MODEL *);
void AS_Md2GenerateLightNormals(AS_MD2_MODEL *);
void AS_Md2_GetBoundingBox(AS_MD2_MODEL *);
///////////////////////////////////////////////////////////////////////////////
AS_MD2_MODEL *ASLoadMd2Model(char *model_name)
{ // begin ASLoadMd2Model()
FILE *md2file;
char ver[5];
int i, j;
AS_MD2_MODEL *mdl;
byte buffer[MD2_MAX_FRAMESIZE];
mdl = (AS_MD2_MODEL *) malloc(sizeof(AS_MD2_MODEL));
memset(mdl, 0, sizeof(AS_MD2_MODEL));
md2file = fopen(model_name, "rb");
if(md2file == NULL)
return NULL;
else
{
fread(&mdl->header, 1, sizeof(AS_MD2_HEADER), md2file);
sprintf(ver, "%c%c%c%c", mdl->header.magic, mdl->header.magic>>8, mdl->header.magic>>16, mdl->header.magic>>24);
if(strcmp(ver, "IDP2") || mdl->header.version != 8)
return NULL;
fseek(md2file, mdl->header.offsetSkins, SEEK_SET);
mdl->skins = (AS_MD2_SKIN *) malloc(sizeof(AS_MD2_SKIN)*mdl->header.numSkins);
for(i = 0; i < mdl->header.numSkins; i++)
fread(&mdl->skins[i], sizeof(AS_MD2_SKIN), 1, md2file);
fseek(md2file, mdl->header.offsetTexCoords, SEEK_SET);
mdl->texCoords = (AS_MD2_TEXTURE_COORDINATE *) malloc(sizeof(AS_MD2_TEXTURE_COORDINATE) * mdl->header.numTexCoords);
mdl->texCoord = (FLOAT2 *) malloc(sizeof(FLOAT2) * mdl->header.numTexCoords);
for(i = 0; i < mdl->header.numTexCoords; i++)
{
fread(&mdl->texCoords[i], sizeof(AS_MD2_TEXTURE_COORDINATE), 1, md2file);
mdl->texCoord[i][X] = (float) mdl->texCoords[i].s/mdl->header.skinWidth;
mdl->texCoord[i][Y] = (float) mdl->texCoords[i].t/mdl->header.skinHeight;
}
fseek(md2file, mdl->header.offsetTriangles, SEEK_SET);
mdl->triangles = (AS_MD2_TRIANGLE *) malloc(sizeof(AS_MD2_TRIANGLE) * mdl->header.numTriangles);
for(i = 0; i < mdl->header.numTriangles; i++)
fread(&mdl->triangles[i], sizeof(AS_MD2_TRIANGLE), 1, md2file);
fseek(md2file, mdl->header.offsetFrames, SEEK_SET);
mdl->prevertex = (FLOAT3 *) malloc(sizeof(FLOAT3)*mdl->header.numVertices);
mdl->prenormal = (FLOAT3 *) malloc(sizeof(FLOAT3)*mdl->header.numVertices);
mdl->frames = (AS_MD2_FRAME *) malloc(sizeof(AS_MD2_FRAME) * mdl->header.numFrames);
for(i = 0; i < mdl->header.numFrames; i++)
{
AS_MD2_ALIAS_FRAME *frame = (AS_MD2_ALIAS_FRAME *) buffer;
mdl->frames[i].vertices = (AS_MD2_TRIANGLE_VERTEX *) malloc(sizeof(AS_MD2_TRIANGLE_VERTEX) * mdl->header.numVertices);
mdl->frames[i].vertex = (FLOAT3 *) malloc(sizeof(FLOAT3) * mdl->header.numVertices);
mdl->frames[i].normal = (FLOAT3 *) malloc(sizeof(FLOAT3) * mdl->header.numVertices);
fread(frame, 1, mdl->header.frameSize, md2file);
strcpy(mdl->frames[i].name, frame->name);
for(j = 0; j < mdl->header.numVertices; j++)
{
mdl->frames[i].vertex[j][X] = mdl->frames[i].vertices[j].vertex[0] = (float) ((int) frame->alias_vertices[j].vertex[0]) * frame->scale[0] + frame->translate[0];
mdl->frames[i].vertex[j][Z] = mdl->frames[i].vertices[j].vertex[2] = -1* ((float) ((int) frame->alias_vertices[j].vertex[1]) * frame->scale[1] + frame->translate[1]);
mdl->frames[i].vertex[j][Y] = mdl->frames[i].vertices[j].vertex[1] = (float) ((int) frame->alias_vertices[j].vertex[2]) * frame->scale[2] + frame->translate[2];
NormalizeFace(&mdl->frames[i].vertices[j].normal, &mdl->frames[i].vertices[j].vertex[0],
&mdl->frames[i].vertices[j].vertex[1], &mdl->frames[i].vertices[j].vertex[2]);
mdl->frames[i].normal[j][X] = mdl->frames[i].vertices[j].normal[X];
mdl->frames[i].normal[j][Y] = mdl->frames[i].vertices[j].normal[Z];
mdl->frames[i].normal[j][Z] = -mdl->frames[i].vertices[j].normal[Y];
}
}
fseek(md2file, mdl->header.offsetGlCommands, SEEK_SET);
mdl->glCommandBuffer = (int *) malloc(sizeof(int) * mdl->header.numGlCommands);
fread(mdl->glCommandBuffer, sizeof(int), mdl->header.numGlCommands, md2file);
fclose(md2file);
}
mdl->Ani = ASMakeMd2Ani(mdl);
AS_Md2GenerateLightNormals(mdl);
AS_Md2_GetBoundingBox(mdl);
return mdl;
} // end ASLoadMd2Model()
void ASDrawMd2Frame(AS_MD2_MODEL *model, int frame)
{ // begin ASDrawMd2Frame()
AS_MD2_FRAME *f = &model->frames[frame];
vertlist vert_list[64];
int i, vertnum, index;
BOOL type;
int *command;
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, f->vertex);
glNormalPointer(GL_FLOAT, 0, f->normal);
if(_AS->bCompiledVertexArraySupported)
glLockArraysEXT(0, model->header.numVertices);
command = model->glCommandBuffer;
while ((*command) != 0)
{
if (*command > 0)
{vertnum = *command; command++; type = 0;}//triangle strip
else
{vertnum = - *command; command++; type = 1;}//triangle fan
if (vertnum<0) vertnum = -vertnum;
for (i=0, index = 0;ibCompiledVertexArraySupported)
glUnlockArraysEXT();
} // end ASDrawMd2Frame()
void ASDrawMd2FrameInt(AS_MD2_MODEL *model, int frame1, int frame2, float pol)
{ // begin ASDrawMd2FrameInt()
AS_MD2_FRAME *f1 = &model->frames[frame1];
AS_MD2_FRAME *f2 = &model->frames[frame2];
FLOAT2 *texCoord;
float x1, y1, z1, x2, y2, z2, *n1, *n2;
AS_MD2_TRIANGLE *t;
int i;
if(frame1 < 0 || frame2 < 0 ||
frame1 >= model->header.numFrames || frame2 >= model->header.numFrames)
return;
texCoord = model->texCoord;
glBegin (GL_TRIANGLES);
for (i = 0; i < model->header.numTriangles; i++)
{
t = &model->triangles[i];
glTexCoord2fv(texCoord[t->textureIndices[0]]);
n1 = f1->vertices[t->vertexIndices[0]].normal;
n2 = f2->vertices[t->vertexIndices[0]].normal;
glNormal3f ((1.0f - pol) * n1[0] + pol * n2[0],
(1.0f - pol) * n1[2] + pol * n2[2],
(1.0f - pol) * -n1[1] + pol * -n2[1]);
x1 = f1->vertices[t->vertexIndices[0]].vertex[0];
y1 = f1->vertices[t->vertexIndices[0]].vertex[1];
z1 = f1->vertices[t->vertexIndices[0]].vertex[2];
x2 = f2->vertices[t->vertexIndices[0]].vertex[0];
y2 = f2->vertices[t->vertexIndices[0]].vertex[1];
z2 = f2->vertices[t->vertexIndices[0]].vertex[2];
glVertex3f (x1 + pol * (x2 - x1),
y1 + pol * (y2 - y1),
z1 + pol * (z2 - z1));
glTexCoord2fv(texCoord[t->textureIndices[1]]);
n1 = f1->vertices[t->vertexIndices[1]].normal;
n2 = f2->vertices[t->vertexIndices[1]].normal;
glNormal3f ((1.0f - pol) * n1[0] + pol * n2[0],
(1.0f - pol) * n1[2] + pol * n2[2],
(1.0f - pol) * -n1[1] + pol * -n2[1]);
x1 = f1->vertices[t->vertexIndices[1]].vertex[0];
y1 = f1->vertices[t->vertexIndices[1]].vertex[1];
z1 = f1->vertices[t->vertexIndices[1]].vertex[2];
x2 = f2->vertices[t->vertexIndices[1]].vertex[0];
y2 = f2->vertices[t->vertexIndices[1]].vertex[1];
z2 = f2->vertices[t->vertexIndices[1]].vertex[2];
glVertex3f (x1 + pol * (x2 - x1),
y1 + pol * (y2 - y1),
z1 + pol * (z2 - z1));
glTexCoord2fv(texCoord[t->textureIndices[2]]);
n1 = f1->vertices[t->vertexIndices[2]].normal;
n2 = f2->vertices[t->vertexIndices[2]].normal;
glNormal3f ((1.0f - pol) * n1[0] + pol * n2[0],
(1.0f - pol) * n1[2] + pol * n2[2],
(1.0f - pol) * -n1[1] + pol * -n2[1]);
x1 = f1->vertices[t->vertexIndices[2]].vertex[0];
y1 = f1->vertices[t->vertexIndices[2]].vertex[1];
z1 = f1->vertices[t->vertexIndices[2]].vertex[2];
x2 = f2->vertices[t->vertexIndices[2]].vertex[0];
y2 = f2->vertices[t->vertexIndices[2]].vertex[1];
z2 = f2->vertices[t->vertexIndices[2]].vertex[2];
glVertex3f (x1 + pol * (x2 - x1),
y1 + pol * (y2 - y1),
z1 + pol * (z2 - z1));
}
glEnd ();
} // end ASDrawMd2FrameInt()
void ASPrecomputeMd2FrameInt(AS_MD2_MODEL *model, int frame1, int frame2, float pol)
{ // begin ASPrecomputeMd2FrameInt()
AS_MD2_FRAME *f1 = &model->frames[frame1];
AS_MD2_FRAME *f2 = &model->frames[frame2];
float x1, y1, z1, x2, y2, z2, *n1, *n2;
int i;
if(frame1 < 0 || frame2 < 0 ||
frame1 >= model->header.numFrames || frame2 >= model->header.numFrames)
return;
for (i = 0; i < model->header.numVertices; i++)
{
n1 = f1->vertices[i].normal;
n2 = f2->vertices[i].normal;
model->prenormal[i][X] = (1.0f - pol) * n1[0] + pol * n2[0];
model->prenormal[i][Y] = (1.0f - pol) * n1[2] + pol * n2[2];
model->prenormal[i][Z] = (1.0f - pol) * -n1[1] + pol * -n2[1];
x1 = f1->vertices[i].vertex[0];
y1 = f1->vertices[i].vertex[1];
z1 = f1->vertices[i].vertex[2];
x2 = f2->vertices[i].vertex[0];
y2 = f2->vertices[i].vertex[1];
z2 = f2->vertices[i].vertex[2];
model->prevertex[i][X] = x1 + pol * (x2 - x1);
model->prevertex[i][Y] = y1 + pol * (y2 - y1);
model->prevertex[i][Z] = z1 + pol * (z2 - z1);
}
} // end ASPrecomputeMd2FrameInt()
void ASDrawPrecomputedMd2Frame(AS_MD2_MODEL *model)
{ // begin ASDrawPrecomputedMd2Frame()
vertlist vert_list[64];
int i, vertnum, index;
BOOL type;
int *command;
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, model->prevertex);
glNormalPointer(GL_FLOAT, 0, model->prenormal);
if(_AS->bCompiledVertexArraySupported)
glLockArraysEXT(0, model->header.numVertices);
command = model->glCommandBuffer;
while ((*command) != 0)
{
if (*command > 0)
{vertnum = *command; command++; type = 0;}//triangle strip
else
{vertnum = - *command; command++; type = 1;}//triangle fan
if (vertnum<0) vertnum = -vertnum;
for (i=0, index = 0;ibCompiledVertexArraySupported)
glUnlockArraysEXT();
} // end ASDrawPrecomputedMd2Frame()
void ASFreeMd2Model(AS_MD2_MODEL *mdl)
{ // begin ASFreeMd2Model()
if(!mdl)
return;
SAFE_FREE(mdl->skins);
SAFE_FREE(mdl->texCoords);
SAFE_FREE(mdl->texCoord);
SAFE_FREE(mdl->triangles);
SAFE_FREE(mdl->prevertex);
SAFE_FREE(mdl->prenormal);
if(mdl->frames)
{
int i;
for(i = 0; i < mdl->header.numFrames; i++)
{
SAFE_FREE(mdl->frames[i].vertices);
SAFE_FREE(mdl->frames[i].vertex);
SAFE_FREE(mdl->frames[i].normal);
}
SAFE_FREE(mdl->frames);
}
SAFE_FREE(mdl->glCommandBuffer);
SAFE_FREE(mdl);
} // end ASFreeMd2Model()
AS_MD2_ANI ASMakeMd2Ani(AS_MD2_MODEL *mdl)
{ // begin ASMakeMd2Ani()
char t_st[16], t_name[16], t_last[16];
int anim_vector[MD2_MAX_FRAMES];
int count_anim, anim_index, t_ln, i;
AS_MD2_ANI animation;
anim_index = 0;
count_anim = 0;
for(i = 0; i < MD2_MAX_FRAMES; i++)
anim_vector[i] = 0;
memset(animation.anim, 0, sizeof(AS_MD2_ANIMATION)*MD2_MAX_FRAMES);
strcpy(animation.anim[count_anim].nameAnimation, "all frames");
animation.anim[count_anim].firstFrame = 0;
animation.anim[count_anim].lastFrame = mdl->header.numFrames;
count_anim++;
strcpy(t_last, "_0_");
for(i = 0; i < mdl->header.numFrames; i++)
{
strcpy(t_st, mdl->frames[i].name);
t_ln = strlen(t_st);
t_ln--;
while(t_st[t_ln] >= '0' && t_st[t_ln] <= '9' || t_st[t_ln] == '_')
t_ln--;
t_ln++;
strncpy(t_name, t_st, t_ln);
t_name[t_ln] = '\0';
if(strcmp(t_name, t_last))
{
anim_vector[anim_index] = i;
anim_index++;
strcpy(animation.anim[count_anim].nameAnimation, t_name);
animation.anim[count_anim].firstFrame = -1;
animation.anim[count_anim].lastFrame = -1;
count_anim++;
}
strcpy(t_last, t_name);
}
anim_vector[anim_index] = mdl->header.numFrames;
anim_index++;
for(i = 0; i < anim_index; i++)
{
animation.anim[i+1].firstFrame = anim_vector[i];
animation.anim[i+1].lastFrame = anim_vector[i+1];
}
animation.count_anim = count_anim;
return animation;
} // end ASMakeMd2Ani()
void AS_Md2GenerateLightNormals(AS_MD2_MODEL *model)
{ // begin AS_Md2GenerateLightNormals()
int i;
float l;
FLOAT3 *fN;
int k;
float facetnormal[3];
int j;
AS_MD2_TRIANGLE *t;
float v1[3], v2[3];
double angle;
if(!model)
return;
for (i = 0; i < model->header.numFrames; i++)
{
/* clear all normals */
for (j = 0; j < model->header.numVertices; j++)
{
model->frames[i].vertices[j].normal[0] = 0.0f;
model->frames[i].vertices[j].normal[1] = 0.0f;
model->frames[i].vertices[j].normal[2] = 0.0f;
}
/* calc normals */
for (j = 0; j < model->header.numTriangles; j++)
{
t = &model->triangles[j];
v1[0] = model->frames[i].vertices[t->vertexIndices[1]].vertex[0] - model->frames[i].vertices[t->vertexIndices[0]].vertex[0];
v1[1] = model->frames[i].vertices[t->vertexIndices[1]].vertex[1] - model->frames[i].vertices[t->vertexIndices[0]].vertex[1];
v1[2] = model->frames[i].vertices[t->vertexIndices[1]].vertex[2] - model->frames[i].vertices[t->vertexIndices[0]].vertex[2];
v2[0] = model->frames[i].vertices[t->vertexIndices[2]].vertex[0] - model->frames[i].vertices[t->vertexIndices[0]].vertex[0];
v2[1] = model->frames[i].vertices[t->vertexIndices[2]].vertex[1] - model->frames[i].vertices[t->vertexIndices[0]].vertex[1];
v2[2] = model->frames[i].vertices[t->vertexIndices[2]].vertex[2] - model->frames[i].vertices[t->vertexIndices[0]].vertex[2];
angle = 1;
facetnormal[0] = (v1[1] * v2[2] - v1[2] * v2[1]) * (float) angle;
facetnormal[1] = (v1[2] * v2[0] - v1[0] * v2[2]) * (float) angle;
facetnormal[2] = (v1[0] * v2[1] - v1[1] * v2[0]) * (float) angle;
for (k = 0; k < 3; k++)
{
model->frames[i].vertices[model->triangles[j].vertexIndices[k]].normal[0] -= facetnormal[0];
model->frames[i].vertices[model->triangles[j].vertexIndices[k]].normal[1] += facetnormal[2];
model->frames[i].vertices[model->triangles[j].vertexIndices[k]].normal[2] -= facetnormal[1];
}
}
/* normalize normals */
for (j = 0; j < model->header.numVertices; j++)
{
fN = &model->frames[i].vertices[j].normal;
l = ASFastSqrt((*fN)[0]*(*fN)[0]+(*fN)[1]*(*fN)[1]+(*fN)[2]*(*fN)[2]);
if(l != 0.0f)
{
(*fN)[0] /= l;
(*fN)[1] /= l;
(*fN)[2] /= l;
}
}
}
} // end AS_Md2GenerateLightNormals()
void AS_Md2_GetBoundingBox(AS_MD2_MODEL *model)
{ // begin AS_Md2_GetBoundingBox()
AS_MD2_TRIANGLE_VERTEX *v;
float minx, maxx, fX;
float miny, maxy, fY;
float minz, maxz, fZ;
int i;
minx = miny = minz = 999999.0f;
maxx = maxy = maxz = -999999.0f;
/* get bounding box */
for (i = 0; i < model->header.numVertices; i++)
{
v = &model->frames[0].vertices[i];
if (v->vertex[0] < minx)
minx = v->vertex[0];
else if (v->vertex[0] > maxx)
maxx = v->vertex[0];
if (v->vertex[1] < miny)
miny = v->vertex[1];
else if (v->vertex[1] > maxy)
maxy = v->vertex[1];
if (v->vertex[2] < minz)
minz = v->vertex[2];
else if (v->vertex[2] > maxz)
maxz = v->vertex[2];
}
model->fBoundingBox[0][X] = minx;
model->fBoundingBox[1][X] = maxx;
if(maxx > minx)
fX = maxx-minx;
else
fX = minx-maxx;
model->fBoundingBox[0][Y] = miny;
model->fBoundingBox[1][Y] = maxy;
if(maxy > miny)
fY = maxy-miny;
else
fY = miny-maxy;
model->fBoundingBox[0][Z] = minz;
model->fBoundingBox[1][Z] = maxz;
if(maxz > minz)
fZ = maxz-minz;
else
fZ = minz-maxz;
model->fBoundigBoxSize = fX;
if(fY > model->fBoundigBoxSize)
model->fBoundigBoxSize = fY;
if(fZ > model->fBoundigBoxSize)
model->fBoundigBoxSize = fZ;
model->fBoundigBoxSize /= 2;
} // end AS_Md2_GetBoundingBox()