void CProjectileHandler::DrawProjectiles(const ProjectileContainer& pc, bool drawReflection, bool drawRefraction) {
	for (ProjectileContainer::render_iterator pci = pc.render_begin(); pci != pc.render_end(); ++pci) {
		CProjectile* pro = *pci;

		pro->UpdateDrawPos();

		if (camera->InView(pro->pos, pro->drawRadius) && (gu->spectatingFullView || loshandler->InLos(pro, gu->myAllyTeam) ||
			(pro->owner() && teamHandler->Ally(pro->owner()->allyteam, gu->myAllyTeam)))) {

			CUnit* owner = pro->owner();
			bool stunned = owner? owner->stunned: false;

			if (owner && stunned && dynamic_cast<CShieldPartProjectile*>(pro)) {
				// if the unit that fired this projectile is stunned and the projectile
				// forms part of a shield (ie., the unit has a CPlasmaRepulser weapon but
				// cannot fire it), prevent the projectile (shield segment) from being drawn
				//
				// also prevents shields being drawn at unit's pre-pickup position
				// (since CPlasmaRepulser::Update() is responsible for updating
				// CShieldPartProjectile::centerPos) if the unit is in a non-fireplatform
				// transport
				continue;
			}

			if (drawReflection) {
				if (pro->pos.y < -pro->drawRadius)
					continue;

				float dif = pro->pos.y - camera->pos.y;
				float3 zeroPos = camera->pos * (pro->pos.y / dif) + pro->pos * (-camera->pos.y / dif);

				if (ground->GetApproximateHeight(zeroPos.x, zeroPos.z) > 3 + 0.5f * pro->drawRadius)
					continue;
			}

			if (drawRefraction && pro->pos.y > pro->drawRadius)
				continue;

			if (pro->s3domodel) {
				if (pro->s3domodel->type == MODELTYPE_S3O) {
					unitDrawer->QueS3ODraw(pro, pro->s3domodel->textureType);
				} else {
					pro->DrawUnitPart();
				}
			}

			pro->tempdist = pro->pos.dot(camera->forward);
			distset.insert(pro);
		}
	}
}
void CProjectileHandler::DrawProjectilesShadow(const ProjectileContainer& pc) {
	for (ProjectileContainer::render_iterator pci = pc.render_begin(); pci != pc.render_end(); ++pci) {
		CProjectile* p = *pci;

		if ((gu->spectatingFullView || loshandler->InLos(p, gu->myAllyTeam) ||
			(p->owner() && teamHandler->Ally(p->owner()->allyteam, gu->myAllyTeam)))) {

			if (p->s3domodel) {
				p->DrawUnitPart();
			} else if (p->castShadow) {
				p->Draw();
			}
		}
	}
}
Beispiel #3
0
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. */

	unitDrawer->SetupForUnitDrawing();
	unitDrawer->SetupFor3DO();
	GML_RECMUTEX_LOCK(proj); // Draw

	Projectile_List::iterator psi;
	distlist.clear();

	// Projectiles (3do's get rendered, s3o qued)
	for (psi = ps.begin(); psi != ps.end(); ++psi) {
		CProjectile* pro = *psi;

		pro->UpdateDrawPos();

		if (camera->InView(pro->pos, pro->drawRadius) && (gu->spectatingFullView || loshandler->InLos(pro, gu->myAllyTeam) ||
			(pro->owner() && teamHandler->Ally(pro->owner()->allyteam, gu->myAllyTeam)))) {

			CUnit* owner = pro->owner();
			CUnit* trans = owner? (CUnit*) owner->GetTransporter(): 0;
			bool stunned = owner? owner->stunned: false;

			if (owner && trans && stunned && dynamic_cast<CShieldPartProjectile*>(pro)) {
				// if the unit that fired this projectile is inside a non-firebase
				// transport (so stunned) and the projectile forms part of a shield
				// (ie., the unit has a CPlasmaRepulser weapon but cannot fire it),
				// prevent the projectile (shield segment) from being drawn at the
				// unit's pre-pickup position (since CPlasmaRepulser::Update() is
				// responsible for updating CShieldPartProjectile::centerPos)
				continue;
			}


			if (drawReflection) {
				if (pro->pos.y < -pro->drawRadius)
					continue;

				float dif = pro->pos.y - camera->pos.y;
				float3 zeroPos = camera->pos * (pro->pos.y / dif) + pro->pos * (-camera->pos.y / dif);

				if (ground->GetApproximateHeight(zeroPos.x, zeroPos.z) > 3 + 0.5f * pro->drawRadius)
					continue;
			}
			if (drawRefraction && pro->pos.y > pro->drawRadius)
				continue;

			if (pro->s3domodel) {
				if (pro->s3domodel->textureType) {
					unitDrawer->QueS3ODraw(pro, pro->s3domodel->textureType);
				} else {
					pro->DrawUnitPart();
				}
			}

			struct projdist tmp;
			tmp.proj = pro;
			tmp.dist = pro->pos.dot(camera->forward);
			distlist.push_back(tmp);
		}
	}

	// 3DO flying pieces
	va->Initialize();
	va->EnlargeArrays(flying3doPieces->size()*4,0,VA_SIZE_TN);
	numFlyingPieces += flying3doPieces->size();
	for(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;
		C3DOTextureHandler::UnitTexture* tex=(*pi)->prim->texture;
		const std::vector<S3DOVertex>& vertices    = (*pi)->object->vertices;
		const std::vector<int>&        verticesIdx = (*pi)->prim->vertices;

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

		v=&vertices[verticesIdx[1]];
		tp=m.Mul(v->pos);
		tn=m.Mul(v->normal);
		tp+=interPos;
		va->AddVertexQTN(tp,tex->xend,tex->ystart,tn);

		v=&vertices[verticesIdx[2]];
		tp=m.Mul(v->pos);
		tn=m.Mul(v->normal);
		tp+=interPos;
		va->AddVertexQTN(tp,tex->xend,tex->yend,tn);

		v=&vertices[verticesIdx[3]];
		tp=m.Mul(v->pos);
		tn=m.Mul(v->normal);
		tp+=interPos;
		va->AddVertexQTN(tp,tex->xstart,tex->yend,tn);
	}
	drawnPieces+=va->drawIndex()/32;

	unitDrawer->CleanUp3DO();

	// draw qued S3O projectiles
	unitDrawer->DrawQuedS3O();

	// S3O flying pieces
	va->DrawArrayTN(GL_QUADS);
	for (int textureType = 1; textureType < flyings3oPieces.size(); textureType++){
		/* TODO Skip this if there's no FlyingPieces. */

		texturehandlerS3O->SetS3oTexture(textureType);

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

			unitDrawer->SetTeamColour(team);

			va->Initialize();
			va->EnlargeArrays(fpl->size()*4,0,VA_SIZE_TN);

			numFlyingPieces += fpl->size();

			for(list<FlyingPiece*>::iterator pi=fpl->begin();pi!=fpl->end();++pi){
				CMatrix44f m;
				m.Rotate((*pi)->rot,(*pi)->rotAxis);
				float3 interPos=(*pi)->pos+(*pi)->speed*gu->timeOffset;

				SS3OVertex * verts = (*pi)->verts;

				float3 tp, tn;

				for (int i = 0; i < 4; i++){
					tp=m.Mul(verts[i].pos);
					tn=m.Mul(verts[i].normal);
					tp+=interPos;
					va->AddVertexQTN(tp,verts[i].textureX,verts[i].textureY,tn);
				}
			}
			drawnPieces+=va->drawIndex()/32;
			va->DrawArrayTN(GL_QUADS);
		}
	}
	unitDrawer->CleanUpUnitDrawing();

	// Alpha transculent particles
	sort(distlist.begin(), distlist.end(), CompareProjDist);

	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_TEXTURE_2D);
	textureAtlas->BindTexture();
	glColor4f(1,1,1,0.2f);
	glAlphaFunc(GL_GREATER,0.0f);
	glEnable(GL_ALPHA_TEST);
	glDepthMask(0);
//	glFogfv(GL_FOG_COLOR,mapInfo->atmosphere.fogColor);
	glDisable(GL_FOG);

	currentParticles=0;
	CProjectile::inArray=false;
	CProjectile::va=GetVertexArray();
	CProjectile::va->Initialize();
	for(int a=0;a<distlist.size();a++){
		distlist.at(a).proj->Draw();
	}
	if(CProjectile::inArray)
		CProjectile::DrawArray();

	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	//glDisable(GL_TEXTURE_2D);
	glDisable(GL_ALPHA_TEST);
	glColor4f(1,1,1,1.0f);
	glDepthMask(1);

	currentParticles=(int)(ps.size()*0.8f+currentParticles*0.2f);
	currentParticles+=(int)(0.2f*drawnPieces+0.3f*numFlyingPieces);
	particleSaturation=(float)currentParticles/(float)maxParticles;
//	glFogfv(GL_FOG_COLOR,mapInfo->atmosphere.fogColor);
}