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(); } } } }
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); }