//------------------------------------------------------------------------ void CTracer::SetGeometry(const char *name, float scale) { if (IEntity *pEntity=gEnv->pEntitySystem->GetEntity(m_entityId)) { m_geometrySlot =pEntity->LoadGeometry(TRACER_GEOM_SLOT, name); if (scale!=1.0f) { Matrix34 tm=Matrix34::CreateIdentity(); tm.ScaleColumn(Vec3(scale, scale, scale)); pEntity->SetSlotLocalTM(m_geometrySlot, tm); } // Set opacity IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)pEntity->GetProxy(ENTITY_PROXY_RENDER); pRenderProxy->SetOpacity(m_geometryOpacity); } }
//------------------------------------------------------------------------ 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; }