//------------------------------------------------------------------ // collide joints with each other. Skip particles too close //------------------------------------------------------------------ bool CChain::SelfCollide() { bool bCollided = false; for(int i = 0; i < GetNumParticles(); i ++) { for (int j = i + m_iSelfCollisionStep; j < GetNumParticles(); j ++) { bCollided |= GetParticle(i).Collide(GetParticle(j)); } } return bCollided; }
void ParticleManager::_DEBUG_ShowParticleStats() { char text[50]; sprintf(text, "Particles: %d", GetNumParticles()); VideoManager->Move(896.0f, 690.0f); TextManager->Draw(text); }
void ParticleSystems::SystemActions::Draw( const Input::Camera& _camera ) { if(!GetNumParticles()) return; // Upload current transformation matrix Mat4x4 modelViewProj = m_systemTransformation.GetTransformation(_camera.Transformation()); modelViewProj = _camera.GetProjection() * modelViewProj; Resources::GetUBO(UniformBuffers::SIMPLE_OBJECT)["WorldViewProjection"] = modelViewProj; // Set renderer and do draw call. The set has no effect if the renderer is // currently active. switch(m_renderer) { case RenderType::BLOB: Device::SetEffect( Resources::GetEffect(Effects::BLOB_PARTICLE) ); } m_particleVertices.Bind(); Graphic::Device::DrawVertices( m_particleVertices, 0, GetNumParticles() ); }
LTBOOL CBulletTrailFX::Update() { if (!m_hObject || !m_pClientDE) return LTFALSE; LTFLOAT fTime = m_pClientDE->GetTime(); if (m_bFirstUpdate) { // See if we can figure out what color bubbles to make, based on the // container we start in... HLOCALOBJ objList[1]; uint32 dwNum = m_pClientDE->GetPointContainers(&m_vStartPos, objList, 1); if (dwNum > 0 && objList[0]) { uint32 dwUserFlags; m_pClientDE->GetObjectUserFlags(objList[0], &dwUserFlags); if (dwUserFlags & USRFLG_VISIBLE) { uint16 dwCode; if (m_pClientDE->GetContainerCode(objList[0], &dwCode)) { GetLiquidColorRange((ContainerCode)dwCode, &m_vColor1, &m_vColor2); } } } // Move the particle system to the correct position... m_pClientDE->SetObjectPos(m_hObject, &m_vStartPos); m_bFirstUpdate = LTFALSE; m_fStartTime = fTime; m_fLastTime = fTime; VEC_INIT(m_vLastPos); // Find the end position... ClientIntersectQuery iQuery; ClientIntersectInfo iInfo; LTVector vTemp, vEndPoint; VEC_MULSCALAR(vTemp, m_vDir, MAX_TRAIL_LENGTH); VEC_ADD(vEndPoint, m_vStartPos, vTemp); VEC_COPY(iQuery.m_From, m_vStartPos); VEC_COPY(iQuery.m_To, vEndPoint); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vEndPoint, iInfo.m_Point, m_vStartPos); m_fDistance = VEC_MAG(vEndPoint); } if (m_fDistance <= 0.0f || m_fFadeTime <= 0.0f) return LTFALSE; // Calculate the trail velocity... m_fTrailVel = m_fDistance / m_fFadeTime; VEC_MULSCALAR(m_vDir, m_vDir, m_fTrailVel); } // Check to see if we should just wait for last bubble to go away... if (fTime > m_fStartTime + m_fFadeTime) { if (fTime > m_fLastTime + m_fLifeTime) { return LTFALSE; } LTFLOAT fScale = (m_fLifeTime - (fTime - m_fLastTime)) / m_fLifeTime; // m_pClientDE->SetParticleSystemColorScale(m_hObject, fScale); LTFLOAT r, g, b, a; m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a); m_pClientDE->SetObjectColor(m_hObject, r, g, b, fScale); return LTTRUE; } // Create the necessary particles... LTFLOAT fTimeOffset = g_pGameClientShell->GetFrameTime(); // Calculate distance traveled this frame... LTFLOAT fDist = m_fTrailVel * fTimeOffset; if (fDist > m_fDistance) fDist = m_fDistance; m_fDistTraveled += fDist; if (m_fDistTraveled > m_fDistance) { fDist = m_fDistance - (m_fDistTraveled - fDist); if (fDist <= 0.0f) return LTTRUE; } // Calculate number of particles to create... LTFLOAT fNumParticles = fDist * m_fNumParticles / m_fDistance; // Calculate starting bubble position... LTVector vCurPos, vPos, vDelta, vTemp, vDriftVel, vColor; VEC_MULSCALAR(vTemp, m_vDir, fTimeOffset); VEC_ADD(vCurPos, m_vLastPos, vTemp); // What is the range of colors? LTFLOAT fRange = m_vColor2.x - m_vColor1.x; // Fill the distance between the last projectile position, and it's // current position with bubbles... VEC_SUB(vTemp, vCurPos, m_vLastPos); VEC_MULSCALAR(vDelta, vTemp, 1.0f/fNumParticles); VEC_COPY(vPos, m_vLastPos); LTFLOAT fLifeTime = 100.0f; LTFLOAT fOffset = 0.0f; LTVector vDriftOffset; VEC_SET(vDriftOffset, 0.0f, 0.0f, 0.0f); int nNumParticles = GetNumParticles((int)fNumParticles); for (int i=0; i < nNumParticles; i++) { // Build the individual bubbless... for (int j=0; j < 1; j++) { VEC_COPY(vTemp, vPos); VEC_SET(vDriftVel, 0.0f, GetRandom(5.0f, 6.0f), 0.0f); vTemp.x += GetRandom(-fOffset, fOffset); vTemp.y += GetRandom(-fOffset, fOffset); vTemp.z += GetRandom(-fOffset, fOffset); GetRandomColorInRange(vColor); m_pClientDE->AddParticle(m_hObject, &vTemp, &vDriftVel, &vColor, fLifeTime); } VEC_ADD(vPos, vPos, vDelta); } VEC_COPY(m_vLastPos, vCurPos); m_fLastTime = fTime; return LTTRUE; }
LTBOOL CSmokeFX::Update() { if (!m_hObject || !m_pClientDE ) return LTFALSE; if( g_pGameClientShell->IsServerPaused() ) { g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, FLAG_PAUSED, FLAG_PAUSED); return LTTRUE; } //make sure we aren't paused g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, 0, FLAG_PAUSED); LTFLOAT fFrameTime = m_pClientDE->GetFrameTime(); m_fElapsedTime += fFrameTime; m_fElapsedEmissionTime += fFrameTime; // Hide/show the particle system if necessary... if (m_hServerObject) { uint32 dwUserFlags; g_pCommonLT->GetObjectFlags(m_hServerObject, OFT_User, dwUserFlags); if (!(dwUserFlags & USRFLG_VISIBLE)) { uint32 dwFlags; g_pCommonLT->GetObjectFlags(m_hObject, OFT_Flags, dwFlags); // Once last puff as disappeared, hide the system (no new puffs // will be added...) if (dwFlags & FLAG_VISIBLE) { if (m_fElapsedEmissionTime > m_fMaxParticleLife) { g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, 0, FLAG_VISIBLE); } } else { m_fElapsedEmissionTime = 0.0f; } return LTTRUE; } else { g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, FLAG_VISIBLE, FLAG_VISIBLE); } } // Check to see if we should just wait for last smoke puff to go away... if (m_fElapsedTime > m_fLifeTime) { if (m_fElapsedEmissionTime > m_fMaxParticleLife) { return LTFALSE; } return LTTRUE; } // See if it is time to add some more smoke... if (m_fElapsedEmissionTime >= m_fParticleCreateDelta) { LTVector vDriftVel, vColor, vPos; // What is the range of colors? LTFLOAT fRange = m_vColor2.x - m_vColor1.x; // Determine how many particles to add... int nNumParticles = GetNumParticles(m_nNumParticles); // Build the individual smoke puffs... for (int j=0; j < nNumParticles; j++) { VEC_SET(vPos, GetRandom(-m_fVolumeRadius, m_fVolumeRadius), -2.0f, GetRandom(-m_fVolumeRadius, m_fVolumeRadius)); VEC_SET(vDriftVel, GetRandom(m_vMinDriftVel.x, m_vMaxDriftVel.x), GetRandom(m_vMinDriftVel.y, m_vMaxDriftVel.y), GetRandom(m_vMinDriftVel.z, m_vMaxDriftVel.z)); if (!m_bIgnoreWind) { VEC_ADD(vDriftVel, vDriftVel, g_vWorldWindVel); } GetRandomColorInRange(vColor); LTFLOAT fLifeTime = GetRandom(m_fMinParticleLife, m_fMaxParticleLife); vDriftVel -= (m_vVel * 0.1f); m_pClientDE->AddParticle(m_hObject, &vPos, &vDriftVel, &vColor, fLifeTime); } m_fElapsedEmissionTime = 0.0f; } return CBaseParticleSystemFX::Update(); }
LTBOOL CParticleTrailSegmentFX::Update() { if (!m_hObject || !m_pClientDE) return LTFALSE; if (!CBaseParticleSystemFX::Update()) return LTFALSE; CGameSettings* pSettings = g_pInterfaceMgr->GetSettings(); if (!pSettings) return LTFALSE; uint8 nDetailLevel = pSettings->SpecialFXSetting(); LTFLOAT fTime = m_pClientDE->GetTime(); if (m_bFirstUpdate) { if (!m_hServerObject) return LTFALSE; m_bFirstUpdate = LTFALSE; m_fStartTime = fTime; m_fLastTime = fTime; // Where is the server (moving) object... LTVector vPos, vTemp; m_pClientDE->GetObjectPos(m_hServerObject, &vPos); // Current position is relative to the particle system's postion (i.e., // each puff of Particle is some distance away from the particle system's /// position)... m_pClientDE->GetObjectPos(m_hObject, &vTemp); VEC_SUB(vPos, vPos, vTemp); VEC_COPY(m_vLastPos, vPos); } // Check to see if we should just wait for last Particle puff to go away... if (m_bWantRemove || (fTime > m_fStartTime + m_fFadeTime)) { if (fTime > m_fLastTime + m_fLifeTime) { return LTFALSE; } LTFLOAT fScale = (m_fLifeTime - (fTime - m_fLastTime)) / m_fLifeTime; LTFLOAT r, g, b, a; m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a); m_pClientDE->SetObjectColor(m_hObject, r, g, b, fScale); return LTTRUE; } // See if it is time to create a new Particle puff... if ((fTime > m_fLastTime + m_fOffsetTime) && m_hServerObject) { LTVector vCurPos, vPos, vDelta, vTemp, vDriftVel, vColor; // Calculate Particle puff position... // Where is the server (moving) object... m_pClientDE->GetObjectPos(m_hServerObject, &vCurPos); // Current position is relative to the particle system's postion (i.e., // each puff of Particle is some distance away from the particle system's /// position)... m_pClientDE->GetObjectPos(m_hObject, &vTemp); VEC_SUB(vCurPos, vCurPos, vTemp); // How long has it been since the last Particle puff? LTFLOAT fTimeOffset = fTime - m_fLastTime; // What is the range of colors? LTFLOAT fRange = m_vColor2.x - m_vColor1.x; // Fill the distance between the last projectile position, and it's // current position with Particle puffs... int nNumSteps = (m_fLastTime > 0) ? (((m_nType & PT_BLOOD) || (m_nType & PT_GIBSMOKE)) ? 20 : 5): 1; if (nDetailLevel != RS_HIGH) { nNumSteps /= 2; } VEC_SUB(vTemp, vCurPos, m_vLastPos); VEC_MULSCALAR(vDelta, vTemp, 1.0f/float(nNumSteps)); VEC_COPY(vPos, m_vLastPos); LTFLOAT fCurLifeTime = 10.0f; if (nDetailLevel == RS_HIGH) { fCurLifeTime /= 2; } LTFLOAT fLifeTimeOffset = fTimeOffset / float(nNumSteps); LTFLOAT fOffset = 0.5f; int nNumPerPuff = GetNumParticles(m_nNumPerPuff); for (int i=0; i < nNumSteps; i++) { // Build the individual Particle puffs... for (int j=0; j < nNumPerPuff; j++) { VEC_COPY(vTemp, vPos); if (m_bIgnoreWind) { VEC_SET(vDriftVel, GetRandom(-m_vDriftOffset.x*2.0f, -m_vDriftOffset.x), GetRandom(5.0f, 6.0f), GetRandom(-m_vDriftOffset.z, m_vDriftOffset.z)); } else { VEC_SET(vDriftVel, g_vWorldWindVel.x + GetRandom(-m_vDriftOffset.x*2.0f, -m_vDriftOffset.x), g_vWorldWindVel.y + GetRandom(5.0f, 6.0f), g_vWorldWindVel.z + GetRandom(-m_vDriftOffset.z, m_vDriftOffset.z)); } vTemp.x += GetRandom(-fOffset, fOffset); vTemp.y += GetRandom(-fOffset, fOffset); vTemp.z += GetRandom(-fOffset, fOffset); GetRandomColorInRange(vColor); m_pClientDE->AddParticle(m_hObject, &vTemp, &vDriftVel, &vColor, fCurLifeTime); } VEC_ADD(vPos, vPos, vDelta); fCurLifeTime += fLifeTimeOffset; } m_fLastTime = fTime; VEC_COPY(m_vLastPos, vCurPos); } return LTTRUE; }
void CParticleExplosionFX::AddParticles(MovingObject* pObject) { if (!m_hObject || !m_pClientDE || !pObject || pObject->m_dwPhysicsFlags & MO_RESTING) return; LTFLOAT fTime = m_pClientDE->GetTime(); LTVector vCurPos, vLastPos, vPos, vDelta, vTemp, vDriftVel, vColor; vCurPos = pObject->m_vPos; vLastPos = pObject->m_vLastPos; // Calculate Particle puff positions... // Current position is relative to the particle system's postion (i.e., // each puff of Particle is some distance away from the particle system's // position)... VEC_SUB(vCurPos, vCurPos, m_vPos); VEC_SUB(vLastPos, vLastPos, m_vPos); // How long has it been since the last Particle puff? LTFLOAT fTimeOffset = fTime - m_fLastTime; // Fill the distance between the last projectile position, and it's // current position with Particle puffs... VEC_SUB(vTemp, vCurPos, vLastPos); VEC_MULSCALAR(vDelta, vTemp, 1.0f/float(m_nNumSteps)); VEC_COPY(vPos, vLastPos); LTFLOAT fCurLifeTime = 10.0f; LTFLOAT fLifeTimeOffset = fTimeOffset / float(m_nNumSteps); LTFLOAT fOffset = 0.5f; int nNumPerPuff = GetNumParticles(m_nNumPerPuff); for (int i=0; i < m_nNumSteps; i++) { // Build the individual Particle puffs... for (int j=0; j < nNumPerPuff; j++) { VEC_COPY(vTemp, vPos); VEC_SET(vDriftVel, GetRandom(m_vMinDriftVel.x, m_vMaxDriftVel.x), GetRandom(m_vMinDriftVel.y, m_vMaxDriftVel.y), GetRandom(m_vMinDriftVel.z, m_vMaxDriftVel.z)); if (!m_bIgnoreWind) { vDriftVel.x += g_vWorldWindVel.x; vDriftVel.y += g_vWorldWindVel.y; vDriftVel.z += g_vWorldWindVel.z; } vTemp.x += GetRandom(-fOffset, fOffset); vTemp.y += GetRandom(-fOffset, fOffset); vTemp.z += GetRandom(-fOffset, fOffset); GetRandomColorInRange(vColor); m_pClientDE->AddParticle(m_hObject, &vTemp, &vDriftVel, &vColor, fCurLifeTime); } VEC_ADD(vPos, vPos, vDelta); fCurLifeTime += fLifeTimeOffset; } }
LTBOOL CParticleSystemFX::Update() { if (!m_hObject || !m_pClientDE || m_bWantRemove) return LTFALSE; LTFLOAT fTime = m_pClientDE->GetTime(); // Hide/show the particle system if necessary... if (m_hServerObject) { uint32 dwUserFlags; g_pCommonLT->GetObjectFlags(m_hServerObject, OFT_User, dwUserFlags); if (!(dwUserFlags & USRFLG_VISIBLE)) { uint32 dwFlags; g_pCommonLT->GetObjectFlags(m_hObject, OFT_Flags, dwFlags); // Once last puff as disappeared, hide the system (no new puffs // will be added...) if (dwFlags & FLAG_VISIBLE) { if (fTime > m_fLastTime + m_cs.fParticleLifetime) { g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, 0, FLAG_VISIBLE); } } else { m_fLastTime = fTime; } return LTTRUE; } else { g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, FLAG_VISIBLE, FLAG_VISIBLE); } } // Debugging aid... if (s_cvarTweak.GetFloat() > 0) { TweakSystem(); } if (m_bFirstUpdate) { m_fLastTime = fTime; m_bFirstUpdate = LTFALSE; } // Make sure it is time to update... if (fTime < m_fLastTime + m_fNextUpdate) { return LTTRUE; } // Ok, how many to add this frame....(make sure time delta is no more than // 15 frames/sec... float fTimeDelta = fTime - m_fLastTime; fTimeDelta = fTimeDelta > 0.0666f ? 0.0666f : fTimeDelta; int nToAdd = (int) floor(m_cs.fParticlesPerSecond * fTimeDelta); nToAdd = LTMIN(nToAdd, (int)(MAX_PARTICLES_PER_SECOND * fTimeDelta)); nToAdd = GetNumParticles(nToAdd); m_pClientDE->AddParticles(m_hObject, nToAdd, &m_vMinOffset, &m_vMaxOffset, // Position offset &(m_cs.vMinVel), &(m_cs.vMaxVel), // Velocity &(m_cs.vColor1), &(m_cs.vColor2), // Color m_cs.fParticleLifetime, m_cs.fParticleLifetime); // Determine when next update should occur... if (m_cs.fBurstWait > 0.001f) { m_fNextUpdate = m_cs.fBurstWait * GetRandom(m_cs.fBurstWaitMin, m_cs.fBurstWaitMax); } else { m_fNextUpdate = 0.001f; } // Rotate the particle system... if (m_cs.fRotationVelocity != 0.0f) { LTRotation rRot; g_pLTClient->GetObjectRotation(m_hObject, &rRot); rRot.Rotate(rRot.Up(), g_pGameClientShell->GetFrameTime() * m_cs.fRotationVelocity); g_pLTClient->SetObjectRotation(m_hObject, &rRot); } m_fLastTime = fTime; return LTTRUE; }