projectilehandler.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 881 行 · 第 1/2 页

CPP
881
字号
#include "StdAfx.h"
// ProjectileHandler.cpp: implementation of the CProjectileHandler class.
//
//////////////////////////////////////////////////////////////////////

#include "ProjectileHandler.h"
#include "Rendering/GL/myGL.h"
#include <GL/glu.h>			// Header File For The GLu32 Library
#include "Projectile.h"
#include "Game/Camera.h"
#include "Rendering/GL/VertexArray.h"
#include "Sim/Misc/QuadField.h"
#include "Sim/Units/Unit.h"
#include "Sim/Units/UnitDef.h"
#include "TimeProfiler.h"
#include "Rendering/Textures/Bitmap.h"
#include "Rendering/GroundFlash.h"
#include "Sim/Misc/LosHandler.h"
#include "Map/Ground.h"
#include "Rendering/Textures/TextureHandler.h"
#include "Sim/Misc/Feature.h"
#include "Platform/ConfigHandler.h"
#include "Rendering/ShadowHandler.h"
#include "Rendering/UnitModels/UnitDrawer.h"
#include "Rendering/UnitModels/3DOParser.h"
#include "Rendering/UnitModels/s3oParser.h"
#include "LogOutput.h"
#include <algorithm>
#include "Rendering/GL/IFramebuffer.h"
#include "System/FileSystem/FileHandler.h"
#include "mmgr.h"
#include "creg/STL_List.h"

CProjectileHandler* ph;
using namespace std;
extern GLfloat FogBlack[];
extern GLfloat FogLand[];

CR_BIND(CProjectileHandler,);

CR_REG_METADATA(CProjectileHandler,(
				//CR_MEMBER(ps),
				CR_MEMBER(groundFlashes),
				CR_RESERVED(32),
				CR_SERIALIZER(Serialize),
				CR_POSTLOAD(PostLoad)
				));

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CProjectileHandler::CProjectileHandler()
{
	PrintLoadMsg("Creating projectile texture");

	maxParticles=configHandler.GetInt("MaxParticles",4000);

	currentParticles=0;
	particleSaturation=0;
	numPerlinProjectiles=0;

	textureAtlas = SAFE_NEW CTextureAtlas(2048, 2048);

	// used to block resources_map.tdf from loading textures
	std::set<std::string> blockMapTexNames;

	TdfParser resources("gamedata/resources.tdf");
	//add all textures in projectiletextures section
	std::map<std::string,std::string> ptex = resources.GetAllValues("resources\\graphics\\projectiletextures");
	for(std::map<std::string,std::string>::iterator pi=ptex.begin(); pi!=ptex.end(); ++pi)
	{
		textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
		blockMapTexNames.insert(pi->first);
	}
	//add all texture from sections within projectiletextures section
	std::vector<std::string> seclist = resources.GetSectionList("resources\\graphics\\projectiletextures");
	for(int i=0; i<seclist.size(); i++)
	{
		std::map<std::string,std::string> ptex2 = resources.GetAllValues("resources\\graphics\\projectiletextures\\" + seclist[i]);
		for(std::map<std::string,std::string>::iterator pi=ptex2.begin(); pi!=ptex2.end(); ++pi)
		{
			textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
			blockMapTexNames.insert(pi->first);
		}
	}


	for (int i = 0; i < 12; i++) {
		char num[10];
		sprintf(num, "%02i", i);
		textureAtlas->AddTexFromFile(std::string("ismoke") + num, std::string("bitmaps/")+resources.SGetValueDef(std::string("smoke/smoke") + num +".tga",std::string("resources\\graphics\\smoke\\smoke")+num+"alpha"));
		blockMapTexNames.insert(std::string("ismoke") + num);
	}

	char tex[128][128][4];
	for (int y = 0; y < 128; y++) { // shield
		for (int x = 0; x < 128; x++) {
			tex[y][x][0] = 70;
			tex[y][x][1] = 70;
			tex[y][x][2] = 70;
			tex[y][x][3] = 70;
		}
	}
	textureAtlas->AddTexFromMem("perlintex", 128, 128, CTextureAtlas::RGBA32, tex);
	blockMapTexNames.insert("perlintex");

	blockMapTexNames.insert("flare");
	blockMapTexNames.insert("explo");
	blockMapTexNames.insert("explofade");
	blockMapTexNames.insert("heatcloud");
	blockMapTexNames.insert("laserend");
	blockMapTexNames.insert("laserfalloff");
	blockMapTexNames.insert("randdots");
	blockMapTexNames.insert("smoketrail");
	blockMapTexNames.insert("wake");
	blockMapTexNames.insert("perlintex");
	blockMapTexNames.insert("flame");

	blockMapTexNames.insert("sbtrailtexture");
	blockMapTexNames.insert("missiletrailtexture");
	blockMapTexNames.insert("muzzleflametexture");
	blockMapTexNames.insert("repulsetexture");
	blockMapTexNames.insert("dguntexture");
	blockMapTexNames.insert("flareprojectiletexture");
	blockMapTexNames.insert("sbflaretexture");
	blockMapTexNames.insert("missileflaretexture");
	blockMapTexNames.insert("beamlaserflaretexture");
	blockMapTexNames.insert("bubbletexture");
	blockMapTexNames.insert("geosquaretexture");
	blockMapTexNames.insert("gfxtexture");
	blockMapTexNames.insert("projectiletexture");
	blockMapTexNames.insert("repulsegfxtexture");
	blockMapTexNames.insert("sphereparttexture");
	blockMapTexNames.insert("torpedotexture");
	blockMapTexNames.insert("wrecktexture");
	blockMapTexNames.insert("plasmatexture");

	// allow map specified atlas textures for gaia unit projectiles
	CFileHandler fh("gamedata/resources_map.tdf");
	if (fh.FileExists()) {
		TdfParser resources_map("gamedata/resources_map.tdf");
		//add all textures in projectiletextures section 
		std::map<std::string,std::string> mptex =
			resources_map.GetAllValues("resources\\graphics\\projectiletextures");
		std::map<std::string,std::string>::iterator pi;
		for (pi = mptex.begin(); pi != mptex.end(); ++pi) {
			if (blockMapTexNames.find(pi->first) == blockMapTexNames.end()) {
				textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
			}
		}
	}

	if (!textureAtlas->Finalize()) {
		logOutput.Print("Could not finalize projectile texture atlas. Use less/smaller textures.");
	}

	flaretex        = textureAtlas->GetTexture("flare");
	explotex        = textureAtlas->GetTexture("explo");
	explofadetex    = textureAtlas->GetTexture("explofade");
	heatcloudtex    = textureAtlas->GetTexture("heatcloud");
	laserendtex     = textureAtlas->GetTexture("laserend");
	laserfallofftex = textureAtlas->GetTexture("laserfalloff");
	randdotstex     = textureAtlas->GetTexture("randdots");
	smoketrailtex   = textureAtlas->GetTexture("smoketrail");
	waketex         = textureAtlas->GetTexture("wake");
	perlintex       = textureAtlas->GetTexture("perlintex");
	flametex        = textureAtlas->GetTexture("flame");

	for (int i = 0; i < 12; i++) {
		char num[10];
		sprintf(num, "%02i", i);
		smoketex[i] = textureAtlas->GetTexture(std::string("ismoke") + num);
	}

	sbtrailtex        = textureAtlas->GetTextureWithBackup("sbtrailtexture",         "smoketrail"    );
	missiletrailtex   = textureAtlas->GetTextureWithBackup("missiletrailtexture",    "smoketrail"    );
	muzzleflametex    = textureAtlas->GetTextureWithBackup("muzzleflametexture",     "explo"         );
	repulsetex        = textureAtlas->GetTextureWithBackup("repulsetexture",         "explo"         );
	dguntex           = textureAtlas->GetTextureWithBackup("dguntexture",            "flare"         );
	flareprojectiletex= textureAtlas->GetTextureWithBackup("flareprojectiletexture", "flare"         );
	sbflaretex        = textureAtlas->GetTextureWithBackup("sbflaretexture",         "flare"         );
	missileflaretex   = textureAtlas->GetTextureWithBackup("missileflaretexture",    "flare"         );
	beamlaserflaretex = textureAtlas->GetTextureWithBackup("beamlaserflaretexture",  "flare"         );
	bubbletex         = textureAtlas->GetTextureWithBackup("bubbletexture",          "circularthingy");
	geosquaretex      = textureAtlas->GetTextureWithBackup("geosquaretexture",       "circularthingy");
	gfxtex            = textureAtlas->GetTextureWithBackup("gfxtexture",             "circularthingy");
	projectiletex     = textureAtlas->GetTextureWithBackup("projectiletexture",      "circularthingy");
	repulsegfxtex     = textureAtlas->GetTextureWithBackup("repulsegfxtexture",      "circularthingy");
	sphereparttex     = textureAtlas->GetTextureWithBackup("sphereparttexture",      "circularthingy");
	torpedotex        = textureAtlas->GetTextureWithBackup("torpedotexture",         "circularthingy");
	wrecktex          = textureAtlas->GetTextureWithBackup("wrecktexture",           "circularthingy");
	plasmatex         = textureAtlas->GetTextureWithBackup("plasmatexture",          "circularthingy");

	groundFXAtlas = SAFE_NEW CTextureAtlas(2048, 2048);
	//add all textures in groundfx section
	ptex = resources.GetAllValues("resources\\graphics\\groundfx");
	for(std::map<std::string,std::string>::iterator pi=ptex.begin(); pi!=ptex.end(); ++pi)
	{
		groundFXAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
	}
	//add all texture from sections within groundfx section
	seclist = resources.GetSectionList("resources\\graphics\\groundfx");
	for(int i=0; i<seclist.size(); i++)
	{
		std::map<std::string,std::string> ptex2 = resources.GetAllValues("resources\\graphics\\groundfx\\" + seclist[i]);
		for(std::map<std::string,std::string>::iterator pi=ptex2.begin(); pi!=ptex2.end(); ++pi)
		{
			groundFXAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
		}
	}

	if (!groundFXAtlas->Finalize())
		logOutput.Print("Could not finalize groundFX texture atlas. Use less/smaller textures.");

	groundflashtex = groundFXAtlas->GetTexture("groundflash");
	groundringtex = groundFXAtlas->GetTexture("groundring");
	seismictex = groundFXAtlas->GetTexture("seismic");

	if(shadowHandler->canUseShadows){
		projectileShadowVP=LoadVertexProgram("projectileshadow.vp");
	}


	flying3doPieces = SAFE_NEW FlyingPiece_List;
	flyingPieces.push_back(flying3doPieces);

	for(int a=0;a<4;++a){
		perlinBlend[a]=0;
	}
	unsigned char tempmem[4*16*16];
	for(int a=0;a<4*16*16;++a)
		tempmem[a]=0;
	for(int a=0;a<8;++a){
		glGenTextures(1, &perlinTex[a]);
		glBindTexture(GL_TEXTURE_2D, perlinTex[a]);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8,16, 16, GL_RGBA, GL_UNSIGNED_BYTE, tempmem);
	}

	drawPerlinTex=false;

	if(shadowHandler && shadowHandler->drawShadows && GLEW_EXT_framebuffer_object && !GLEW_ATI_envmap_bumpmap){	//this seems to bug on ati cards so disable it on those (just some random ati extension to detect ati cards), should be fixed by someone that actually has a ati card
		perlinFB = instantiate_fb(512, 512, FBO_NEED_COLOR);
		if (perlinFB && perlinFB->valid()){
			drawPerlinTex=true;
			perlinFB->attachTexture(textureAtlas->gltex, GL_TEXTURE_2D, FBO_ATTACH_COLOR);
			perlinFB->checkFBOStatus();
		}
	}
	else
		perlinFB = 0;
}

CProjectileHandler::~CProjectileHandler()
{
	for(int a=0;a<8;++a)
		glDeleteTextures (1, &perlinTex[a]);

	Projectile_List::iterator psi;
	for(psi=ps.begin();psi!=ps.end();++psi)
		delete *psi;
	std::vector<CGroundFlash*>::iterator gfi;
	for(gfi=groundFlashes.begin();gfi!=groundFlashes.end();++gfi)
		delete *gfi;
	distlist.clear();

	if(shadowHandler->canUseShadows){
		glSafeDeleteProgram(projectileShadowVP);
	}

	/* Also invalidates flying3doPieces and flyings3oPieces. */
	for(std::list<FlyingPiece_List*>::iterator pti=flyingPieces.begin();pti!=flyingPieces.end();++pti){
		FlyingPiece_List * fpl = *pti;
		for(std::list<FlyingPiece*>::iterator pi=fpl->begin();pi!=fpl->end();++pi){
			if ((*pi)->verts != NULL){
				delete[] ((*pi)->verts);
			}
			delete *pi;
		}
		delete fpl;
	}
	ph=0;
	delete perlinFB;
	delete textureAtlas;
	delete groundFXAtlas;
}

void CProjectileHandler::Serialize(creg::ISerializer *s)
{
	if (s->IsWriting ()) {
		int size = (int)ps.size();
		s->Serialize (&size,sizeof(int));
		for (Projectile_List::iterator it = ps.begin(); it!=ps.end(); ++it) {
			void **ptr = (void**)&*it;
			s->SerializeObjectPtr(ptr,(*it)->GetClass());
		}
	} else {
		int size;
		s->Serialize (&size, sizeof(int));
		ps.resize (size);
		for (Projectile_List::iterator it = ps.begin(); it!=ps.end(); ++it) {
			void **ptr = (void**)&*it;
			s->SerializeObjectPtr(ptr,0/*FIXME*/);
		}
	}
}

void CProjectileHandler::PostLoad()
{

}

void CProjectileHandler::SetMaxParticles(int value)
{
	maxParticles = value;
}


void CProjectileHandler::Update()
{
	SCOPED_TIMER("Projectile handler");

	Projectile_List::iterator psi=ps.begin();
	while(psi!= ps.end()){
		CProjectile *p = *psi;
		if(p->deleteMe){
			Projectile_List::iterator prev=psi++;
			ps.erase(prev);
			delete p;
		} else {
			(*psi)->Update();
			++psi;
		}
	}

	for(unsigned int i = 0; i < groundFlashes.size();)
	{
		CGroundFlash *gf = groundFlashes[i];
		if (!gf->Update ())
		{
			// swap gf with the groundflash at the end of the list, so pop_back() can be used to erase it
			if ( i < groundFlashes.size()-1 )
				std::swap (groundFlashes.back(), groundFlashes[i]);
			groundFlashes.pop_back();
			delete gf;
		} else i++;
	}

	for(std::list<FlyingPiece_List*>::iterator pti=flyingPieces.begin();pti!=flyingPieces.end();++pti){
		FlyingPiece_List * fpl = *pti;
		/* Note: nothing in the third clause of this loop. TODO Rewrite it as a while */
		for(std::list<FlyingPiece*>::iterator pi=fpl->begin();pi!=fpl->end();){
			(*pi)->pos+=(*pi)->speed;
			(*pi)->speed*=0.996f;
			(*pi)->speed.y+=gs->gravity;
			(*pi)->rot+=(*pi)->rotSpeed;
			if((*pi)->pos.y<ground->GetApproximateHeight((*pi)->pos.x,(*pi)->pos.z)-10){
				delete *pi;
				pi=fpl->erase(pi);
			} else {
				++pi;
			}
		}
	}
}

int CompareProjDist(CProjectileHandler::projdist const &arg1, CProjectileHandler::projdist const &arg2){
	if (arg1.dist <= arg2.dist)
	   return 0;
   return 1;
}

void CProjectileHandler::Draw(bool drawReflection,bool drawRefraction)
{
	glDisable(GL_BLEND);
	glEnable(GL_TEXTURE_2D);
	glDepthMask(1);

	CVertexArray* va=GetVertexArray();

	int numFlyingPieces = 0;
	int drawnPieces = 0;

	/* Putting in, say, viewport culling will deserve refactoring. */

	/* 3DO */
	unitDrawer->SetupForUnitDrawing();

	va->Initialize();
	numFlyingPieces += flying3doPieces->size();
	for(std::list<FlyingPiece*>::iterator pi=flying3doPieces->begin();pi!=flying3doPieces->end();++pi){
		CMatrix44f m;
		m.Rotate((*pi)->rot,(*pi)->rotAxis);
		float3 interPos=(*pi)->pos+(*pi)->speed*gu->timeOffset;
		CTextureHandler::UnitTexture* tex=(*pi)->prim->texture;

		S3DOVertex* v=&(*pi)->object->vertices[(*pi)->prim->vertices[0]];
		float3 tp=m.Mul(v->pos);
		float3 tn=m.Mul(v->normal);
		tp+=interPos;
		va->AddVertexTN(tp,tex->xstart,tex->ystart,tn);

		v=&(*pi)->object->vertices[(*pi)->prim->vertices[1]];
		tp=m.Mul(v->pos);
		tn=m.Mul(v->normal);
		tp+=interPos;
		va->AddVertexTN(tp,tex->xend,tex->ystart,tn);

		v=&(*pi)->object->vertices[(*pi)->prim->vertices[2]];
		tp=m.Mul(v->pos);
		tn=m.Mul(v->normal);
		tp+=interPos;
		va->AddVertexTN(tp,tex->xend,tex->yend,tn);

		v=&(*pi)->object->vertices[(*pi)->prim->vertices[3]];
		tp=m.Mul(v->pos);
		tn=m.Mul(v->normal);
		tp+=interPos;
		va->AddVertexTN(tp,tex->xstart,tex->yend,tn);
	}
	drawnPieces+=va->drawIndex/32;
	va->DrawArrayTN(GL_QUADS);

	unitDrawer->CleanUpUnitDrawing();

	/* S3O */
	unitDrawer->SetupForS3ODrawing();

	for (int textureType = 1; textureType < flyings3oPieces.size(); textureType++){
		/* TODO Skip this if there's no FlyingPieces. */

		texturehandler->SetS3oTexture(textureType);

		for (int team = 0; team < flyings3oPieces[textureType].size(); team++){
			FlyingPiece_List * fpl = flyings3oPieces[textureType][team];

			unitDrawer->SetS3OTeamColour(team);

			va->Initialize();

⌨️ 快捷键说明

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