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

📄 cmap.h

📁 Ion Team Lord Of The Rings Demo 模拟指环王的3D游戏 VS.NET编译 里面提供高级渲染算法
💻 H
字号:
//////////////////////////////////////////////
//	MAP LOADER AND RENDER
//	TODO:OPTIMIZE, MORE EFFECTS, SIMPLIFY
////////////////////////////////////////////
#include <math.h>		//sqrt function
#include <stdlib.h>		//mem function
#include <stdio.h>		//sprintf

#define CMF_FILTER CT_MIPMAP	//specify filter used

//extern (HWND)0 (HWND)0;	//for msg boxes
//(HWND)0 (HWND)0=0;		//use for alternative

//////////////////////////

struct SPlane
  {
    double Vect[3];
    float Normal[3];
    double Dist;
  };

/////////////////

struct SVertex
  {
    double Coord[3];
    double U;
    double V;
  };

////////////////////

struct SPolygon
  {
    unsigned long TextureID;
    SPlane Plane;
    unsigned long NumVertices;
    SVertex *Vertices;
  };

struct SProperty
  {
    char *PropName;
    char *PropValue;
  };

/////////////////////

struct SEntity
  {
    char Class[40];
    unsigned long NumProps;
    SProperty *Properties;
    unsigned long NumPoly;
    SPolygon *Polygons;
  };

///////////////////////////////////////////

//general structure

struct STriangle
  {
    double Coords[9]; //x,y,z *3
    float Normal[3]; //normal vector
    double TexCoords[6]; //texture coords u,v *3
    int TexIndex;		//texture index
  }
;

/////////////////

struct SCMFhdr
  {
    char ID[3];
    char Version;
    unsigned long NumberOfWADfiles;
    unsigned long NumberOfEntities;
    unsigned long NumberOfTextures;
    char *WADFileNames;
    char TextureNames[2000];
    SEntity *Entities;
  };


///////////////////////////////////////////////////////////////////////

class CMap
  {
  public:

    void Init(char *filename);	//load cmf
    void Destroy();				//still it's likely to miss some stuff
    void OldDisplay();				//this is an old,slower,draw function, tha used polygons
    void Draw();					//this is new (and improved :))	function, faster, draws triangles
  private:
    void CreateTriangles();
    void AddTexture(char *filename);	//add texture name (in order)
    void LoadAllTextures();
    BOOL CLoadTexture(GLuint *texPntr, char* name);
    GLuint maptexture[256];		//space for textures
    int texptr;					//current texture indicator
    int mgetc();							//emulate fgetc() (lame technic)
    void mread(void* dest,size_t size);		//emulate fread()  (also lame)
    long mptr;				//the reference pointer for the above 2 functions

    SCMFhdr hdr;			//the main data storage structure

    char tempstr[200];		//all purpose string MAX STRING=200
    int a;	//loop counters
    int b;
    FILE *file; //file handle
    char *buffer;	//put all file data here *POSSIBLE PROBLEM*
    long fsize;	//hold file size
  public:	//public ,so  the collider can use them
    STriangle *Triangles;	//the new data type
    int NumTriangles;		//the number of triangles
  }
;

//////////////////////////////////////////////////////////////////////////

void CMap::Init(char *filename)
{
  NumTriangles=0;
  mptr=0;	//important	, resets the memory pointer
  texptr=0;	//important	, resets the texture pointer

  FILE *file;	//pointer to stream

  file=fopen(filename,"rb");	//open file

  long curpos=ftell(file);	//store position in file
  fseek(file,0,SEEK_END);	//goto end of file
  fsize = ftell(file); //store file size
  fseek(file,curpos,SEEK_SET);	//return to beggining of file

  buffer=(char*)malloc(fsize);	//allocate space for *ENTIRE FILE*

  if(buffer==NULL)
    MessageBox((HWND)0,"Not Enough Memory","Error",0);	//check for error

  //read it and check for errors
  if((long)fread(buffer,1,fsize,file)!=fsize)
    MessageBox((HWND)0,"FREAD error","Error",0);

  mread(&hdr,16);	//read hdr details

  //check file identifier
  if(hdr.ID[0] != 'C')
    MessageBox((HWND)0,"Wrong file type","Error",0);
  if(hdr.ID[1] != 'M')
    MessageBox((HWND)0,"Wrong file type","Error",0);
  if(hdr.ID[2] != 'F')
    MessageBox((HWND)0,"Wrong file type","Error",0);

  //check version
  if(hdr.Version != 2)
    MessageBox((HWND)0,"Wrong version","Error",0);

  a=0;
  while(a!=(signed int)hdr.NumberOfWADfiles)
    {
      while(mgetc()!=0)
        ;	//skip wad name because aren't needed
      a++;
    }

  //read in texture names
  a=0;
  b=0;
  while(a!=(int)hdr.NumberOfTextures)
    {
      hdr.TextureNames[b]=mgetc();
      if(hdr.TextureNames[b]==0)
        a++;
      b++;
    }

  //get mem for entity *ONLY READY FOR 1 -> "WORLDSPAWN"*
  hdr.Entities=(SEntity*)malloc(sizeof(SEntity));

  mread(hdr.Entities[0].Class,11);	//fill with worldspawn0

  //read no properties
  mread(&hdr.Entities[0].NumProps,4);

  //skip it
  a=0;
  while(a!=(int)hdr.Entities[0].NumProps*2)
    {
      if(mgetc()==0)
        a++;
    }

  //read no polygons
  mread(&hdr.Entities[0].NumPoly,4);

  //mem for polys
  hdr.Entities[0].Polygons=(SPolygon*)malloc(sizeof(SPolygon)*hdr.Entities[0].NumPoly);


  //loop for all polys
  for(a=0;a!=(int)hdr.Entities[0].NumPoly;a++)
    {

      mread(&hdr.Entities[0].Polygons[a].TextureID,4);
      mread(&hdr.Entities[0].Polygons[a].Plane,32);
      //Normalize the vector

      float lenght=(float)sqrt((hdr.Entities[0].Polygons[a].Plane.Vect[0]*hdr.Entities[0].Polygons[a].Plane.Vect[0])+
                               (hdr.Entities[0].Polygons[a].Plane.Vect[1]*hdr.Entities[0].Polygons[a].Plane.Vect[1])+
                               (hdr.Entities[0].Polygons[a].Plane.Vect[2]*hdr.Entities[0].Polygons[a].Plane.Vect[2]));

      hdr.Entities[0].Polygons[a].Plane.Normal[0]=(float)hdr.Entities[0].Polygons[a].Plane.Vect[0]/lenght;
      hdr.Entities[0].Polygons[a].Plane.Normal[1]=(float)hdr.Entities[0].Polygons[a].Plane.Vect[1]/lenght;
      hdr.Entities[0].Polygons[a].Plane.Normal[2]=(float)hdr.Entities[0].Polygons[a].Plane.Vect[2]/lenght;


      //end normalizing and procede

      //sprintf(tempstr,"Plane eq: %f , %f , %f",hdr.Entities[0].Polygons[a].Plane.Normal[0],hdr.Entities[0].Polygons[a].Plane.Normal[1],hdr.Entities[0].Polygons[a].Plane.Normal[2]);
      //MessageBox((HWND)0,tempstr,"Error",0);	//check for error

      mread(&hdr.Entities[0].Polygons[a].NumVertices,4);

      //aloocate mem for vertices
      hdr.Entities[0].Polygons[a].Vertices=(SVertex*)malloc(40*hdr.Entities[0].Polygons[a].NumVertices);

      //check for error and tell stuff
      if(hdr.Entities[0].Polygons[a].Vertices==NULL)
        {
          sprintf(tempstr,"Mem Vertex[%i] was for %i polys",a,hdr.Entities[0].Polygons[a].NumVertices);
          MessageBox((HWND)0,tempstr,"Error",0);	//check for error
        }

      NumTriangles+=(hdr.Entities[0].Polygons[a].NumVertices-2);

      //loop vertices (don't know why but it's the only way it works)
      for(b=0;b!=(int)hdr.Entities[0].Polygons[a].NumVertices;b++)
        {
          //read data for 1 vertex
          mread(&hdr.Entities[0].Polygons[a].Vertices[b],40);
        }

    }

  //////////////////////////////////////LOAD THE ENTITIES(POWERUPS)
  for(a=0;a!=(int)hdr.NumberOfEntities-1;a++)
    {
      char EntName[8];	//max for now
      char Values[40];	//scan values in here
      float tx,ty,tz;	//temporary
      mread(EntName,8);
      mgetc();
      mgetc();
      mgetc();
      mgetc();	//skip 4 bytes
      mgetc();
      mgetc();
      mgetc();
      mgetc();
      mgetc();
      mgetc();
      mgetc();//skip 6 bytes ("origin")

      memset(Values,0,40);	//zero mem

      b=0;

      for(;;)
        {
          Values[b]=mgetc();
          if(Values[b]==0)
            break;
          b++;
        }

      if(sscanf(Values,"%f %f %f ",&tx,&ty,&tz)==0)
        MessageBeep(0xffff);
    }
  /////////////////////////////////////FREE MEM
  free(buffer);	//free file memory
  fclose(file);	//close file

  LoadAllTextures(/*int filter*/);
  CreateTriangles();
}

//////////////////////////////////////////////////////////////////////////

void CMap::Destroy()
{
  glDeleteTextures(hdr.NumberOfTextures,maptexture);		//free gl textures

  for(a=0;a!=(int)hdr.Entities[0].NumPoly;a++)
    free(hdr.Entities[0].Polygons[a].Vertices);

  free(hdr.Entities[0].Polygons);

  free(hdr.Entities);

  //free(hdr.WADFileNames);
  free(Triangles);
}

///////////////////////////////////////////////////////////////////////////

void CMap::OldDisplay()
{
  a=0;

  while(a!=(int)hdr.Entities[0].NumPoly)
    {
      b=0;

      //POSSIBLE SLOW DOWN
      Bind(maptexture[hdr.Entities[0].Polygons[a].TextureID]);

      glNormal3f(hdr.Entities[0].Polygons[a].Plane.Normal[0],
                 hdr.Entities[0].Polygons[a].Plane.Normal[1],
                 hdr.Entities[0].Polygons[a].Plane.Normal[2]);

      glBegin(GL_POLYGON);	//start polygon

      while(b!=(int)hdr.Entities[0].Polygons[a].NumVertices)
        {

          glTexCoord2d(-hdr.Entities[0].Polygons[a].Vertices[b].U,
                       -hdr.Entities[0].Polygons[a].Vertices[b].V);	//HACK, don't know why but should be linked with the "mirror" bug
          glVertex3dv((double*)hdr.Entities[0].Polygons[a].Vertices[b].Coord);

          b++;
        }

      glEnd();	//end poly

      a++;
    }

}

///////////////////////////////////////////////////////////////////////////

void CMap::mread(void *dest,size_t size)
{
  //warn if  error is eminent
  if(mptr>fsize)
    MessageBox((HWND)0,"Going beyond mem","Error",0);
  memcpy(dest,&buffer[mptr],size);
  mptr+=size;

}

///////////////////////////////////////////////////////////////////////////

int CMap::mgetc()
{
  //warn if  error is eminent
  if(mptr>fsize)
    MessageBox((HWND)0,"Going beyond mem","Error",0);

  mptr++;
  return (int)buffer[mptr-1];	// the "-1" is because "mptr++;" should be after this
}

////////////////////////////////////////////////////////////////////////////


BOOL CMap::CLoadTexture(GLuint *texPntr,char *name)
{
  FILE *file = fopen(name,"r");//open for check

  if(file==NULL)
    {
      MessageBeep(0xFFFF);
      char temp[80];
      sprintf(temp,"Unable to open texture: %s",name);
      MessageBox(0,temp,"Error",0);
    }
  else
    fclose(file);



  *texPntr = LoadTexture(name,CT_JPG,CMF_FILTER);

  return 1;
}

////////////////////////////////////////////////////////////////////

void CMap::AddTexture(char *filename)
{
  CLoadTexture(&maptexture[texptr],filename);
  texptr++;
}

///////////////////////////////////////////////////////////////////

void CMap::LoadAllTextures()
{
  char texname[80];	//use for temporary storage
  char callname[80];	//for  name+dir
  int	read=-1;
  int loop=0;

  a=0;
  b=0;

  for(;;)
    {
      read=hdr.TextureNames[b];	//read a char
      texname[a]=hdr.TextureNames[b];

      if(read==0)		//if its 0 get ready to load
        {
          sprintf(callname,"data/CMap/%s.jpg",texname);
          AddTexture(callname);
          loop++;
          a=-1;	//-1 because now comes a++;
          //memset(texname,0,80);
        }

      a++;	//texname loop counter
      b++;	//same for texturenames
      if(loop==(int)hdr.NumberOfTextures)
        break;
    }

}

/////////////////////////////////////

void CMap::CreateTriangles()
{
  int c=0;	//index
  Triangles=(STriangle*)malloc(sizeof(STriangle)*NumTriangles);	//allocate space

  if(!Triangles)
    MessageBox((HWND)0,"no mem for triangle","error",0);

  a=0;

  while(a!=(int)hdr.Entities[0].NumPoly)
    {
      for(b=0;(int)(hdr.Entities[0].Polygons[a].NumVertices-2)!=b;b++)
        {
          //just copy
          Triangles[c].TexIndex=hdr.Entities[0].Polygons[a].TextureID;

          Triangles[c].Normal[0]=-hdr.Entities[0].Polygons[a].Plane.Normal[0];
          Triangles[c].Normal[1]=hdr.Entities[0].Polygons[a].Plane.Normal[1];
          Triangles[c].Normal[2]=hdr.Entities[0].Polygons[a].Plane.Normal[2];

          //first vertex is always the same
          Triangles[c].Coords[0]=-hdr.Entities[0].Polygons[a].Vertices[0].Coord[0];
          Triangles[c].Coords[1]=hdr.Entities[0].Polygons[a].Vertices[0].Coord[1];
          Triangles[c].Coords[2]=hdr.Entities[0].Polygons[a].Vertices[0].Coord[2];

          Triangles[c].TexCoords[0]=hdr.Entities[0].Polygons[a].Vertices[0].U;
          Triangles[c].TexCoords[1]=hdr.Entities[0].Polygons[a].Vertices[0].V;

          Triangles[c].TexCoords[2]=hdr.Entities[0].Polygons[a].Vertices[b+1].U;
          Triangles[c].TexCoords[3]=hdr.Entities[0].Polygons[a].Vertices[b+1].V;

          Triangles[c].TexCoords[4]=hdr.Entities[0].Polygons[a].Vertices[b+2].U;
          Triangles[c].TexCoords[5]=hdr.Entities[0].Polygons[a].Vertices[b+2].V;

          Triangles[c].Coords[3]=-hdr.Entities[0].Polygons[a].Vertices[(b+1)].Coord[0];
          Triangles[c].Coords[4]=hdr.Entities[0].Polygons[a].Vertices[(1+b)].Coord[1];
          Triangles[c].Coords[5]=hdr.Entities[0].Polygons[a].Vertices[(1+b)].Coord[2];

          Triangles[c].Coords[6]=-hdr.Entities[0].Polygons[a].Vertices[(2+b)].Coord[0];
          Triangles[c].Coords[7]=hdr.Entities[0].Polygons[a].Vertices[(2+b)].Coord[1];
          Triangles[c].Coords[8]=hdr.Entities[0].Polygons[a].Vertices[(2+b)].Coord[2];

          c++;
        }
      a++;
    }
  //say number of triangles
  //char nt[80];
  //sprintf(nt,"%i",NumTriangles);
  //MessageBox(0,nt,"",0);
}

////////////////////////////////////////////////////////


void CMap::Draw()
{
  static int temptex;	//static is faster

  for(a=0;a!=NumTriangles;a++)	//loop through all triangles
    {
      //NOTE: this brings from about 4 to 8/9 fps, avoiding redundant calls to glBindTexture
      if(Triangles[a].TexIndex!=temptex)
        {
          glEnd();	//end, redundant if it's the first triangle

          Bind(maptexture[Triangles[a].TexIndex]);	//set new texture

          glBegin(GL_TRIANGLES);	//restart the drawing

          temptex=Triangles[a].TexIndex;	//set the new comparative value
        }

      //this vector version gives much more FPS(GREAT :P )


      glTexCoord2dv(&Triangles[a].TexCoords[0]);	//first tex coord
      glNormal3fv(Triangles[a].Normal);			//set the normal vector
      glVertex3dv(&Triangles[a].Coords[0]);		//first vertice
      glTexCoord2dv(&Triangles[a].TexCoords[2]);	//2nd tex coord and so on
      glVertex3dv(&Triangles[a].Coords[3]);
      glTexCoord2dv(&Triangles[a].TexCoords[4]);
      glVertex3dv(&Triangles[a].Coords[6]);
    }

  glEnd();	//end drawing

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -