smfreadmap.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 495 行
CPP
495 行
#include "StdAfx.h"
#include "SmfReadMap.h"
#include "mapfile.h"
#include "Rendering/GL/myGL.h"
#include <GL/glu.h>
#include "FileSystem/FileHandler.h"
#include "Platform/ConfigHandler.h"
#include "BFGroundTextures.h"
#include "BFGroundDrawer.h"
#include "LogOutput.h"
#include "Sim/Misc/FeatureHandler.h"
#include "myMath.h"
#include "Platform/errorhandler.h"
#include "Rendering/Textures/Bitmap.h"
#include "Game/Camera.h"
#include "bitops.h"
#include "mmgr.h"
using namespace std;
CR_BIND_DERIVED(CSmfReadMap, CReadMap, (""))
//CR_REG_METADATA(CSmfReadMap, (
// ))
CBaseGroundDrawer* CSmfReadMap::GetGroundDrawer ()
{
return groundDrawer;
}
CSmfReadMap::CSmfReadMap(std::string mapname)
{
PrintLoadMsg("Opening map file");
ConfigureAnisotropy();
string smdfile = string("maps/")+mapname.substr(0,mapname.find_last_of('.'))+".smd";
mapDefParser.LoadFile(smdfile);
TdfParser resources("gamedata/resources.tdf");
ParseSettings(resources);
mapDefParser.GetDef(detailTexName, "", "MAP\\DetailTex");
if(detailTexName.empty())
detailTexName = "bitmaps/"+resources.SGetValueDef("detailtex2.bmp","resources\\graphics\\maps\\detailtex");
else
detailTexName = "maps/" + detailTexName;
for(int a=0;a<1024;++a){
for(int b=0;b<3;++b){
float c=max(waterMinColor[b],waterBaseColor[b]-waterAbsorb[b]*a);
waterHeightColors[a*4+b]=(unsigned char)(c*210);
}
waterHeightColors[a*4+3]=1;
}
PUSH_CODE_MODE;
ENTER_MIXED;
ifs=SAFE_NEW CFileHandler(string("maps/")+mapname);
if(!ifs->FileExists())
throw content_error("Couldn't open map file " + mapname);
POP_CODE_MODE;
READPTR_MAPHEADER(header,ifs);
if(strcmp(header.magic,"spring map file")!=0 || header.version!=1 || header.tilesize!=32 || header.texelPerSquare!=8 || header.squareSize!=8)
throw content_error("Incorrect map file " + mapname);
width=header.mapx;
height=header.mapy;
gs->mapx=header.mapx;
gs->mapy=header.mapy;
gs->mapSquares = gs->mapx*gs->mapy;
gs->hmapx=gs->mapx/2;
gs->hmapy=gs->mapy/2;
gs->pwr2mapx=next_power_of_2(gs->mapx);
gs->pwr2mapy=next_power_of_2(gs->mapy);
// logOutput.Print("%i %i",gs->mapx,gs->mapy);
float3::maxxpos=gs->mapx*SQUARE_SIZE-1;
float3::maxzpos=gs->mapy*SQUARE_SIZE-1;
heightmap=SAFE_NEW float[(gs->mapx+1)*(gs->mapy+1)];//SAFE_NEW float[(gs->mapx+1)*(gs->mapy+1)];
//CFileHandler ifs((string("maps/")+stupidGlobalMapname).c_str());
float base=header.minHeight;
float mod=(header.maxHeight-header.minHeight)/65536.0f;
int hmx=gs->mapx+1, hmy=gs->mapy+1;
unsigned short* temphm=SAFE_NEW unsigned short[hmx * hmy];
ifs->Seek(header.heightmapPtr);
ifs->Read(temphm,hmx*hmy*2);
for(int y=0;y<hmx*hmy;++y){
heightmap[y]=base+swabword(temphm[y])*mod;
}
delete[] temphm;
CReadMap::Initialize();
for(unsigned int a=0;a<mapname.size();++a){
mapChecksum+=mapname[a];
mapChecksum*=mapname[a];
}
PrintLoadMsg("Loading detail textures");
CBitmap bm;
if (!bm.Load(detailTexName))
throw content_error("Could not load detail texture from file " + detailTexName);
glGenTextures(1, &detailTex);
glBindTexture(GL_TEXTURE_2D, detailTex);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bm.xsize, bm.ysize, GL_RGBA, GL_UNSIGNED_BYTE, bm.mem);
if (anisotropy != 0.0f) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
}
PrintLoadMsg("Creating overhead texture");
unsigned char* buf=SAFE_NEW unsigned char[MINIMAP_SIZE];
ifs->Seek(header.minimapPtr);
ifs->Read(buf,MINIMAP_SIZE);
glGenTextures(1, &minimapTex);
glBindTexture(GL_TEXTURE_2D, minimapTex);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
//glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8 ,512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
int offset=0;
for(unsigned int i=0; i<MINIMAP_NUM_MIPMAP; i++)
{
int mipsize = 1024>>i;
int size = ((mipsize+3)/4)*((mipsize+3)/4)*8;
glCompressedTexImage2DARB(GL_TEXTURE_2D, i, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipsize, mipsize, 0, size, buf + offset);
offset += size;
}
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MINIMAP_NUM_MIPMAP-1 );
delete[] buf;
PrintLoadMsg("Creating ground shading");
glGenTextures(1, &shadowTex);
glBindTexture(GL_TEXTURE_2D, shadowTex);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8 ,gs->pwr2mapx, gs->pwr2mapy, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
if (anisotropy != 0.0f) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
}
HeightmapUpdated(0, gs->mapx, 0, gs->mapy);
groundDrawer=SAFE_NEW CBFGroundDrawer(this);
ReadFeatureInfo ();
}
CSmfReadMap::~CSmfReadMap(void)
{
delete[] featureTypes;
delete groundDrawer;
delete ifs;
delete[] heightmap;
if (detailTex) glDeleteTextures (1, &detailTex);
if (minimapTex) glDeleteTextures (1, &minimapTex);
if (shadowTex) glDeleteTextures (1, &shadowTex);
}
void CSmfReadMap::HeightmapUpdated(int x1, int x2, int y1, int y2)
{
x1-=x1&3;
x2+=(20004-x2)&3;
y1-=y1&3;
y2+=(20004-y2)&3;
int xsize=x2-x1;
int ysize=y2-y1;
//logOutput.Print("%i %i %i %i",x1,x2,y1,y2);
unsigned char* tempMem=SAFE_NEW unsigned char[xsize*ysize*4];
for(int y=0;y<ysize;++y){
for(int x=0;x<xsize;++x){
float height = centerheightmap[(x+x1)+(y+y1)*gs->mapx];
if(height<0){
int h=(int)-height;
if(height>-10){
float3 light = GetLightValue(x+x1,y+y1)*210.0f;
float wc=-height*0.1f;
tempMem[(y*xsize+x)*4+0] = (unsigned char)(waterHeightColors[h*4+0]*wc+light.x*(1-wc));
tempMem[(y*xsize+x)*4+1] = (unsigned char)(waterHeightColors[h*4+1]*wc+light.y*(1-wc));
tempMem[(y*xsize+x)*4+2] = (unsigned char)(waterHeightColors[h*4+2]*wc+light.z*(1-wc));
} else if(h<1024){
tempMem[(y*xsize+x)*4+0] = waterHeightColors[h*4+0];
tempMem[(y*xsize+x)*4+1] = waterHeightColors[h*4+1];
tempMem[(y*xsize+x)*4+2] = waterHeightColors[h*4+2];
} else {
tempMem[(y*xsize+x)*4+0] = waterHeightColors[1023*4+0];
tempMem[(y*xsize+x)*4+1] = waterHeightColors[1023*4+1];
tempMem[(y*xsize+x)*4+2] = waterHeightColors[1023*4+2];
}
tempMem[(y*xsize+x)*4+3] = EncodeHeight(height);
} else {
float3 light = GetLightValue(x+x1,y+y1)*210.0f;
tempMem[(y*xsize+x)*4] = (unsigned char)light.x;
tempMem[(y*xsize+x)*4+1] = (unsigned char)light.y;
tempMem[(y*xsize+x)*4+2] = (unsigned char)light.z;
tempMem[(y*xsize+x)*4+3] = 255;
}
}
}
glBindTexture(GL_TEXTURE_2D, shadowTex);
glTexSubImage2D(GL_TEXTURE_2D,0,x1,y1,xsize,ysize,GL_RGBA,GL_UNSIGNED_BYTE,tempMem);
delete[] tempMem;
}
float3 CSmfReadMap::GetLightValue(int x, int y)
{
float3 n1=facenormals[(y*gs->mapx+x)*2]+facenormals[(y*gs->mapx+x)*2+1];
n1.Normalize();
float3 light=sunColor*gs->sunVector.dot(n1);
for(int a=0;a<3;++a)
if(light[a]<0)
light[a]=0;
light+=ambientColor;
for(int a=0;a<3;++a)
if(light[a]>1)
light[a]=1;
return light;
}
void CSmfReadMap::DrawMinimap ()
{
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glBindTexture(GL_TEXTURE_2D, shadowTex);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV,GL_RGB_SCALE_ARB,2);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, minimapTex);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glActiveTextureARB(GL_TEXTURE0_ARB);
if(groundDrawer->DrawExtraTex()){
glActiveTextureARB(GL_TEXTURE2_ARB);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_ADD_SIGNED_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
glBindTexture(GL_TEXTURE_2D, groundDrawer->infoTex);
glActiveTextureARB(GL_TEXTURE0_ARB);
}
float isx=gs->mapx/float(gs->pwr2mapx);
float isy=gs->mapy/float(gs->pwr2mapy);
glBegin(GL_QUADS);
glTexCoord2f(0,isy);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,1);
glMultiTexCoord2fARB(GL_TEXTURE2_ARB,0,isy);
glVertex2f(0,0);
glTexCoord2f(0,0);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,0);
glMultiTexCoord2fARB(GL_TEXTURE2_ARB,0,0);
glVertex2f(0,1);
glTexCoord2f(isx,0);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1,0);
glMultiTexCoord2fARB(GL_TEXTURE2_ARB,isx,0);
glVertex2f(1,1);
glTexCoord2f(isx,isy);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1,1);
glMultiTexCoord2fARB(GL_TEXTURE2_ARB,isx,isy);
glVertex2f(1,0);
glEnd();
glTexEnvi(GL_TEXTURE_ENV,GL_RGB_SCALE_ARB,1);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE2_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);
}
void CSmfReadMap::GridVisibility (CCamera *cam, int quadSize, float maxdist, CReadMap::IQuadDrawer *qd, int extraSize)
{
int cx=(int)(cam->pos.x/(SQUARE_SIZE*quadSize));
int cy=(int)(cam->pos.z/(SQUARE_SIZE*quadSize));
int drawSquare=int(maxdist/(SQUARE_SIZE*quadSize))+1;
int drawQuadsX = header.mapx / quadSize;
int sy=cy-drawSquare;
if(sy<0)
sy=0;
int ey=cy+drawSquare;
if(ey>=header.mapy/quadSize)
ey=header.mapy/quadSize-1;
for(int y=sy;y<=ey;y++){
int sx=cx-drawSquare;
if(sx<0)
sx=0;
int ex=cx+drawSquare;
if(ex>drawQuadsX-1)
ex=drawQuadsX-1;
float xtest,xtest2;
std::vector<CBFGroundDrawer::fline>::iterator fli;
for(fli=groundDrawer->left.begin();fli!=groundDrawer->left.end();fli++){
xtest=((fli->base/SQUARE_SIZE+fli->dir*(y*quadSize)));
xtest2=((fli->base/SQUARE_SIZE+fli->dir*((y*quadSize)+quadSize)));
if(xtest>xtest2)
xtest=xtest2;
xtest=xtest/quadSize;
if(xtest-extraSize>sx)
sx=((int)xtest)-extraSize;
}
for(fli=groundDrawer->right.begin();fli!=groundDrawer->right.end();fli++){
xtest=((fli->base/SQUARE_SIZE+fli->dir*(y*quadSize)));
xtest2=((fli->base/SQUARE_SIZE+fli->dir*((y*quadSize)+quadSize)));
if(xtest<xtest2)
xtest=xtest2;
xtest=xtest/quadSize;
if(xtest+extraSize<ex)
ex=((int)xtest)+extraSize;
}
for(int x=sx;x<=ex;x++)
qd->DrawQuad (x,y);
}
}
int CSmfReadMap::GetNumFeatures ()
{
return featureHeader.numFeatures;
}
int CSmfReadMap::GetNumFeatureTypes ()
{
return featureHeader.numFeatureType;
}
void CSmfReadMap::GetFeatureInfo (MapFeatureInfo* f)
{
ifs->Seek (featureFileOffset);
for(int a=0;a<featureHeader.numFeatures;++a){
MapFeatureStruct ffs;
READ_MAPFEATURESTRUCT(ffs, ifs);
f[a].featureType = ffs.featureType;
f[a].pos = float3(ffs.xpos, ffs.ypos, ffs.zpos);
f[a].rotation = ffs.rotation;
}
}
const char *CSmfReadMap::GetFeatureType (int typeID)
{
assert (typeID >= 0 && typeID < featureHeader.numFeatureType);
return featureTypes[typeID].c_str();
}
unsigned char *CSmfReadMap::GetInfoMap (const std::string& name, MapBitmapInfo* bmInfo)
{
if (name == "grass") {
bmInfo->width = header.mapx / 4;
bmInfo->height = header.mapy / 4;
unsigned char *data = SAFE_NEW unsigned char[bmInfo->width*bmInfo->height];
ReadGrassMap (data);
return data;
}
else if(name == "metal") {
bmInfo->width = header.mapx/2;
bmInfo->height = header.mapy/2;
unsigned char *data = SAFE_NEW unsigned char[bmInfo->width*bmInfo->height];
ifs->Seek(header.metalmapPtr);
ifs->Read(data,header.mapx/2*header.mapy/2);
return data;
}
else if(name == "type") {
bmInfo->width = header.mapx/2;
bmInfo->height = header.mapy/2;
unsigned char *data = SAFE_NEW unsigned char[bmInfo->width*bmInfo->height];
ifs->Seek(header.typeMapPtr);
ifs->Read(data,gs->mapx*gs->mapy/4);
return data;
}
return false;
}
void CSmfReadMap::FreeInfoMap (const std::string& name, unsigned char *data)
{
delete[] data;
}
void CSmfReadMap::ReadGrassMap(void *data)
{
CFileHandler* fh=ifs;
fh->Seek(sizeof(MapHeader));
for(int a=0;a<header.numExtraHeaders;++a){
int size;
fh->Read(&size,4);
size=swabdword(size);
int type;
fh->Read(&type,4);
type=swabdword(type);
if(type==MEH_Vegetation){
int pos;
fh->Read(&pos,4);
pos=swabdword(pos);
fh->Seek(pos);
fh->Read(data,gs->mapx*gs->mapy/16);
/* char; no swabbing. */
break; //we arent interested in other extensions anyway
} else {
unsigned char buf[100]; //todo: fix this if we create larger extensions
fh->Read(buf,size-8);
}
}
}
void CSmfReadMap::ReadFeatureInfo()
{
ifs->Seek(header.featurePtr);
READ_MAPFEATUREHEADER(featureHeader, ifs);
featureTypes=SAFE_NEW string[featureHeader.numFeatureType];
for(int a=0;a<featureHeader.numFeatureType;++a){
char c;
ifs->Read(&c,1);
while(c){
featureTypes[a]+=c;
ifs->Read(&c,1);
}
}
featureFileOffset = ifs->GetPos();
}
void CSmfReadMap::ConfigureAnisotropy()
{
if (!GLEW_EXT_texture_filter_anisotropic) {
anisotropy = 0.0f;
return;
}
const char* SMFTexAniso = "SMFTexAniso";
anisotropy = atof(configHandler.GetString(SMFTexAniso, "0.0").c_str());
if (anisotropy < 1.0f) {
anisotropy = 0.0f; // disabled
} else {
GLfloat maxAniso;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso);
if (anisotropy > maxAniso) {
anisotropy = maxAniso;
char buf[64];
SNPRINTF(buf, sizeof(buf), "%f", anisotropy);
configHandler.SetString(SMFTexAniso, buf);
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?