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()