3doparser.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 696 行 · 第 1/2 页
CPP
696 行
// 3DOParser.cpp: implementation of the C3DOParser class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "3DOParser.h"
#include "Rendering/GL/myGL.h"
#include "GlobalStuff.h"
#include "LogOutput.h"
#include <vector>
#include "Rendering/GL/VertexArray.h"
#include "FileSystem/VFSHandler.h"
#include <set>
#include "FileSystem/FileHandler.h"
#include "FileSystem/SimpleParser.h"
#include "Rendering/FartextureHandler.h"
#include "Sim/Units/COB/CobInstance.h"
#include "Rendering/Textures/TAPalette.h"
#include "Matrix44f.h"
#include <algorithm>
#include <cctype>
#include <locale>
#include <stdexcept>
#include "Game/Team.h"
#include "Game/Player.h"
#include "Platform/errorhandler.h"
#include "Platform/byteorder.h"
#include "SDL_types.h"
#include "s3oParser.h"
#include "mmgr.h"
using namespace std;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define READ_3DOBJECT(o) \
do { \
unsigned int __tmp; \
unsigned short __isize = sizeof(unsigned int); \
SimStreamRead(&__tmp,__isize); \
(o).VersionSignature = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).NumberOfVertices = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).NumberOfPrimitives = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).SelectionPrimitive = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).XFromParent = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).YFromParent = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).ZFromParent = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).OffsetToObjectName = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).Always_0 = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).OffsetToVertexArray = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).OffsetToPrimitiveArray = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).OffsetToSiblingObject = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(o).OffsetToChildObject = (int)swabdword(__tmp); \
} while (0)
#define READ_VERTEX(v) \
do { \
unsigned int __tmp; \
unsigned short __isize = sizeof(unsigned int); \
SimStreamRead(&__tmp,__isize); \
(v).x = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(v).y = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(v).z = (int)swabdword(__tmp); \
} while (0)
#define READ_PRIMITIVE(p) \
do { \
unsigned int __tmp; \
unsigned short __isize = sizeof(unsigned int); \
SimStreamRead(&__tmp,__isize); \
(p).PaletteEntry = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(p).NumberOfVertexIndexes = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(p).Always_0 = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(p).OffsetToVertexIndexArray = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(p).OffsetToTextureName = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(p).Unknown_1 = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(p).Unknown_2 = (int)swabdword(__tmp); \
SimStreamRead(&__tmp,__isize); \
(p).Unknown_3 = (int)swabdword(__tmp); \
} while (0)
void S3DO::DrawStatic()
{
glPushMatrix();
glTranslatef(offset.x,offset.y,offset.z);
glCallList(displist);
for(unsigned int i=0; i<childs.size(); i++)
childs[i]->DrawStatic();
glPopMatrix();
}
S3DO::~S3DO()
{
glDeleteLists(displist, 1);
}
C3DOParser::C3DOParser()
{
scaleFactor=400000.0f;
CFileHandler file("unittextures/tatex/teamtex.txt");
CSimpleParser parser(file);
while(!file.Eof()) {
teamtex.insert(StringToLower(parser.GetLine()));
}
}
C3DOParser::~C3DOParser()
{
map<string,S3DOModel*>::iterator ui;
for(ui=units.begin();ui!=units.end();++ui){
DeleteS3DO(ui->second->rootobject3do);
delete ui->second;
}
}
void C3DOParser::DeleteS3DO(S3DO *o)
{
for(std::vector<S3DO*>::iterator di=o->childs.begin();di!=o->childs.end();di++){
DeleteS3DO(*di);
}
delete o;
}
S3DOModel* C3DOParser::Load3DO(string name,float scale,int team)
{
int color=team;
if(name.find(".")==string::npos)
name+=".3do";
scaleFactor=1/(65536.0f);
string sideName(name);
StringToLowerInPlace(sideName);
sideName+=color+'0';
map<string,S3DOModel*>::iterator ui;
if((ui=units.find(sideName))!=units.end()){
return ui->second;
}
// if(sideName.find("armstump.3do")!=std::string.npos){
// logOutput.Print("New type %s %i %s %s",name.c_str(),team,sideName.c_str(),gs->players[gs->Team(team)->leader]->playerName.c_str());
// }
PUSH_CODE_MODE;
ENTER_SYNCED;
// ifstream ifs(name, ios::in|ios::binary);
//int size=hpiHandler->GetFileSize(name);
CFileHandler file(name);
if(!file.FileExists()){
POP_CODE_MODE;
throw content_error("File not found: "+name);
}
fileBuf=SAFE_NEW unsigned char[file.FileSize()];
//hpiHandler->LoadFile(name,fileBuf);
file.Read(fileBuf, file.FileSize());
if (fileBuf == NULL) {
delete [] fileBuf;
throw content_error("Failed to read file "+name);
}
S3DOModel *model = SAFE_NEW S3DOModel;
S3DO* object=SAFE_NEW S3DO;
model->rootobject3do=object;
model->rootobjects3o=0;
model->textureType=0;
object->isEmpty=true;
model->name=name;
model->numobjects=1;
_3DObject root;
// ifs.seekg(0);
// ifs.read((char*)&root,sizeof(_3DObject));
curOffset=0;
READ_3DOBJECT(root);
object->name = StringToLower(GetText(root.OffsetToObjectName));
std::vector<float3> vertexes;
GetVertexes(&root,object);
GetPrimitives(object,root.OffsetToPrimitiveArray,root.NumberOfPrimitives,&vertexes,root.SelectionPrimitive,color);
CalcNormals(object);
if(root.OffsetToChildObject>0)
if(!ReadChild(root.OffsetToChildObject,object,color,&model->numobjects))
object->isEmpty=false;
object->offset.x=root.XFromParent*scaleFactor;
object->offset.y=root.YFromParent*scaleFactor;
object->offset.z=-root.ZFromParent*scaleFactor;
FindCenter(object);
object->radius=FindRadius(object,-object->relMidPos);
object->relMidPos.x=0;
object->relMidPos.z=0; //stupid but seems to work better
if(object->relMidPos.y<1)
object->relMidPos.y=1;
units[sideName]=model;
CreateLists(object);
model->radius = model->rootobject3do->radius * scale; //this is a hack to make aircrafts less likely to collide and get hit by nontracking weapons
model->height = FindHeight(model->rootobject3do,ZeroVector);
// logOutput.Print("%s has height %f",name,model->height);
model->maxx=model->rootobject3do->maxx;
model->maxy=model->rootobject3do->maxy;
model->maxz=model->rootobject3do->maxz;
model->minx=model->rootobject3do->minx;
model->miny=model->rootobject3do->miny;
model->minz=model->rootobject3do->minz;
model->relMidPos=model->rootobject3do->relMidPos;
fartextureHandler->CreateFarTexture(model);
delete[] fileBuf;
POP_CODE_MODE;
return model;
}
S3DOModel* C3DOParser::Load3DO(string name,float scale,int team,const float3& offsets)
{
S3DOModel *model = C3DOParser::Load3DO(name, scale, team);
model->rootobject3do->relMidPos.x=offsets.x;
model->rootobject3do->relMidPos.y=offsets.y;
model->rootobject3do->relMidPos.z=offsets.z;
model->relMidPos = model->rootobject3do->relMidPos;
return model;
}
void C3DOParser::GetVertexes(_3DObject* o,S3DO* object)
{
curOffset=o->OffsetToVertexArray;
for(int a=0;a<o->NumberOfVertices;a++){
_Vertex v;
READ_VERTEX(v);
S3DOVertex vertex;
float3 f;
f.x=(v.x)*scaleFactor;
f.y=(v.y)*scaleFactor;
f.z=-(v.z)*scaleFactor;
vertex.pos=f;
object->vertices.push_back(vertex);
}
}
void C3DOParser::GetPrimitives(S3DO* obj,int pos,int num,vertex_vector* vv,int excludePrim,int side)
{
map<int,int> prevHashes;
for(int a=0;a<num;a++){
if(excludePrim==a){
continue;
}
curOffset=pos+a*sizeof(_Primitive);
_Primitive p;
READ_PRIMITIVE(p);
S3DOPrimitive sp;
sp.numVertex=p.NumberOfVertexIndexes;
if(sp.numVertex<3)
continue;
curOffset=p.OffsetToVertexIndexArray;
Uint16 w;
list<int> orderVert;
for(int b=0;b<sp.numVertex;b++){
SimStreamRead(&w,2);
w = swabword(w);
sp.vertices.push_back(w);
orderVert.push_back(w);
}
orderVert.sort();
int vertHash=0;
for(list<int>::iterator vi=orderVert.begin();vi!=orderVert.end();++vi)
vertHash=(vertHash+(*vi))*(*vi);
sp.texture=0;
if(p.OffsetToTextureName!=0)
{
string texture = GetText(p.OffsetToTextureName);
char chside[3];
chside[0] = '0' + (side / 10);
chside[1] = '0' + (side % 10);
chside[2] = 0;
StringToLowerInPlace(texture);
if(teamtex.find(texture) != teamtex.end())
sp.texture=texturehandler->GetTATexture(texture + chside, side, false);
else
sp.texture=texturehandler->GetTATexture(texture + "00",side, false);
if(sp.texture==0)
logOutput << "Parser couldnt get texture " << GetText(p.OffsetToTextureName).c_str() << "\n";
} else {
char t[50];
sprintf(t,"ta_color%i",p.PaletteEntry);
sp.texture=texturehandler->GetTATexture(t,0, false);
}
float3 n=-(obj->vertices[sp.vertices[1]].pos-obj->vertices[sp.vertices[0]].pos).cross(obj->vertices[sp.vertices[2]].pos-obj->vertices[sp.vertices[0]].pos);
n.Normalize();
sp.normal=n;
for(int a=0;a<sp.numVertex;++a)
sp.normals.push_back(n);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?