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);
	}
}
예제 #2
0
/*
============
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;
}