⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unitdrawer.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
#include "StdAfx.h"
#include "UnitDrawer.h"
#include "myMath.h"
#include "LogOutput.h"
#include "3DModelParser.h"
#include "Game/Camera.h"
#include "Game/GameHelper.h"
#include "Game/GameSetup.h"
#include "Game/SelectedUnits.h"
#include "Game/Team.h"
#include "Lua/LuaMaterial.h"
#include "Lua/LuaUnitMaterial.h"
#include "Map/BaseGroundDrawer.h"
#include "Map/Ground.h"
#include "Map/ReadMap.h"
#include "Platform/ConfigHandler.h"
#include "Rendering/Env/BaseSky.h"
#include "Rendering/Env/BaseWater.h"
#include "Rendering/FartextureHandler.h"
#include "Rendering/GL/myGL.h"
#include "Rendering/GL/VertexArray.h"
#include "Rendering/GroundDecalHandler.h"
#include "Rendering/IconHandler.h"
#include "Rendering/ShadowHandler.h"
#include "Rendering/Textures/Bitmap.h"
#include "Rendering/Textures/TextureHandler.h"
#include "Sim/Misc/LosHandler.h"
#include "Sim/Misc/RadarHandler.h"
#include "Sim/Units/CommandAI/BuilderCAI.h"
#include "Sim/Units/UnitDef.h"
#include "Sim/Units/UnitDefHandler.h"
#include "Sim/Units/Unit.h"
#include "Sim/Units/UnitHandler.h"
#include "mmgr.h"

CUnitDrawer* unitDrawer;
using namespace std;


static bool luaDrawing = false; // FIXME


static float GetLODFloat(const string& name, float def)
{
	// NOTE: the inverse of the value is used
	char buf[64];
	SNPRINTF(buf, sizeof(buf), "%.3f", def);
	const string valueStr = configHandler.GetString(name, buf);
	char* end;
	float value = (float)strtod(valueStr.c_str(), &end);
	if ((end == valueStr.c_str()) || (value <= 0.0f)) {
		return (1.0f / def);
	}
	return (1.0f / value);
}


CUnitDrawer::CUnitDrawer(void)
:	showHealthBars(true),
	updateFace(0)
{
	if (texturehandler == 0) { 
		texturehandler = SAFE_NEW CTextureHandler;
	}

	unitDrawDist = configHandler.GetInt("UnitLodDist",200);
	unitIconDist = configHandler.GetInt("UnitIconDist",200);
	iconLength = 750 * unitIconDist * unitIconDist;

	specTexSize = configHandler.GetInt("CubeTexSizeSpecular", 128);
	reflTexSize = configHandler.GetInt("CubeTexSizeReflection", 128);

	LODScale           = GetLODFloat("LODScale",           1.0f);
	LODScaleShadow     = GetLODFloat("LODScaleShadow",     1.0f);
	LODScaleReflection = GetLODFloat("LODScaleReflection", 1.0f);
	LODScaleRefraction = GetLODFloat("LODScaleRefraction", 1.0f);

	CBitmap white;
	white.Alloc(1, 1);
	for (int a = 0; a < 4; ++a) {
		white.mem[a] = 255;
	}

	whiteTex=white.CreateTexture(false);

	unitAmbientColor=readmap->mapDefParser.GetFloat3(float3(0.4f,0.4f,0.4f),"MAP\\LIGHT\\UnitAmbientColor");
	unitSunColor=readmap->mapDefParser.GetFloat3(float3(0.7f,0.7f,0.7f),"MAP\\LIGHT\\UnitSunColor");

	float3 specularSunColor=readmap->mapDefParser.GetFloat3(unitSunColor,"MAP\\LIGHT\\SpecularSunColor");
	readmap->mapDefParser.GetDef(unitShadowDensity,"0.8","MAP\\LIGHT\\UnitShadowDensity");

	advShading=!!configHandler.GetInt("AdvUnitShading", GLEW_ARB_fragment_program ? 1 : 0);
	if (advShading && !GLEW_ARB_fragment_program) {
		logOutput.Print("You are missing an OpenGL extension needed to use advanced unit shading (GL_ARB_fragment_program)");
		advShading = false;
	}

	if (advShading)
	{
		unitVP = LoadVertexProgram("unit.vp");
		unitFP = LoadFragmentProgram("unit.fp");
		unitS3oVP = LoadVertexProgram("units3o.vp");
		unitS3oFP = LoadFragmentProgram("units3o.fp");

		if (shadowHandler->canUseShadows) {
			unitShadowFP    = LoadFragmentProgram("unit_shadow.fp");
			unitShadowS3oFP = LoadFragmentProgram("units3o_shadow.fp");
			unitShadowGenVP = LoadVertexProgram("unit_genshadow.vp");
		} else {
			unitShadowFP    = 0;
			unitShadowS3oFP = 0;
			unitShadowGenVP = 0;
		}

		glGenTextures(1,&boxtex);
		glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, boxtex);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,0,GL_RGBA8,reflTexSize,reflTexSize,0,GL_RGBA,GL_UNSIGNED_BYTE,0);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,0,GL_RGBA8,reflTexSize,reflTexSize,0,GL_RGBA,GL_UNSIGNED_BYTE,0);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,0,GL_RGBA8,reflTexSize,reflTexSize,0,GL_RGBA,GL_UNSIGNED_BYTE,0);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,0,GL_RGBA8,reflTexSize,reflTexSize,0,GL_RGBA,GL_UNSIGNED_BYTE,0);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,0,GL_RGBA8,reflTexSize,reflTexSize,0,GL_RGBA,GL_UNSIGNED_BYTE,0);
		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,0,GL_RGBA8,reflTexSize,reflTexSize,0,GL_RGBA,GL_UNSIGNED_BYTE,0);

		glGenTextures(1,&specularTex);
		glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, specularTex);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,specTexSize,float3( 1, 1, 1),float3( 0, 0,-2),float3(0,-2, 0),gs->sunVector,100,specularSunColor);
		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,specTexSize,float3(-1, 1,-1),float3( 0, 0, 2),float3(0,-2, 0),gs->sunVector,100,specularSunColor);
		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,specTexSize,float3(-1 ,1,-1),float3( 2, 0, 0),float3(0, 0, 2),gs->sunVector,100,specularSunColor);
		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,specTexSize,float3(-1,-1, 1),float3( 2, 0, 0),float3(0, 0,-2),gs->sunVector,100,specularSunColor);
		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,specTexSize,float3(-1, 1, 1),float3( 2, 0, 0),float3(0,-2, 0),gs->sunVector,100,specularSunColor);
		CreateSpecularFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,specTexSize,float3( 1, 1,-1),float3(-2, 0, 0),float3(0,-2, 0),gs->sunVector,100,specularSunColor);
	}
}


CUnitDrawer::~CUnitDrawer(void)
{
	glDeleteTextures(1, &whiteTex);

	if (advShading) {
		glSafeDeleteProgram(unitVP);
		glSafeDeleteProgram(unitFP);

		glSafeDeleteProgram(unitShadowFP);
		glSafeDeleteProgram(unitS3oVP);
		glSafeDeleteProgram(unitS3oFP);
		glSafeDeleteProgram(unitShadowS3oFP);
		glSafeDeleteProgram(unitShadowGenVP);

		glDeleteTextures(1, &boxtex);
		glDeleteTextures(1, &specularTex);
	}

	std::list<GhostBuilding*>::iterator gbi;

	for (gbi = ghostBuildings.begin(); gbi != ghostBuildings.end(); /* no inc */) {
		if ((*gbi)->decal) {
			(*gbi)->decal->gbOwner = 0;
		}
		delete *gbi;
		gbi = ghostBuildings.erase(gbi);
	}

	for (gbi = ghostBuildingsS3O.begin(); gbi != ghostBuildingsS3O.end(); /* no inc */) {
		if ((*gbi)->decal) {
			(*gbi)->decal->gbOwner = 0;
		}
		delete *gbi;
		gbi = ghostBuildingsS3O.erase(gbi);
	}
}


void CUnitDrawer::Update(void)
{
	while (!tempDrawUnits.empty() && tempDrawUnits.begin()->first < gs->frameNum - 1) {
		tempDrawUnits.erase(tempDrawUnits.begin());
	}
	while (!tempTransparentDrawUnits.empty() && tempTransparentDrawUnits.begin()->first <= gs->frameNum) {
		tempTransparentDrawUnits.erase(tempTransparentDrawUnits.begin());
	}
}


extern GLfloat FogLand[];


inline void CUnitDrawer::DrawUnitLOD(CUnit* unit)
{
	if (unit->isCloaked) {
		const LuaMatType matType =
			(water->drawReflection) ? LUAMAT_ALPHA_REFLECT : LUAMAT_ALPHA;
		LuaUnitMaterial& unitMat = unit->luaMats[matType];
		const unsigned lod = unit->CalcLOD(unitMat.GetLastLOD());
		unit->currentLOD = lod;
		LuaUnitLODMaterial* lodMat = unitMat.GetMaterial(lod);

		if ((lodMat != NULL) && lodMat->IsActive()) {
			lodMat->AddUnit(unit);
		} else {
			if (unit->model->textureType) {
				drawCloakedS3O.push_back(unit);
			} else {
				drawCloaked.push_back(unit);
			}
		}
	}
	else {
		const LuaMatType matType =
			(water->drawReflection) ? LUAMAT_OPAQUE_REFLECT : LUAMAT_OPAQUE;
		LuaUnitMaterial& unitMat = unit->luaMats[matType];
		const unsigned lod = unit->CalcLOD(unitMat.GetLastLOD());
		unit->currentLOD = lod;
		LuaUnitLODMaterial* lodMat = unitMat.GetMaterial(lod);

		if ((lodMat != NULL) && lodMat->IsActive()) {
			lodMat->AddUnit(unit);
		} else {
			if (unit->model->textureType) {
				QueS3ODraw(unit, unit->model->textureType);
			} else {
				unit->Draw();
			}
		}
	}
}


inline void CUnitDrawer::DrawUnit(CUnit* unit)
{
	if (unit->lodCount > 0) {
		DrawUnitLOD(unit);
		return;
	}

	if (unit->model->textureType) {
		if (unit->isCloaked) {
			drawCloakedS3O.push_back(unit);
		} else {
			QueS3ODraw(unit, unit->model->textureType);
		}
	} else {
		if (unit->isCloaked) {
			drawCloaked.push_back(unit);
		} else {
			unit->Draw();
		}
	}
}


void CUnitDrawer::Draw(bool drawReflection, bool drawRefraction)
{
	ASSERT_UNSYNCED_MODE;

	vector<CUnit*> drawFar;
	vector<CUnit*> drawStat;
	drawCloaked.clear();
	drawCloakedS3O.clear();

	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
	glFogfv(GL_FOG_COLOR,FogLand);

	vector<CUnit*> drawIcon;
	vector<CUnit*> drawRadarIcon;

	if (drawReflection) {
		CUnit::SetLODFactor(LODScale * LODScaleReflection);
	} else if (drawRefraction) {
		CUnit::SetLODFactor(LODScale * LODScaleRefraction);
	} else {
		CUnit::SetLODFactor(LODScale);
	}

	SetupForUnitDrawing();

#ifdef DIRECT_CONTROL_ALLOWED
	CUnit* excludeUnit = drawReflection ? NULL : gu->directControl;
#endif

	for (list<CUnit*>::iterator usi = uh->activeUnits.begin(); usi != uh->activeUnits.end(); ++usi) {
		CUnit* unit = *usi;

#ifdef DIRECT_CONTROL_ALLOWED
		if (unit == excludeUnit) {
			continue;
		}
#endif
		if (unit->noDraw) {
			continue;
		}
		if (camera->InView(unit->midPos, unit->radius + 30)) {
			if (gs->Ally(unit->allyteam,gu->myAllyTeam)       ||
			    (unit->losStatus[gu->myAllyTeam] & LOS_INLOS) ||
			    gu->spectatingFullView) {

				if (drawReflection) {
					float3 zeroPos;
					if (unit->midPos.y < 0.0f) {
						zeroPos = unit->midPos;
					} else {
						const float dif = unit->midPos.y - camera->pos.y;
						zeroPos = camera->pos  * (unit->midPos.y / dif) +
						          unit->midPos * (-camera->pos.y / dif);
					}
					if (ground->GetApproximateHeight(zeroPos.x, zeroPos.z) > unit->radius) {
						continue;
					}
				}

				if (drawRefraction) {
					if (unit->pos.y > 0.0f) {
						continue;
					}
				}

				float sqDist = (unit->pos-camera->pos).SqLength();
				float iconDistMult = iconHandler->GetDistance(unit->unitDef->iconType);
				float realIconLength = iconLength * (iconDistMult * iconDistMult);
				if (sqDist>realIconLength) {
					drawIcon.push_back(unit);
					unit->isIcon = true;
				}
				else {
					unit->isIcon = false;

					float farLength = unit->sqRadius * (unitDrawDist * unitDrawDist);
					if (sqDist>farLength) {
						drawFar.push_back(unit);
					} else {
						DrawUnit(unit);
					}

					if ((sqDist < (unitDrawDist * unitDrawDist * 500)) && showHealthBars) {
						drawStat.push_back(unit);
					}
				}
			}
			else if (unit->losStatus[gu->myAllyTeam] & LOS_PREVLOS) {
				unit->isIcon = true;

				if ((!gameSetup || gameSetup->ghostedBuildings) && !(unit->mobility)) {
					// it's a building we've had LOS on once,
					// add it to the vector of cloaked units
					float sqDist = (unit->pos-camera->pos).SqLength();
					float iconDistMult = iconHandler->GetDistance(unit->unitDef->iconType);
					float realIconLength = iconLength * (iconDistMult * iconDistMult);

					if (sqDist < realIconLength) {
						if (unit->model->textureType) {
							drawCloakedS3O.push_back(unit);
						} else {
							drawCloaked.push_back(unit);
						}
						unit->isIcon = false;
					}
				}
				if ((unit->losStatus[gu->myAllyTeam] & LOS_INRADAR)) {
					if (!(unit->losStatus[gu->myAllyTeam] & LOS_CONTRADAR)) {
						drawRadarIcon.push_back(unit);
					} else if (unit->isIcon) {
						// this prevents us from drawing icons on top of ghosted buildings
						drawIcon.push_back(unit);
					}
				}
			} else if ((unit->losStatus[gu->myAllyTeam] & LOS_INRADAR)) {
				drawRadarIcon.push_back(unit);
			}
		}
	}

	std::multimap<int, TempDrawUnit>::iterator ti;
	for (ti = tempDrawUnits.begin(); ti != tempDrawUnits.end(); ++ti) {
		if (camera->InView(ti->second.pos, 100)) {
			glPushMatrix();
			glTranslatef3(ti->second.pos);
			glRotatef(ti->second.rotation * 180 / PI, 0, 1, 0);
			ti->second.unitdef->LoadModel(ti->second.team)->DrawStatic();
			glPopMatrix();
		}
	}

	DrawQuedS3O();
	CleanUpUnitDrawing();
	DrawOpaqueShaderUnits();

	va = GetVertexArray();
	va->Initialize();
	glAlphaFunc(GL_GREATER, 0.8f);
	glEnable(GL_ALPHA_TEST);
	glBindTexture(GL_TEXTURE_2D, fartextureHandler->farTexture);
	camNorm = camera->forward;
	camNorm.y = -0.1f;
	camNorm.Normalize();
	glColor3f(1, 1, 1);
	glEnable(GL_FOG);
	glFogfv(GL_FOG_COLOR, FogLand);

	for (vector<CUnit*>::iterator usi = drawFar.begin(); usi != drawFar.end(); usi++) {
		DrawFar(*usi);
	}

	va->DrawArrayTN(GL_QUADS);

	if (!drawReflection) {
		// Draw unit icons and radar blips.
		glAlphaFunc(GL_GREATER, 0.5f);
		vector<CUnit*>::iterator ui;
		for (ui = drawIcon.begin(); ui != drawIcon.end(); ++ui) {
			DrawIcon(*ui, false);

⌨️ 快捷键说明

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