⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 md2model.h

📁 Ion Team Lord Of The Rings Demo 模拟指环王的3D游戏 VS.NET编译 里面提供高级渲染算法
💻 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 + -