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 + -
显示快捷键?