void ParticleInstance::emitNewParticles(float p_DeltaTime) { DirectX::XMFLOAT3 tempPos = DirectX::XMFLOAT3(m_SysPosition.x, m_SysPosition.y, m_SysPosition.z); DirectX::XMFLOAT4 tempColor = m_SysBaseColor; m_AccumulatedTime += p_DeltaTime; const float timePerParticle = 1.f / m_ParticleEffectDef->particlesPerSec; //check if new particles are to be emitted or not while (m_AccumulatedTime > timePerParticle) { m_AccumulatedTime -= timePerParticle; if (m_ParticleList.size() >= m_ParticleEffectDef->maxParticles) { break; } //Velocity std::uniform_real_distribution<float> velDistributionX(-m_ParticleEffectDef->velocityDeviation.x, m_ParticleEffectDef->velocityDeviation.x); std::uniform_real_distribution<float> velDistributionY(-m_ParticleEffectDef->velocityDeviation.y, m_ParticleEffectDef->velocityDeviation.y); std::uniform_real_distribution<float> velDistributionZ(-m_ParticleEffectDef->velocityDeviation.z, m_ParticleEffectDef->velocityDeviation.z); DirectX::XMFLOAT3 randVel( m_ParticleEffectDef->velocitybase.x + velDistributionX(m_RandomEngine), m_ParticleEffectDef->velocitybase.y + velDistributionY(m_RandomEngine), m_ParticleEffectDef->velocitybase.z + velDistributionZ(m_RandomEngine)); DirectX::XMMATRIX tempRotationM = DirectX::XMMatrixRotationRollPitchYaw(m_SysRotation.y, m_SysRotation.x, m_SysRotation.z); DirectX::XMVECTOR tempVEC = DirectX::XMLoadFloat3(&randVel); tempVEC = DirectX::XMVector3Transform(tempVEC, tempRotationM); DirectX::XMStoreFloat3(&randVel, tempVEC); //Position std::uniform_real_distribution<float> posDistribution(-m_ParticleEffectDef->particlePositionDeviation, m_ParticleEffectDef->particlePositionDeviation); DirectX::XMFLOAT3 randPos( tempPos.x + posDistribution(m_RandomEngine), tempPos.y + posDistribution(m_RandomEngine), tempPos.z + posDistribution(m_RandomEngine)); //Life std::uniform_real_distribution<float> lifeDistribution(-m_ParticleEffectDef->maxLifeDeviation, m_ParticleEffectDef->maxLifeDeviation); float randMaxLife = m_ParticleEffectDef->maxLife + lifeDistribution(m_RandomEngine); //Color std::uniform_real_distribution<float> oneToOneDistribution(-1.f, 1.f); DirectX::XMFLOAT4 randColorOffset( tempColor.x + oneToOneDistribution(m_RandomEngine) * m_ParticleEffectDef->particleColorDeviation.x, tempColor.y + oneToOneDistribution(m_RandomEngine) * m_ParticleEffectDef->particleColorDeviation.y, tempColor.z + oneToOneDistribution(m_RandomEngine) * m_ParticleEffectDef->particleColorDeviation.z, tempColor.w + oneToOneDistribution(m_RandomEngine) * m_ParticleEffectDef->particleColorDeviation.w); //Put all the new data for the new particle into one container Particle tempParticle(randPos, randVel, randColorOffset, m_ParticleEffectDef->size, 0.f, randMaxLife); //Add the new particle to the others in the same system m_ParticleList.push_back(tempParticle); } }
/* ============ hhDebrisSpawner::SpawnDebris ============ */ void hhDebrisSpawner::SpawnDebris() { const idKeyValue * kv = NULL; idEntity * debris; idDict args; idStr debrisEntity; idList<idStr> debrisEntities; int numDebris; // For entity sources idBounds sourceBounds; idVec3 sourceBoundCenter; idVec3 debrisOrigin; idBounds searchBounds; idVec3 debrisVelocity; bool fit; idBounds afBounds; //rww bool gotAFBounds = false; //rww idVec3 defOrigin = vec3_zero; idAngles defAngles = ang_zero; // Optimization: if player is far away, don't spawn the chunks if (!gameLocal.isMultiplayer) { float maxDistance = spawnArgs.GetFloat("max_debris_distance"); if (maxDistance > 0.0f) { float distSquared = (gameLocal.GetLocalPlayer()->GetOrigin() - origin).LengthSqr(); if (distSquared > maxDistance*maxDistance) { return; } } } args.SetInt( "nodrop", 1 ); args.SetVector( "origin", origin ); args.SetFloat( "duration", duration ); // Pass along variabes requested hhUtils::PassArgs( spawnArgs, args, "pass_" ); if (useAFBounds && sourceEntity && sourceEntity->IsType(idActor::Type)) { //rww - try for AF bounds idActor *actor = static_cast<idActor *>(sourceEntity); if (actor->IsActiveAF()) { //they are ragdolling, so we have a chance. idPhysics_AF *afPhys = actor->GetAFPhysics(); if (afPhys) { //got the af physics object, now loop through the bodies and collect an appropriate bounds. afBounds.Zero(); for (int bodyCount = 0; bodyCount < afPhys->GetNumBodies(); bodyCount++) { idAFBody *b = afPhys->GetBody(bodyCount); if (b) { idClipModel *bodyClip = b->GetClipModel(); if (bodyClip) { //now add the bounds of the clipModel into afBounds idBounds bodyBounds = bodyClip->GetBounds(); idVec3 point = (b->GetWorldOrigin()-origin); bodyBounds.AddPoint(point); afBounds.AddBounds(bodyBounds); gotAFBounds = true; } } } } } } // Find all Debris while ( GetNextDebrisData( debrisEntities, numDebris, kv, defOrigin, defAngles ) ) { int numEntities = debrisEntities.Num(); for ( int count = 0; count < numDebris; ++count ) { // Select a debris to use from the list debrisEntity = debrisEntities[ gameLocal.random.RandomInt( numEntities ) ]; // If we have a bounding box to fill, use that if ( fillBounds && ( sourceEntity || hasBounds ) ) { if (gotAFBounds) { //rww sourceBounds = afBounds; //gameRenderWorld->DebugBounds(colorGreen, afBounds, origin, 1000); } else if ( sourceEntity ) { sourceBounds = sourceEntity->GetPhysics()->GetBounds(); } else { sourceBounds = bounds; } fit = false; for ( int i = 0; i < 4; i++ ) { if ( i == 0 && defOrigin != vec3_zero ) { //first try bone origin without random offset debrisOrigin = defOrigin; } else { debrisOrigin = origin + hhUtils::RandomPointInBounds( sourceBounds ); } if ( !testBounds || hhUtils::EntityDefWillFit( debrisEntity, debrisOrigin, defAngles.ToMat3(), CONTENTS_SOLID, NULL ) ) { fit = true; break; // Found a spot for the gib } } if ( !fit ) { // Gib didn't fit after 4 attempts, so don't spawn the gib //common->Warning( "SpawnDebris: gib didn't fit when spawned (%s)\n", debrisEntity.c_str() ); defAngles = ang_zero; continue; } args.SetVector( "origin", debrisOrigin ); if ( sourceEntity ) { idMat3 sourceAxis = idAngles( 0, sourceEntity->GetAxis().ToAngles().yaw, 0 ).ToMat3(); args.SetMatrix( "rotation", defAngles.ToMat3() * sourceAxis ); } else { args.SetMatrix( "rotation", defAngles.ToMat3() ); } } if ( duration ) { args.SetFloat( "removeTime", duration + duration * gameLocal.random.CRandomFloat() ); } // Spawn the object debris = gameLocal.SpawnObject( debrisEntity, &args ); HH_ASSERT(debris != NULL); // JRM - Nick, I added this because of a crash I got. Hopefully this will catch it sooner // mdl: Added this check to make sure no AFs go through the debris spawner if ( debris->IsType( idAFEntity_Base::Type ) ) { gameLocal.Warning( "hhDebrisSpawner spawned an articulated entity: '%s'.", debrisEntity.c_str() ); } if ( nonSolid ) { idVec3 origin; if ( debris->GetFloorPos( 64.0f, origin ) ) { debris->SetOrigin( origin ); // Start on floor, since we're not going to be moving at all debris->RunPhysics(); // Make sure any associated effects get updated before we turn collision off } // Turn off collision debris->GetPhysics()->SetContents( 0 ); debris->GetPhysics()->SetClipMask( 0 ); debris->GetPhysics()->UnlinkClip(); debris->GetPhysics()->PutToRest(); } else { // Add in random velocity idVec3 randVel( gameLocal.random.RandomInt( power.x ) - power.x / 2, gameLocal.random.RandomInt( power.y ) - power.y / 2, gameLocal.random.RandomInt( power.z ) - power.z / 2 ); // Set linear velocity debrisVelocity.x = velocity.x * power.x * 0.25; debrisVelocity.y = velocity.y * power.y * 0.25; debrisVelocity.z = 0.0f; debris->GetPhysics()->SetLinearVelocity( debrisVelocity + randVel ); // Add random angular velocity idVec3 aVel; aVel.x = spawnArgs.GetFloat( "ang_vel", "90.0" ) * gameLocal.random.CRandomFloat(); aVel.y = spawnArgs.GetFloat( "ang_vel", "90.0" ) * gameLocal.random.CRandomFloat(); aVel.z = spawnArgs.GetFloat( "ang_vel", "90.0" ) * gameLocal.random.CRandomFloat(); if ( defAngles == ang_zero ) { debris->GetPhysics()->SetAxis( idVec3( 1, 0, 0 ).ToMat3() ); } debris->GetPhysics()->SetAngularVelocity( aVel ); } } defAngles = ang_zero; // Zero out the list debrisEntities.Clear(); } return; }