void CSmokeManager::CullOtherSmokeEffectsInProximityWhenGrenadeHasLanded(SSmokeInstance& smokeInstance, IEntity* pGrenade) { if(pGrenade && (smokeInstance.state == eSIS_Active_PhysicsAwake)) { IPhysicalEntity* pPhysEnt = pGrenade->GetPhysics(); if(pPhysEnt) { pe_status_awake psa; if(pPhysEnt->GetStatus(&psa) == false) { // Was awake, now asleep... SSmokeInstance* pOldestSmokeInstanceToDelete = NULL; const int kNumActiveSmokeInstances = m_numActiveSmokeInstances; uint32 otherSmokeInstanceProximityCount = 0; SSmokeInstance* pOtherSmokeInstance = NULL; PrefetchLine(m_smokeInstances, 0); PrefetchLine(m_smokeInstances, 128); // Find oldest smoke grenade effect in proximity for(int i=0; i<kNumActiveSmokeInstances; i++) { pOtherSmokeInstance = &m_smokeInstances[i]; if(pOtherSmokeInstance != &smokeInstance) { PrefetchLine(pOtherSmokeInstance, 128); const float fDistanceSq = Distance::Point_PointSq(smokeInstance.vPositon, pOtherSmokeInstance->vPositon); const float fCombinedRadiusSq = sqr(smokeInstance.fMaxRadius) + sqr(pOtherSmokeInstance->fMaxRadius); if(fDistanceSq < fCombinedRadiusSq) { otherSmokeInstanceProximityCount++; if(pOldestSmokeInstanceToDelete == NULL || (pOldestSmokeInstanceToDelete->fTimer < pOtherSmokeInstance->fTimer)) { pOldestSmokeInstanceToDelete = pOtherSmokeInstance; } } } } // Delete old smoke effect in proximity if there are too many if(pOldestSmokeInstanceToDelete && (otherSmokeInstanceProximityCount >= kMaxSmokeEffectsInSameArea)) { IEntity * pGrenadeToDeleteParticleEmitterFor = gEnv->pEntitySystem->GetEntity(pOldestSmokeInstanceToDelete->grenadeId); if(pGrenadeToDeleteParticleEmitterFor) { int slotCount = pGrenadeToDeleteParticleEmitterFor->GetSlotCount(); for(int i=0; i<slotCount; i++) { IParticleEmitter* pParticleEmitter = pGrenadeToDeleteParticleEmitterFor->GetParticleEmitter(i); if(pParticleEmitter) { pParticleEmitter->Activate(false); } } } pOldestSmokeInstanceToDelete->state = eSIS_ForDeletion; } smokeInstance.state = eSIS_Active_PhysicsAsleep; } } } }
//------------------------------------------------------------------------ void CTracerManager::Update(float frameTime) { CryPrefetch(m_tracerPool); const CCamera& viewCamera = gEnv->pSystem->GetViewCamera(); const Vec3 cameraPosition = viewCamera.GetPosition(); const float viewCameraFovScale = viewCamera.GetFov() / DEG2RAD(g_pGame->GetFOV()); const int kNumActiveTracers = m_numActiveTracers; for(int i = 0; i < kNumActiveTracers;) { int nextTracerIndex = i + 1; CTracer& tracer = m_tracerPool[i]; CryPrefetch(&m_tracerPool[nextTracerIndex]); //Update const bool stillMoving = tracer.Update(frameTime, cameraPosition, viewCameraFovScale); //Is it worth putting this in another loop for instruction cache coherency? Profile when PS3 is up and running - Rich S if(stillMoving || (tracer.m_fadeOutTime > 0.f)) { tracer.m_tracerFlags |= kTracerFlag_active; if (!stillMoving) { tracer.m_fadeOutTime -= frameTime; if (tracer.m_effectSlot > -1) { if (IEntity *pEntity = gEnv->pEntitySystem->GetEntity(tracer.m_entityId)) { IParticleEmitter * emitter = pEntity->GetParticleEmitter(tracer.m_effectSlot); if (emitter) { emitter->Activate(false); } if (tracer.m_tracerFlags & kTracerFlag_useGeometry) { pEntity->SetSlotFlags(tracer.m_geometrySlot, pEntity->GetSlotFlags(tracer.m_geometrySlot) &~ (ENTITY_SLOT_RENDER|ENTITY_SLOT_RENDER_NEAREST)); } tracer.m_effectSlot = -1; } } if(tracer.m_tracerFlags & kTracerFlag_useGeometry) { // Fade out geometry if((tracer.m_fadeOutTime < tracer.m_startFadeOutTime) && (tracer.m_startFadeOutTime > 0.0f)) { if (IEntity *pEntity = gEnv->pEntitySystem->GetEntity(tracer.m_entityId)) { IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)pEntity->GetProxy(ENTITY_PROXY_RENDER); pRenderProxy->SetOpacity(max((tracer.m_fadeOutTime / tracer.m_startFadeOutTime) * tracer.m_geometryOpacity, 0.0f)); } } } } } else { tracer.m_tracerFlags &= ~kTracerFlag_active; tracer.m_boundToBulletId = 0; } i = nextTracerIndex; } //This is where we clear out the inactive tracers, so the counter isn't const int numActiveTracers = kNumActiveTracers; CWeaponSystem* pWeaponSystem = g_pGame->GetWeaponSystem(); for(int i = kNumActiveTracers - 1; i >= 0;) { int nextIndex = i - 1; CTracer& tracer = m_tracerPool[i]; CryPrefetch(&m_tracerPool[nextIndex]); if(!(tracer.m_tracerFlags & kTracerFlag_active)) { if (IEntity *pEntity=gEnv->pEntitySystem->GetEntity(tracer.m_entityId)) { pEntity->Hide(true); pEntity->FreeSlot(TRACER_GEOM_SLOT); pEntity->FreeSlot(TRACER_FX_SLOT); } //Switch the inactive tracer so it's at the end of the array; const int lastTracer = numActiveTracers - 1; static CTracer temp; temp = tracer; numActiveTracers = lastTracer; tracer = m_tracerPool[lastTracer]; m_tracerPool[lastTracer] = temp; //Re-bind index to the corresponding bullet if (tracer.m_boundToBulletId) { CProjectile* pProjectile = pWeaponSystem->GetProjectile(tracer.m_boundToBulletId); if (pProjectile && pProjectile->IsAlive()) { if(lastTracer == pProjectile->GetTracerIdx()) { pProjectile->BindToTracer(i); } else if(lastTracer == pProjectile->GetThreatTrailTracerIdx()) { pProjectile->BindToThreatTrailTracer(i); } } } } i = nextIndex; } m_numActiveTracers = numActiveTracers; }