📄 cmap.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 + -