www.pudn.com > QuadTreeLOD4cs.rar > Loaders.cpp, change:2003-06-12,size:10124b
//==================================================================//
//==================================================================//
//= Loaders.cpp ====================================================//
//==================================================================//
//= Original coder: Trent Polack (ShiningKnight) ===================//
//==================================================================//
//==================================================================//
#include "loaders.h"
#include <stdio.h>
#include "math.h"
//------------------------------------------------------------------//
//------------------------------------------------------------------//
//- DEFINITIONS ----------------------------------------------------//
//------------------------------------------------------------------//
//------------------------------------------------------------------//
//------------------------------------------------------------------//
//- bool LoadTGA(char*, GLfloat, GLfloat) --------------------------//
//------------------------------------------------------------------//
//- Description: This function loads a truevision TARGA into the -//
//- CTexture class object that it represents. -//
//------------------------------------------------------------------//
//- Big thanks to NeHe for this one -//
//------------------------------------------------------------------//
//------------------------------------------------------------------//
//- bool LoadBMP(char*, GLfloat, GLfloat) --------------------------//
//------------------------------------------------------------------//
//- Description: This function loads a Windows Bitmap into the -//
//- CTexture class object that it represents. -//
//------------------------------------------------------------------//
//- Big thanks to NeHe for this one -//
//------------------------------------------------------------------//
//------------------------------------------------------------------//
//------------------------------------------------------------------//
//- CMD2 CODE -------------------------------------------------------//
//------------------------------------------------------------------//
//------------------------------------------------------------------//
//------------------------------------------------------------------//
//- bool Load(char*) -----------------------------------------------//
//------------------------------------------------------------------//
//- Description: This funtion loads a Quake 2 model (.md2) into the-//
//- program! .md2s are great, because there are a TON-//
//- out there (www.polycount.com mainly), and they -//
//- include keyframes inside of them! -//
//------------------------------------------------------------------//
//- Big thanks to Justin "Blackscar" Eslinger for this one... -//
//- though I only used a little bit of his base code, and even that-//
//- I had to edit heavily... So I don't see why I'm giving him -//
//- any credit what-so-ever. Oh well, he's a cool guy anyway. :D -//
//------------------------------------------------------------------//
bool CMD2::Load(char* filename)
{
FILE* file;
MD2_HEADER header;
//Open the .md2 model file
if((file= fopen(filename, "rb"))==NULL)
{
::MessageBox(NULL,"error open md2 file.","error",MB_OK);
::ExitProcess(1);
return false;
}
//Read in the header
fread(&header, sizeof(MD2_HEADER), 1, file);
//Create space for the frame information
m_pFrames= new char[header.m_nFrameSize*header.nFrames];
//Check to see if it allocated correctly
if(m_pFrames==NULL)
return false;
//Zoom to the correct spot in the file
fseek(file, header.offsetFrames, SEEK_SET);
fread(m_pFrames, header.m_nFrameSize*header.nFrames, 1, file);
//Create space for the GL command information (whether or not to use tri strips, or tri fans)
m_pGLCommands= new long [header.nGlCommands];
//Check to see if it allocated correctly
if(m_pGLCommands==NULL)
return false;
//Zoom to the correct spot in the file
fseek(file, header.offsetGlCommands, SEEK_SET);
fread(m_pGLCommands, header.nGlCommands*sizeof(long), 1, file);
//Move the important information from the header, to the permanent class info.
m_nFrames = header.nFrames;
endFrame = m_nFrames;
m_nGlCommands= header.nGlCommands;
m_nFrameSize = header.m_nFrameSize;
m_nTriangles = header.nTriangles;
fclose(file);
return true;
}
//------------------------------------------------------------------//
//- void Render(int) -----------------------------------------------//
//------------------------------------------------------------------//
//- Description: This function renders an .md2 model with the given-//
//- frame of animation. -//
//------------------------------------------------------------------//
//- Ok, now I really owe Justin a big one for this... His code -//
//- seems to be the only one that took advantage of the gl commands-//
//- that are within the md2 file (for speed)! -//
//------------------------------------------------------------------//
void CMD2::Render(int numFrame)
{
MD2_FRAME_PTR currentFrame;
MD2_MODELVERTEX vertList[100];
CVertex v1;
CVertex v2;
CVertex v3;
long* command;
float texcoord[2];
int loop;
int vertIndex;
int type;
int numVertex;
int index;
//Get the current frame and gl command information
currentFrame= (MD2_FRAME*) ((char*)m_pFrames+m_nFrameSize*numFrame);
command = m_pGLCommands;
//Make sure that the command doesn't equal 0, and if it doesn't lets start rendering!
while((*command)!=0)
{
if(*command>0) //This is a triangle strip
{
numVertex= *command;
command++;
type= 0;
}
else //This is a triangle fan
{
numVertex= - *command;
command++;
type= 1;
}
if(numVertex<0)
numVertex= -numVertex;
index= 0;
//Fill the vertex list information
for(loop=0; loop<numVertex; loop++)
{
vertList[index].u= *((float*)command);
command++;
vertList[index].v= *((float*)command);
command++;
vertIndex= *command;
command++;
vertList[index].x= ( (currentFrame->vertices[vertIndex].vertex[0]*
currentFrame->scale[0])+
currentFrame->translate[0]);
vertList[index].z= -((currentFrame->vertices[vertIndex].vertex[1]*
currentFrame->scale[1])+
currentFrame->translate[1]);
vertList[index].y= ( (currentFrame->vertices[vertIndex].vertex[2]*
currentFrame->scale[2])+
currentFrame->translate[2]);
index++;
}
//If the .md2 was optimized for use with triangle strips...
if(type==0)
{
glBegin(GL_TRIANGLE_STRIP);
for(loop=0; loop<index; loop++)
{
v1.vertex[0]=(vertList[loop].x);
v1.vertex[1]=(vertList[loop].y);
v1.vertex[2]=(vertList[loop].z);
texcoord[0]= vertList[loop].u;
texcoord[1]= vertList[loop].v;
glTexCoord2fv(texcoord);
glVertex3fv(v1.vertex);
}
glEnd();
}
//If the .md2 was made for use with triangle fans...
else
{
glBegin(GL_TRIANGLE_FAN);
for(loop=0; loop<index; loop++)
{
v1.vertex[0]=(vertList[loop].x);
v1.vertex[1]=(vertList[loop].y);
v1.vertex[2]=(vertList[loop].z);
texcoord[0]= vertList[loop].u;
texcoord[1]= vertList[loop].v;
glTexCoord2fv(texcoord);
v1.SendToOGL();
}
glEnd();
}
// char buf[255];
// sprintf(buf,"x y z = %f %f %f\n",v1.vertex[0],v1.vertex[1],v1.vertex[2]);
// OutputDebugString(buf);
}
}
float CMD2::GetPercent()
{
static lastT = GetTickCount();
float speed = 200.0;
static nowT = 0;
nowT = GetTickCount();
if(nowT-lastT>speed)
{
m_nCurrentFrame = (m_nCurrentFrame+1)%endFrame;
m_nNextFrame = (m_nCurrentFrame+1)%endFrame;
lastT = nowT;
return 1;
}
else
{
return (nowT-lastT)/speed;
}
}
void CMD2::Animate()
{
MD2_FRAME_PTR pCurrentFrm;
MD2_FRAME_PTR pNextFrm;
CVertex v1,v2;
long* pCommand;
int vertIndex;
int type;
int numVertex;
//Get the current frame and gl pCommand information
pCurrentFrm= (MD2_FRAME*) ((char*)m_pFrames+m_nFrameSize*m_nCurrentFrame);
pNextFrm = (MD2_FRAME*) ((char*)m_pFrames+m_nFrameSize*m_nNextFrame);
pCommand = m_pGLCommands;
float t = GetPercent();
while((*pCommand)!=0)
{
if(*pCommand>0) //This is a triangle strip
{
numVertex= *pCommand;
pCommand++;
type= 0;
}
else //This is a triangle fan
{
numVertex= - *pCommand;
pCommand++;
type= 1;
}
if(numVertex<0)
numVertex= -numVertex;
//Fill the vertex list information
if(type==0)
glBegin(GL_TRIANGLE_STRIP);
else
glBegin(GL_TRIANGLE_FAN);
for(int loop=0; loop<numVertex; loop++)
{
float u= *((float*)pCommand);
pCommand++;
float v= *((float*)pCommand);
pCommand++;
vertIndex= *pCommand;
pCommand++;
v1.vertex[0] = pCurrentFrm->vertices[vertIndex].vertex[0]* pCurrentFrm->scale[0] +
pCurrentFrm->translate[0];
v1.vertex[1] = pCurrentFrm->vertices[vertIndex].vertex[2]* pCurrentFrm->scale[2]+
pCurrentFrm->translate[2];
v1.vertex[2] = -(pCurrentFrm->vertices[vertIndex].vertex[1]* pCurrentFrm->scale[1]+
pCurrentFrm->translate[1]);
v2.vertex[0] = pNextFrm->vertices[vertIndex].vertex[0]* pNextFrm->scale[0] +
pNextFrm->translate[0];
v2.vertex[1] = pNextFrm->vertices[vertIndex].vertex[2]* pNextFrm->scale[2]+
pNextFrm->translate[2];
v2.vertex[2] = -(pNextFrm->vertices[vertIndex].vertex[1]* pNextFrm->scale[1]+
pNextFrm->translate[1]);
glTexCoord2f(u,v);
glVertex3f(v1.vertex[0]+t*(v2.vertex[0]-v1.vertex[0]),
v1.vertex[1]+t*(v2.vertex[1]-v1.vertex[1]),
v1.vertex[2]+t*(v2.vertex[2]-v1.vertex[2]));
}
glEnd();
}
}