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

📄 unitdrawer.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		}
		for (ui = drawRadarIcon.begin(); ui != drawRadarIcon.end(); ++ui) {
			DrawIcon(*ui, true);
		}
		glDisable(GL_TEXTURE_2D);
		for (ui = drawStat.begin(); ui != drawStat.end(); ++ui) {
			(*ui)->DrawStats();
		}
	}
	glDisable(GL_TEXTURE_2D);
}


/******************************************************************************/
/******************************************************************************/

static void DrawBins(LuaMatType type)
{
	const LuaMatBinSet& bins = luaMatHandler.GetBins(type);
	if (bins.empty()) {
		return;
	}

	luaDrawing = true;

	glPushAttrib(GL_TEXTURE_BIT | GL_ENABLE_BIT);

	const LuaMaterial* currMat = &LuaMaterial::defMat;

	LuaMatBinSet::const_iterator it;
	for (it = bins.begin(); it != bins.end(); ++it) {
		LuaMatBin* bin = *it;
		bin->Execute(*currMat);
		currMat = (LuaMaterial*)bin;

		const vector<CUnit*>& units = bin->GetUnits();
		const int count = (int)units.size();
		for (int i = 0; i < count; i++) {
			CUnit* unit = units[i];
			const LuaUnitMaterial& unitMat = unit->luaMats[type];
			const LuaUnitLODMaterial* lodMat = unitMat.GetMaterial(unit->currentLOD);

			lodMat->uniforms.Execute(unit);
			unitDrawer->SetS3OTeamColour(unit->team);
			unit->DrawWithLists(lodMat->preDisplayList, lodMat->postDisplayList);
		}
	}

	LuaMaterial::defMat.Execute(*currMat);
	luaMatHandler.ClearBins(type);

	glPopAttrib();

	luaDrawing = false;
}


/******************************************************************************/

static void SetupShadowDrawing()
{
	glColor3f(1.0f, 1.0f, 1.0f);
	glDisable(GL_TEXTURE_2D);
	glBindProgramARB(GL_VERTEX_PROGRAM_ARB, unitDrawer->unitShadowGenVP);
	glEnable(GL_VERTEX_PROGRAM_ARB);
	glPolygonOffset(1.0f, 1.0f);
	glEnable(GL_POLYGON_OFFSET_FILL);

	const CShadowHandler* sh = shadowHandler;
	glProgramEnvParameter4fARB(
		GL_VERTEX_PROGRAM_ARB, 16, sh->xmid, sh->ymid, 0.0f, 0.0f);
	glProgramEnvParameter4fARB(
		GL_VERTEX_PROGRAM_ARB, 17, sh->p17,  sh->p17,  0.0f, 0.0f);
	glProgramEnvParameter4fARB(
		GL_VERTEX_PROGRAM_ARB, 18, sh->p18,  sh->p18,  0.0f, 0.0f);
}


static void CleanUpShadowDrawing()
{
	glDisable(GL_VERTEX_PROGRAM_ARB);
	glDisable(GL_POLYGON_OFFSET_FILL);
}


/******************************************************************************/

static void SetupOpaque3DO() { unitDrawer->SetupForUnitDrawing(); }
static void ResetOpaque3DO() { unitDrawer->CleanUpUnitDrawing();  }
static void SetupOpaqueS3O() { unitDrawer->SetupForS3ODrawing();  }
static void ResetOpaqueS3O() { unitDrawer->CleanUpS3ODrawing();   }

static void SetupAlpha3DO()  { unitDrawer->SetupForGhostDrawing();    }
static void ResetAlpha3DO()  { unitDrawer->CleanUpGhostDrawing();     }
static void SetupAlphaS3O()  { unitDrawer->SetupForGhostDrawing();
                               unitDrawer->SetupForGhostDrawingS3O(); }
static void ResetAlphaS3O()  { unitDrawer->CleanUpGhostDrawing();     }

static void SetupShadow3DO() { SetupShadowDrawing();   }
static void ResetShadow3DO() { CleanUpShadowDrawing(); }
static void SetupShadowS3O() { SetupShadowDrawing();   }
static void ResetShadowS3O() { CleanUpShadowDrawing(); }


/******************************************************************************/

void CUnitDrawer::DrawOpaqueShaderUnits()
{
	luaMatHandler.setup3doShader = SetupOpaque3DO;
	luaMatHandler.reset3doShader = ResetOpaque3DO;
	luaMatHandler.setupS3oShader = SetupOpaqueS3O;
	luaMatHandler.resetS3oShader = ResetOpaqueS3O;

	const LuaMatType matType =
		(water->drawReflection) ? LUAMAT_OPAQUE_REFLECT : LUAMAT_OPAQUE;

	DrawBins(matType);
}


void CUnitDrawer::DrawCloakedShaderUnits()
{
	luaMatHandler.setup3doShader = SetupAlpha3DO;
	luaMatHandler.reset3doShader = ResetAlpha3DO;
	luaMatHandler.setupS3oShader = SetupAlphaS3O;
	luaMatHandler.resetS3oShader = ResetAlphaS3O;

	const LuaMatType matType =
		(water->drawReflection) ? LUAMAT_ALPHA_REFLECT : LUAMAT_ALPHA;

	DrawBins(matType);
}


void CUnitDrawer::DrawShadowShaderUnits()
{
	luaMatHandler.setup3doShader = SetupShadow3DO;
	luaMatHandler.reset3doShader = ResetShadow3DO;
	luaMatHandler.setupS3oShader = SetupShadowS3O;
	luaMatHandler.resetS3oShader = ResetShadowS3O;

	DrawBins(LUAMAT_SHADOW);
}


/******************************************************************************/
/******************************************************************************/

void CUnitDrawer::DrawShadowPass(void)
{
	ASSERT_UNSYNCED_MODE;
	glColor3f(1.0f, 1.0f, 1.0f);
	glDisable(GL_TEXTURE_2D);
//	glEnable(GL_TEXTURE_2D);
//	texturehandler->SetTexture();
	glBindProgramARB(GL_VERTEX_PROGRAM_ARB, unitShadowGenVP);
	glEnable(GL_VERTEX_PROGRAM_ARB);
	glPolygonOffset(1.0f, 1.0f);
	glEnable(GL_POLYGON_OFFSET_FILL);

	CUnit::SetLODFactor(LODScale * LODScaleShadow);

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

		if ((gs->Ally(unit->allyteam, gu->myAllyTeam)     ||
			(unit->losStatus[gu->myAllyTeam] & LOS_INLOS) ||
			gu->spectatingFullView)
		    && camera->InView(unit->midPos, unit->radius + 700)) {

			// FIXME: test against the shadow projection intersection
			float sqDist = (unit->pos-camera->pos).SqLength();
			float farLength = unit->sqRadius * (unitDrawDist * unitDrawDist);

			if (sqDist < farLength) {
				float iconDistMult = iconHandler->GetDistance(unit->unitDef->iconType);
				float realIconLength = iconLength * (iconDistMult * iconDistMult);

				if (sqDist < realIconLength) {
					if (!unit->isCloaked) {
						if (unit->lodCount <= 0) {
							unit->Draw();
						} else {
							LuaUnitMaterial& unitMat = unit->luaMats[LUAMAT_SHADOW];
							const unsigned lod = unit->CalcLOD(unitMat.GetLastLOD());
							unit->currentLOD = lod;
							LuaUnitLODMaterial* lodMat = unitMat.GetMaterial(lod);

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

	glDisable(GL_VERTEX_PROGRAM_ARB);

	glDisable(GL_POLYGON_OFFSET_FILL);

	DrawShadowShaderUnits();

//	glDisable(GL_TEXTURE_2D);
}


inline void CUnitDrawer::DrawFar(CUnit *unit)
{
	float3 interPos = unit->pos + unit->speed * gu->timeOffset + UpVector * unit->model->height * 0.5f;
	int snurr =- unit->heading + GetHeadingFromVector(camera->pos.x - unit->pos.x, camera->pos.z - unit->pos.z) + (0xffff >> 4);

	if (snurr < 0)
		snurr += 0xffff;
	if (snurr > 0xffff)
		snurr -= 0xffff;

	snurr = snurr >> 13;
	float r = 1.0f / 64.0f;
	float tx = (unit->model->farTextureNum % 8) * (1.0f / 8.0f) + snurr * r;
	float ty = (unit->model->farTextureNum / 8) * r;
	float offset = 0;

	va->AddVertexTN(interPos - (camera->up * unit->radius * 1.4f - offset) + camera->right * unit->radius, tx,     ty,     camNorm);
	va->AddVertexTN(interPos + (camera->up * unit->radius * 1.4f + offset) + camera->right * unit->radius, tx,     ty + r, camNorm);
	va->AddVertexTN(interPos + (camera->up * unit->radius * 1.4f + offset) - camera->right * unit->radius, tx + r, ty + r, camNorm);
	va->AddVertexTN(interPos - (camera->up * unit->radius * 1.4f - offset) - camera->right * unit->radius, tx + r, ty,     camNorm);
}


void CUnitDrawer::DrawIcon(CUnit * unit, bool asRadarBlip)
{
	// If the icon is to be drawn as a radar blip, we want to get the default icon.
	std::string iconType;
	if(asRadarBlip){
		iconType="default";
	} else {
		iconType=unit->unitDef->iconType;
	}

	// Fetch the icon information.
	CIcon* icon=iconHandler->GetIcon(iconType);

	unsigned char color[4];
	color[3]=255;

	// Calculate the icon size. It scales with:
	//  * The square root of the camera distance.
	//  * The mod defined 'iconSize' (which acts a multiplier).
	//  * The unit radius, depending on whether the mod defined 'radiusadjust' is true or false.
	float3 pos;
	if (gu->spectatingFullView) {
		pos = unit->midPos;
	} else {
		pos = helper->GetUnitErrorPos(unit,gu->myAllyTeam);
	}
	float dist=sqrt((pos-camera->pos).Length());
	float scale=0.4f*icon->size*dist;
	if (icon->radiusAdjust && !asRadarBlip) {
		scale=scale*unit->radius/30; // I take the standard unit radius to be 30 ... call it an educated guess. (Teake Nutma)
	}

	unit->iconRadius = scale; // store the icon size so that we don't have to calculate it again

	// Is the unit selected? Then draw it white.
	if (unit->commandAI->selected) {
		color[0] = 255;
		color[1] = 255;
		color[2] = 255;
	} else {
		color[0] = gs->Team(unit->team)->color[0];
		color[1] = gs->Team(unit->team)->color[1];
		color[2] = gs->Team(unit->team)->color[2];
	}

	// If the icon is partly under the ground, move it up.
	const float h = ground->GetHeight(pos.x, pos.z);
	if (pos.y < (h + scale)) {
		pos.y = (h + scale);
	}

	// Draw the icon.
	glBindTexture(GL_TEXTURE_2D, icon->texture);
	va = GetVertexArray();
	va->Initialize();
	va->AddVertexTC(pos + camera->up * scale + camera->right * scale, 1, 0, color);
	va->AddVertexTC(pos - camera->up * scale + camera->right * scale, 1, 1, color);
	va->AddVertexTC(pos - camera->up * scale - camera->right * scale, 0, 1, color);
	va->AddVertexTC(pos + camera->up * scale - camera->right * scale, 0, 0, color);
	va->DrawArrayTC(GL_QUADS);
}


void CUnitDrawer::SetupForGhostDrawing()
{
	glPushAttrib (GL_TEXTURE_BIT | GL_ENABLE_BIT);
	glEnable(GL_TEXTURE_2D);

	texturehandler->SetTATexture();
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
}


void CUnitDrawer::SetupForGhostDrawingS3O()
{
	SetupBasicS3OTexture0();
	SetupBasicS3OTexture1();
	// use the alpha given by glColor for the outgoing alpha.
	// (might need to change this if we ever have transparent bits on units?)
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);

	glActiveTextureARB(GL_TEXTURE0_ARB);
}


void CUnitDrawer::CleanUpGhostDrawing()
{
	glPopAttrib();
	glDisable(GL_TEXTURE_2D);
	glDepthMask(1);
	glDisable(GL_ALPHA_TEST);

	// clean up s3o drawing stuff
	// reset texture1 state
	CleanupBasicS3OTexture1();

	// also reset the alpha generation
	glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_ALPHA_ARB, GL_MODULATE);
	glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);

	// reset texture0 state
	CleanupBasicS3OTexture0();
}


void CUnitDrawer::DrawCloakedUnits(void)
{
	SetupForGhostDrawing();

	glEnable(GL_TEXTURE_2D);
	glDisable(GL_CULL_FACE);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glAlphaFunc(GL_GREATER, 0.1f);
	glEnable(GL_ALPHA_TEST);
	glColor4f(1, 1, 1, 0.3f);
	glDepthMask(0);

	// units drawn by AI, these aren't really
	// cloaked but the effect is the same
	for (std::multimap<int, TempDrawUnit>::iterator ti = tempTransparentDrawUnits.begin(); ti != tempTransparentDrawUnits.end(); ++ti) {
		if (camera->InView(ti->second.pos, 100)) {
			glPushMatrix();
			glTranslatef3(ti->second.pos);
			glRotatef(ti->second.rotation * 180 / PI, 0, 1, 0);
			S3DOModel* model = ti->second.unitdef->LoadModel(ti->second.team);
			model->DrawStatic();
			glPopMatrix();
		}
		if (ti->second.drawBorder) {
			float3 pos = ti->second.pos;
			const UnitDef *unitdef = ti->second.unitdef;

			BuildInfo bi(unitdef, pos, ti->second.facing);
			pos = helper->Pos2BuildPos(bi);

			float xsize = bi.GetXSize() * 4;
			float ysize = bi.GetYSize() * 4;
			glColor4f(0.2f, 1, 0.2f, 0.7f);
			glDisable(GL_TEXTURE_2D);
			glBegin(GL_LINE_STRIP);
			glVertexf3(pos+float3( xsize, 1,  ysize));
			glVertexf3(pos+float3(-xsize, 1,  ysize));
			glVertexf3(pos+float3(-xsize, 1, -ysize));
			glVertexf3(pos+float3( xsize, 1, -ysize));
			glVertexf3(pos+float3( xsize, 1,  ysize));
			glEnd();
			glColor4f(1, 1, 1, 0.3f);
			glEnable(GL_TEXTURE_2D);
		}
	}


	// 3dos
	DrawCloakedUnitsHelper(drawCloaked, ghostBuildings, false);

	// s3os
	SetupForGhostDrawingS3O();
	glColor4f(1, 1, 1, 0.3f);
	DrawCloakedUnitsHelper(drawCloakedS3O, ghostBuildingsS3O, true);

	// reset gl states
	CleanUpGhostDrawing();

	// shader rendering
	DrawCloakedShaderUnits();
}


void CUnitDrawer::DrawCloakedUnitsHelper(std::vector<CUnit*>& dC, std::list<GhostBuilding*>& gB, bool is_s3o)
{
	// cloaked units and living ghosted buildings (stored in same vector)
	for (vector<CUnit*>::iterator ui = dC.begin(); ui != dC.end(); ++ui) {
		CUnit* unit = *ui;

		if ((unit->losStatus[gu->myAllyTeam] & LOS_INLOS) || gu->spectatingFullView) {
			if (is_s3o) {
				SetBasicS3OTeamColour(unit->team);
				texturehandler->SetS3oTexture(unit->model->textureType);
			}

⌨️ 快捷键说明

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