📄 particlecloud.cpp
字号:
gosFX::ParticleCloud::ParticleCloud(
ClassData *class_data,
Specification *spec,
unsigned flags
):
Effect(class_data, spec, flags)
{
Check_Pointer(this);
Check_Object(spec);
Verify(gos_GetCurrentHeap() == Heap);
//
//------------------------------------------------
// Set up the data pointers into the channel block
//------------------------------------------------
//
m_data.SetLength(spec->m_maxParticleCount*spec->m_totalParticleSize);
//
//-------------------------------
// Set up an empty particle cloud
//-------------------------------
//
m_activeParticleCount = 0;
m_birthAccumulator = 0.0f;
}
//------------------------------------------------------------------------------
//
void
gosFX::ParticleCloud::Start(ExecuteInfo *info)
{
Check_Object(this);
Check_Pointer(info);
//
//--------------------------------------------------------------------------
// Let effect initialize, then figure out how many particles we want to make
//--------------------------------------------------------------------------
//
Effect::Start(info);
Specification *spec = GetSpecification();
Check_Object(spec);
Stuff::Scalar newbies =
spec->m_startingPopulation.ComputeValue(m_age, m_seed);
Min_Clamp(newbies, 0.0f);
m_birthAccumulator += newbies;
}
//------------------------------------------------------------------------------
//
bool gosFX::ParticleCloud::Execute(ExecuteInfo *info)
{
Check_Object(this);
Check_Object(info);
Verify(IsExecuted());
//
//--------------------------------------------------------------------
// If we were given a new matrix, see if we have a parent. If so,
// concatenate the two and figure out its inverse. If no parent, then
// just invert the new matrix, otherwise just use the existing one
//--------------------------------------------------------------------
//
Stuff::LinearMatrix4D new_world_to_local;
Stuff::LinearMatrix4D *matrix = NULL;
int sim_mode = GetSimulationMode();
if (sim_mode == DynamicWorldSpaceSimulationMode)
{
Stuff::LinearMatrix4D local_to_world;
local_to_world.Multiply(m_localToParent, *info->m_parentToWorld);
new_world_to_local.Invert(local_to_world);
matrix = &new_world_to_local;
}
//
//--------------------------------------------------------
// Figure out the birth rate and request the new particles
//--------------------------------------------------------
//
Specification *spec = GetSpecification();
Check_Object(spec);
Stuff::Scalar dT =
static_cast<Stuff::Scalar>(info->m_time - m_lastRan);
Verify(dT >= 0.0f);
Stuff::Scalar prev_age = m_age;
m_age += dT * m_ageRate;
if (m_age >= 1.0f)
m_birthAccumulator = 0.0f;
else
{
Stuff::Scalar new_life =
spec->m_particlesPerSecond.ComputeValue(m_age, m_seed);
Min_Clamp(new_life, 0.0f);
m_birthAccumulator += dT * new_life;
}
//
//-----------------------------------
// Deal with all the active particles
//-----------------------------------
//
int i;
int last_real = -1;
for (i = 0; i < m_activeParticleCount; i++)
{
//
//--------------------------------------------------------------------
// If the particle is active, age it and if it is not yet time to die,
// go to the next particle, otherwise kill it
//--------------------------------------------------------------------
//
Particle *particle = GetParticle(i);
Check_Object(particle);
if (particle->m_age < 1.0f)
{
particle->m_age += dT*particle->m_ageRate;
if (AnimateParticle(i, matrix, info->m_time))
{
last_real = i;
continue;
}
DestroyParticle(i);
}
//
//--------------------------------------------------------------------
// If there are new particles to be born, go ahead and create them now
//--------------------------------------------------------------------
//
if (m_birthAccumulator >= 1.0f)
{
Stuff::Point3D translation;
CreateNewParticle(i, &translation);
if (AnimateParticle(i, matrix, info->m_time))
last_real = i;
else
DestroyParticle(i);
m_birthAccumulator -= 1.0f;
}
}
m_activeParticleCount = last_real + 1;
//
//----------------------------------------------------------------------
// If there are still new particles to be born, then we must try to grow
// the active particle count
//----------------------------------------------------------------------
//
while (
m_birthAccumulator >= 1.0f
&& m_activeParticleCount < spec->m_maxParticleCount
)
{
i = m_activeParticleCount++;
Stuff::Point3D translation;
CreateNewParticle(i, &translation);
if (!AnimateParticle(i, matrix, info->m_time))
{
DestroyParticle(i);
--m_activeParticleCount;
}
m_birthAccumulator -= 1.0f;
}
//
//---------------------------------------------------------
// Only allow fractional births to carry over to next frame
//---------------------------------------------------------
//
m_birthAccumulator -= static_cast<Stuff::Scalar>(floor(m_birthAccumulator));
//
//----------------------------
// Now let effect do its thing
//----------------------------
//
m_age = prev_age;
return Effect::Execute(info);
}
//------------------------------------------------------------------------------
//
bool gosFX::ParticleCloud::HasFinished()
{
Check_Object(this);
return Effect::HasFinished() && (m_activeParticleCount == 0);
}
//------------------------------------------------------------------------------
//
void gosFX::ParticleCloud::Kill()
{
Check_Object(this);
//
//-------------------------------------------------------------
// Destroy all the particles and set up an empty particle cloud
//-------------------------------------------------------------
//
for(int i=0; i < m_activeParticleCount; i++)
DestroyParticle(i);
m_activeParticleCount = 0;
m_birthAccumulator = 0.0f;
//
//----------------------------------------
// Now let the base effect handle stopping
//----------------------------------------
//
Effect::Kill();
}
//------------------------------------------------------------------------------
//
void
gosFX::ParticleCloud::CreateNewParticle(
unsigned index,
Stuff::Point3D *translation
)
{
Check_Object(this);
//
//----------------------------------------------------
// Figure out the age and age rate of the new particle
//----------------------------------------------------
//
Specification *spec = GetSpecification();
Check_Object(spec);
Particle *particle = GetParticle(index);
Check_Object(particle);
particle->m_age = 0.0f;
Stuff::Scalar min_seed =
spec->m_minimumChildSeed.ComputeValue(m_age, m_seed);
Stuff::Scalar seed_range =
spec->m_maximumChildSeed.ComputeValue(m_age, m_seed) - min_seed;
Stuff::Scalar seed =
Stuff::Random::GetFraction()*seed_range + min_seed;
Clamp(seed, 0.0f, 1.0f);
particle->m_seed = seed;
Stuff::Scalar lifetime =
spec->m_pLifeSpan.ComputeValue(m_age, seed);
Min_Clamp(lifetime, 0.0333333f);
particle->m_ageRate = 1.0f / lifetime;
//
//--------------------------------
// Figure out the initial position
//--------------------------------
//
Stuff::YawPitchRange
initial_p(
Stuff::Random::GetFraction() * Stuff::Two_Pi,
Stuff::Random::GetFraction() * Stuff::Pi - Stuff::Pi_Over_2,
Stuff::Random::GetFraction()
);
Stuff::Vector3D position(initial_p);
translation->x =
position.x * spec->m_emitterSizeX.ComputeValue(m_age, seed);
translation->y =
position.y * spec->m_emitterSizeY.ComputeValue(m_age, seed);
translation->z =
position.z * spec->m_emitterSizeZ.ComputeValue(m_age, seed);
//
//--------------------------------
// Figure out the initial velocity
//--------------------------------
//
Stuff::Scalar pitch_min =
spec->m_minimumDeviation.ComputeValue(m_age, seed);
Stuff::Scalar pitch_range =
spec->m_maximumDeviation.ComputeValue(m_age, seed) - pitch_min;
if (pitch_range < 0.0f)
pitch_range = 0.0f;
pitch_min +=
pitch_range * Stuff::Random::GetFraction() - Stuff::Pi_Over_2;
Stuff::YawPitchRange
initial_v(
Stuff::Random::GetFraction() * Stuff::Two_Pi,
pitch_min,
spec->m_startingSpeed.ComputeValue(m_age, seed)
);
particle->m_localLinearVelocity = initial_v;
}
//------------------------------------------------------------------------------
//
void gosFX::ParticleCloud::DestroyParticle(unsigned index)
{
Particle *particle = GetParticle(index);
Check_Object(particle);
particle->m_age = 1.0f;
}
//------------------------------------------------------------------------------
//
void
gosFX::ParticleCloud::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -