📄 md2model.h
字号:
/* Used these great documents to learn this format:
http://www.ugrad.cs.jhu.edu/~dansch/md2/ <-- nice format reference
Chapter 18 of OpenGL Game Programming. <-_
MD2 Model Example - OOP Author: Kevin Hawkins <-- helpful :=)
Mustata Bogdan and Mirko R. Teran's Md2 Loading Code! <-- helped me on the blasted
glcommands thing, of which
i knew nothing :)
Thanx go2 chumbalum soft for making not only a great modeling program,
but also for making available the md2viewer code :)
Thank ye all! */
#define MAX_ANIMS 40
inline string RealName (string s)
{
Uint16 i;
for (i=0;i<s.size();i++)
if (s[i]=='0' || s[i]=='1' || s[i]=='2' || s[i]=='3' || s[i]=='4' || s[i]=='5'
|| s[i]=='6' || s[i]=='7' || s[i]=='8' || s[i]=='9')
break;
return s.substr(0,i);
}
#define NUMVERTEXNORMALS 162
float AVertexNormals[NUMVERTEXNORMALS][3] = {
#include "anorms.h"
};
typedef struct
{
int iIdent; // A "magic number" used to identify the file
int iVersion; // Version number of the file. Always 8.
int iSkinWidth; // Width of the skin(s) in pixels.
int iSkinHeight; // Height of the skin(s) in pixels.
int iFrameSize; // Size of each frame in bytes.
int iNumSkins; // Number of skins associated with this model.
int iNumVertices; // Number of vertices in each frame.
int iNumTexCoords; // Number of texture coordinates.
int iNumTriangles; // Number of triangles in each frame.
int iNumGlCommands; // Number of dwords (4 bytes) in the gl command list.
int iNumFrames; // Number of Frames.
int iOffsetSkins; // Offset, in bytes from the start of the file, to the list of skin names.
int iOffsetTexCoords; // Offset, in bytes from the start of the file, to the list of texture coordinates.
int iOffsetTriangles; // Offset, in bytes from the start of the file, to the list of triangles.
int iOffsetFrames; // Offset, in bytes from the start of the file, to the list of Frames.
int iOffsetGlCommands; // Offset, in bytes from the start of the file, to the gl command list.
int iOffsetEnd; // Offset, in bytes from the start of the file, to the end (size of the file).
}
Md2Header; // The Md2 File Header!
typedef struct
{
byte bVertex[3]; // THE VERTEX!
byte bLightNormalIndex; // am i ever gonna use this?
}
Md2TriangleVertex;
typedef struct
{
short VertexIndices[3];
short TextureIndices[3];
}
Md2Triangle;
typedef struct
{
short u, v;
}
Md2TextureCoordinate;
struct Md2FrameInfo
{
string Name;
int Start,End;
};
class Md2Model : public Model
{
public:
~Md2Model()
{
delete [] VertexList;
delete [] TexCoords;
delete [] Mesh;
delete [] glCommandBuffer;
delete [] NormalList;
}
Md2Header Header; // the header!
int iFirstFrame, iLastFrame, iCurrentFrame; //Frame Numbers (explicit names, come on!)
float fInterpol; // Used for linear interpolation
Md2Triangle *Mesh; // THE MESH (or triangle list) (uses indices)
Md2TextureCoordinate *TexCoords; // texture coordinate list
int *glCommandBuffer;
GLuint Texture;
Vector3d *VertexList, *NormalList; // vertex list and normals list
Md2FrameInfo Animations[MAX_ANIMS];
int iNumOfAnims;
ModelErrorCode Load(string meshFilename, string skinFilename)
{
ModelErrorCode Error;
Error = LoadMesh(meshFilename);
if (Error!=mOK)
return Error;
Error=LoadSkin(skinFilename);
if (Error!=mOK)
return Error;
return mOK;
}
ModelErrorCode LoadMesh(string Filename)
{
FILE *Md2File;
int i=0,j=0,t=0;
// open the model file
#ifdef Log
fprintf(LogFile,"Attempting To Load Md2 File: %s\n",Filename.c_str());
#endif
Md2File = fopen(Filename.c_str(), "rb");
if (Md2File == NULL)
{
#ifdef Log
fprintf(LogFile,"Could Not Open Md2 File: %s\n", Filename.c_str());
#endif
return errFileDoesNotExist;
}
fread(&Header, 1, sizeof(Md2Header), Md2File); // reads the header
char cVersion[5];
sprintf(cVersion, "%c%c%c%c", Header.iIdent, Header.iIdent>>8, Header.iIdent>>16, Header.iIdent>>24);
if ( strcmp(cVersion, "IDP2") || Header.iVersion != 8)
{
#ifdef Log
fprintf(LogFile,"Wrong File Type In Md2 File: %s\n", Filename.c_str());
#endif
return errNotModelFile;
}
fseek(Md2File, Header.iOffsetTexCoords, SEEK_SET);
TexCoords = new Md2TextureCoordinate[Header.iNumTexCoords];
for (i=0; i<Header.iNumTexCoords; i++)
fread(&TexCoords[i], sizeof(Md2TextureCoordinate), 1, Md2File);
fseek(Md2File, Header.iOffsetTriangles, SEEK_SET);
Mesh = new Md2Triangle[Header.iNumTriangles];
for (i=0; i<Header.iNumTriangles; i++)
fread(&Mesh[i], sizeof(Md2Triangle), 1, Md2File);
fseek(Md2File, Header.iOffsetFrames, SEEK_SET);
float fScale[3];
float fTranslate[3];
char cName[16];
string CurrentName, PreviousName;
int frames[2]={0,0};
Md2TriangleVertex Vertex;
VertexList = new Vector3d[Header.iNumFrames * Header.iNumVertices];
NormalList = new Vector3d[Header.iNumFrames * Header.iNumVertices];
iNumOfAnims=0;
for (i=0; i<Header.iNumFrames; i++)
{
fread(&fScale, sizeof(float), 3, Md2File);
fread(&fTranslate, sizeof(float), 3, Md2File);
fread(&cName, 1, 16, Md2File);
PreviousName=CurrentName;
CurrentName=RealName(cName);
if (CurrentName!=PreviousName)
{
frames[1]=i-1;
if (i!=0)
{
Animations[iNumOfAnims].Name=PreviousName;
Animations[iNumOfAnims].Start=frames[0];
Animations[iNumOfAnims].End=frames[1];
iNumOfAnims++;
}
frames[0]=i;
}
frames[1]=i-1;
#ifdef Log
#ifdef ExtraLog
fprintf(LogFile," Frame Number %d has the name %s.\n",i,cName );
#endif
#endif
for (j=0; j<Header.iNumVertices;j++)
{
fread(&Vertex, sizeof(Md2TriangleVertex), 1, Md2File);
int t=i*Header.iNumVertices + j;
VertexList[t].Coords[0] = (float)((int) Vertex.bVertex[0]) * fScale[0] + fTranslate[0];
VertexList[t].Coords[2] = -1.0f * ( (float)((int)Vertex.bVertex[1]) * fScale[1] + fTranslate[1]);
VertexList[t].Coords[1] = (float)((int)Vertex.bVertex[2]) * fScale[2] + fTranslate[2];
NormalList[t].Coords[0] = AVertexNormals[Vertex.bLightNormalIndex][0];
NormalList[t].Coords[2] = AVertexNormals[Vertex.bLightNormalIndex][1];
NormalList[t].Coords[1] = AVertexNormals[Vertex.bLightNormalIndex][2];
}
}
if (i!=0)
{
Animations[iNumOfAnims].Name=PreviousName;
Animations[iNumOfAnims].Start=frames[0];
Animations[iNumOfAnims].End=frames[1];
iNumOfAnims++;
}
frames[0]=i;
fseek(Md2File, Header.iOffsetGlCommands, SEEK_SET);
glCommandBuffer = new int[Header.iNumGlCommands];
fread(glCommandBuffer, sizeof(int), Header.iNumGlCommands, Md2File);
#ifdef Log
fprintf(LogFile,"Loaded Model (%s) Successfuly!\n", Filename.c_str());
#endif
fclose (Md2File);
return mOK;
}
ModelErrorCode LoadSkin(string Filename)
{
Texture = LoadTexture(Filename,CT_FIND);
return mOK;
}
void SetFrames(int FirstFrame, int LastFrame)
{
iFirstFrame = FirstFrame;
iLastFrame=LastFrame;
}
void SetAnimation(string ModelState)
{
int i;
for (i=0;i<iNumOfAnims;i++)
{
if (Animations[i].Name==ModelState)
break;
}
SetFrames(Animations[i].Start,Animations[i].End);
}
inline void Draw(int FrameNumber)
{
int i = 0;
int val = glCommandBuffer[i++];
Bind(Texture);
while (val != 0)
{
int count;
if (val > 0)
{
glBegin(GL_TRIANGLE_STRIP);
count = val;
}
else
{
glBegin(GL_TRIANGLE_FAN);
count = -val;
}
while (count--)
{
float s = * (float *) &glCommandBuffer[i++];
float t = * (float *) &glCommandBuffer[i++];
int index = glCommandBuffer[i++];
glTexCoord2f(s, t);
glNormal3fv(NormalList[Header.iNumVertices*FrameNumber+index].Coords);
glVertex3fv(VertexList[Header.iNumVertices*FrameNumber+index].Coords);
}
glEnd();
val = glCommandBuffer[i++];
}
}
inline void Animate(float Fraction, bool looping=true)
{
int CurrentFrame;
float CurrentFrameFraction;
if (looping)
{
CurrentFrame = (int)((float)iFirstFrame + (float)(iLastFrame+1-iFirstFrame)*Fraction);
CurrentFrameFraction = (float)((float)iFirstFrame + (float)(iLastFrame+1-iFirstFrame)*Fraction) - (float)(CurrentFrame);
}
else
{
CurrentFrame = (int)((float)iFirstFrame + (float)(iLastFrame-iFirstFrame)*Fraction);
CurrentFrameFraction = (float)((float)iFirstFrame + (float)(iLastFrame-iFirstFrame)*Fraction) - (float)(CurrentFrame);
}
int i = 0, Index, Index2;
int val = glCommandBuffer[i++];
Bind(Texture);
while (val != 0)
{
int count;
if (val > 0)
{
glBegin(GL_TRIANGLE_STRIP);
count = val;
}
else
{
glBegin(GL_TRIANGLE_FAN);
count = -val;
}
while (count--)
{
float s = * (float *) &glCommandBuffer[i++];
float t = * (float *) &glCommandBuffer[i++];
int index = glCommandBuffer[i++];
glTexCoord2f(s, t);
Index = (Header.iNumVertices*CurrentFrame)+index;
if (CurrentFrame==iLastFrame)
Index2 = (Header.iNumVertices*(iFirstFrame))+index;
else
Index2 = (Header.iNumVertices*(CurrentFrame+1))+index;
glNormal3fv((NormalList[Index] + ((NormalList[Index2]-NormalList[Index])*CurrentFrameFraction)).Coords);
glVertex3fv((VertexList[Index] + ((VertexList[Index2]-VertexList[Index])*CurrentFrameFraction)).Coords);
}
glEnd();
val = glCommandBuffer[i++];
}
}
inline void TwoFrameInterpolate(float Fraction, int FirstFrame, int SecondFrame)
{
int i = 0, Index, Index2;
int val = glCommandBuffer[i++];
Bind(Texture);
while (val != 0)
{
int count;
if (val > 0)
{
glBegin(GL_TRIANGLE_STRIP);
count = val;
}
else
{
glBegin(GL_TRIANGLE_FAN);
count = -val;
}
while (count--)
{
float s = * (float *) &glCommandBuffer[i++];
float t = * (float *) &glCommandBuffer[i++];
int index = glCommandBuffer[i++];
glTexCoord2f(s, t);
Index = (Header.iNumVertices*FirstFrame)+index;
Index2 = (Header.iNumVertices*(SecondFrame))+index;
glNormal3fv((NormalList[Index] + ((NormalList[Index2]-NormalList[Index])*Fraction)).Coords);
glVertex3fv((VertexList[Index] + ((VertexList[Index2]-VertexList[Index])*Fraction)).Coords);
}
glEnd();
val = glCommandBuffer[i++];
}
}
void DrawWithEMap(int FrameNumber)
{
int i = 0;
int val = glCommandBuffer[i++];
glEnable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S
glEnable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T
Bind(Texture);
while (val != 0)
{
int count;
if (val > 0)
{
glBegin(GL_TRIANGLE_STRIP);
count = val;
}
else
{
glBegin(GL_TRIANGLE_FAN);
count = -val;
}
while (count--)
{
float s = * (float *) &glCommandBuffer[i++];
float t = * (float *) &glCommandBuffer[i++];
int index = glCommandBuffer[i++];
glTexCoord2f(s, t);
glNormal3fv(NormalList[Header.iNumVertices*FrameNumber+index].Coords);
glVertex3fv(VertexList[Header.iNumVertices*FrameNumber+index].Coords);
}
glEnd();
val = glCommandBuffer[i++];
}
glDisable(GL_TEXTURE_GEN_S); // Enable Texture Coord Generation For S
glDisable(GL_TEXTURE_GEN_T); // Enable Texture Coord Generation For T
}
void UnLoad()
{
}
}
;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -