Skip to content
This repository has been archived by the owner on Jan 5, 2024. It is now read-only.

Commit

Permalink
Big improvements to emission performance with better cache coherency
Browse files Browse the repository at this point in the history
  • Loading branch information
Causeless committed Nov 27, 2023
1 parent be32a8f commit 78723ee
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 76 deletions.
87 changes: 42 additions & 45 deletions Entities/AEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ ConcreteClassInfo(AEmitter, Attachable, 100);

void AEmitter::Clear()
{
for (std::list<Emission *>::const_iterator itr = m_EmissionList.begin(); itr != m_EmissionList.end(); ++itr)
delete (*itr);
m_EmissionList.clear();
m_EmissionSound = nullptr;
m_BurstSound = nullptr;
Expand Down Expand Up @@ -77,10 +75,9 @@ int AEmitter::Create(const AEmitter &reference) {

if (reference.m_pFlash) { SetFlash(dynamic_cast<Attachable *>(reference.m_pFlash->Clone())); }

for (const Emission *referenceEmission : reference.m_EmissionList) {
m_EmissionList.push_back(dynamic_cast<Emission *>(referenceEmission->Clone()));
}

for (auto itr = reference.m_EmissionList.begin(); itr != reference.m_EmissionList.end(); ++itr) {
m_EmissionList.push_back(*itr);
}
if (reference.m_EmissionSound) { m_EmissionSound = dynamic_cast<SoundContainer*>(reference.m_EmissionSound->Clone()); }
if (reference.m_BurstSound) { m_BurstSound = dynamic_cast<SoundContainer*>(reference.m_BurstSound->Clone()); }
if (reference.m_EndSound) { m_EndSound = dynamic_cast<SoundContainer*>(reference.m_EndSound->Clone()); }
Expand Down Expand Up @@ -121,8 +118,8 @@ int AEmitter::ReadProperty(const std::string_view &propName, Reader &reader) {
StartPropertyList(return Attachable::ReadProperty(propName, reader));

MatchProperty("AddEmission", {
Emission * emission = new Emission();
reader >> *emission;
Emission emission;
reader >> emission;
m_EmissionList.push_back(emission);
});
MatchProperty("EmissionSound", {
Expand All @@ -144,7 +141,7 @@ int AEmitter::ReadProperty(const std::string_view &propName, Reader &reader) {
float ppm;
reader >> ppm;
// Go through all emissions and set the rate so that it emulates the way it used to work, for mod backwards compatibility.
for (Emission *emission : m_EmissionList) { emission->m_PPM = ppm / static_cast<float>(m_EmissionList.size()); }
for (Emission &emission : m_EmissionList) { emission.m_PPM = ppm / static_cast<float>(m_EmissionList.size()); }
});
MatchProperty("NegativeThrottleMultiplier", { reader >> m_NegativeThrottleMultiplier; });
MatchProperty("PositiveThrottleMultiplier", { reader >> m_PositiveThrottleMultiplier; });
Expand All @@ -154,7 +151,7 @@ int AEmitter::ReadProperty(const std::string_view &propName, Reader &reader) {
int burstSize;
reader >> burstSize;
// Go through all emissions and set the rate so that it emulates the way it used to work, for mod backwards compatibility.
for (Emission *emission : m_EmissionList) { emission->m_BurstSize = std::ceil(static_cast<float>(burstSize) / static_cast<float>(m_EmissionList.size())); }
for (Emission &emission : m_EmissionList) { emission.m_BurstSize = std::ceil(static_cast<float>(burstSize) / static_cast<float>(m_EmissionList.size())); }
});
MatchProperty("BurstScale", { reader >> m_BurstScale; });
MatchProperty("BurstDamage", { reader >> m_BurstDamage; });
Expand Down Expand Up @@ -185,7 +182,7 @@ int AEmitter::Save(Writer &writer) const
{
Attachable::Save(writer);

for (std::list<Emission *>::const_iterator itr = m_EmissionList.begin(); itr != m_EmissionList.end(); ++itr)
for (auto itr = m_EmissionList.begin(); itr != m_EmissionList.end(); ++itr)
{
writer.NewProperty("AddEmission");
writer << *itr;
Expand Down Expand Up @@ -276,8 +273,8 @@ void AEmitter::Destroy(bool notInherited)
void AEmitter::ResetEmissionTimers()
{
m_LastEmitTmr.Reset();
for (std::list<Emission *>::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
(*eItr)->ResetEmissionTimers();
for (auto eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
(*eItr).ResetEmissionTimers();
}


Expand Down Expand Up @@ -314,23 +311,23 @@ float AEmitter::EstimateImpulse(bool burst)
float velMin, velMax, velRange, spread;

// Go through all emissions and emit them according to their respective rates
for (std::list<Emission *>::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
for (auto eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
{
// Only check emissions that push the emitter
if ((*eItr)->PushesEmitter())
if ((*eItr).PushesEmitter())
{
double emissions = (*eItr)->GetRate() * g_TimerMan.GetDeltaTimeSecs() / 60.0f;
double emissions = (*eItr).GetRate() * g_TimerMan.GetDeltaTimeSecs() / 60.0f;
if (burst) {
emissions *= (*eItr)->GetBurstSize();
emissions *= (*eItr).GetBurstSize();
}

velMin = std::min((*eItr)->GetMinVelocity(), (*eItr)->GetMaxVelocity());
velMax = std::max((*eItr)->GetMinVelocity(), (*eItr)->GetMaxVelocity());
velMin = std::min((*eItr).GetMinVelocity(), (*eItr).GetMaxVelocity());
velMax = std::max((*eItr).GetMinVelocity(), (*eItr).GetMaxVelocity());
velRange = (velMax - velMin) * 0.5;
spread = std::max(static_cast<float>(c_PI) - (*eItr)->GetSpread(), .0f) / c_PI; // A large spread will cause the forces to cancel eachother out
spread = std::max(static_cast<float>(c_PI) - (*eItr).GetSpread(), .0f) / c_PI; // A large spread will cause the forces to cancel eachother out

// Add to accumulative recoil impulse generated, F = m * a.
impulse += (velMin + velRange) * spread * (*eItr)->m_pEmission->GetMass() * emissions;
impulse += (velMin + velRange) * spread * (*eItr).m_pEmission->GetMass() * emissions;
}
}

Expand All @@ -353,8 +350,8 @@ float AEmitter::EstimateImpulse(bool burst)

float AEmitter::GetTotalParticlesPerMinute() const {
float totalPPM = 0;
for (const Emission *emission : m_EmissionList) {
totalPPM += emission->m_PPM;
for (const Emission &emission : m_EmissionList) {
totalPPM += emission.m_PPM;
}
return totalPPM;
}
Expand All @@ -363,8 +360,8 @@ float AEmitter::GetTotalParticlesPerMinute() const {

int AEmitter::GetTotalBurstSize() const {
int totalBurstSize = 0;
for (const Emission *emission : m_EmissionList) {
totalBurstSize += emission->m_BurstSize;
for (const Emission &emission : m_EmissionList) {
totalBurstSize += emission.m_BurstSize;
}
return totalBurstSize;
}
Expand Down Expand Up @@ -442,8 +439,8 @@ void AEmitter::Update()
if (m_EmissionSound) { m_EmissionSound->Play(m_Pos); }

// Reset the timers of all emissions so they will start/stop at the correct relative offsets from now
for (std::list<Emission *>::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
(*eItr)->ResetEmissionTimers();
for (Emission &emission : m_EmissionList)
emission.ResetEmissionTimers();
}
// Update the distance attenuation
else
Expand Down Expand Up @@ -472,13 +469,13 @@ void AEmitter::Update()
MovableObject *pParticle = 0;
Vector parentVel, emitVel, pushImpulses;
// Go through all emissions and emit them according to their respective rates
for (std::list<Emission *>::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
for (Emission &emission : m_EmissionList)
{
// Make sure the emissions only happen between the start time and end time
if ((*eItr)->IsEmissionTime())
if (emission.IsEmissionTime())
{
// Apply the throttle factor to the emission rate
currentPPM = (*eItr)->GetRate() * throttleFactor;
currentPPM = emission.GetRate() * throttleFactor;
int emissionCount = 0;

// Only do all this if the PPM is actually above zero
Expand All @@ -488,47 +485,47 @@ void AEmitter::Update()
SPE = 60.0 / currentPPM;

// Add the last elapsed time to the accumulator
(*eItr)->m_Accumulator += m_LastEmitTmr.GetElapsedSimTimeS();
emission.m_Accumulator += m_LastEmitTmr.GetElapsedSimTimeS();

// Now figure how many full emissions can fit in the current accumulator
emissionCount = std::floor((*eItr)->m_Accumulator / SPE);
emissionCount = std::floor(emission.m_Accumulator / SPE);
// Deduct the about to be emitted emissions from the accumulator
(*eItr)->m_Accumulator -= emissionCount * SPE;
emission.m_Accumulator -= emissionCount * SPE;

RTEAssert((*eItr)->m_Accumulator >= 0, "Emission accumulator negative!");
RTEAssert(emission.m_Accumulator >= 0, "Emission accumulator negative!");
}
else {
(*eItr)->m_Accumulator = 0;
emission.m_Accumulator = 0;
}
float scale = 1.0F;
// Add extra emissions if bursting.
if (m_BurstTriggered) {
emissionCount += (*eItr)->GetBurstSize() * std::floor(throttleFactor);
emissionCount += emission.GetBurstSize() * std::floor(throttleFactor);
scale = m_BurstScale;
}
emissionCountTotal += emissionCount;
pParticle = 0;
emitVel.Reset();
parentVel = pRootParent->GetVel() * (*eItr)->InheritsVelocity();
parentVel = pRootParent->GetVel() * emission.InheritsVelocity();

for (int i = 0; i < emissionCount; ++i)
{
velMin = (*eItr)->GetMinVelocity() * scale;
velRange = (*eItr)->GetMaxVelocity() - (*eItr)->GetMinVelocity() * scale;
spread = (*eItr)->GetSpread() * scale;
velMin = emission.GetMinVelocity() * scale;
velRange = emission.GetMaxVelocity() - emission.GetMinVelocity() * scale;
spread = emission.GetSpread() * scale;
// Make a copy after the reference particle
pParticle = dynamic_cast<MovableObject *>((*eItr)->GetEmissionParticlePreset()->Clone());
pParticle = dynamic_cast<MovableObject *>(emission.GetEmissionParticlePreset()->Clone());
// Set up its position and velocity according to the parameters of this.
// Emission point offset not set

if ((*eItr)->GetOffset().IsZero()) {
if (emission.GetOffset().IsZero()) {
if (m_EmissionOffset.IsZero()) {
pParticle->SetPos(m_Pos);
} else {
pParticle->SetPos(m_Pos + RotateOffset(m_EmissionOffset));
}
} else {
pParticle->SetPos(m_Pos + RotateOffset((*eItr)->GetOffset()));
pParticle->SetPos(m_Pos + RotateOffset(emission.GetOffset()));
}
// TODO: Optimize making the random angles!")
emitVel.SetXY(velMin + RandomNum(0.0F, velRange), 0.0F);
Expand All @@ -540,15 +537,15 @@ void AEmitter::Update()

//Scale the particle's lifetime based on life variation and throttle, as long as it's not 0
if (pParticle->GetLifetime() != 0) {
pParticle->SetLifetime(std::max(static_cast<int>(static_cast<float>(pParticle->GetLifetime()) * (1.0F + ((*eItr)->GetLifeVariation() * RandomNormalNum()))), 1));
pParticle->SetLifetime(std::max(static_cast<int>(static_cast<float>(pParticle->GetLifetime()) * (1.0F + (emission.GetLifeVariation() * RandomNormalNum()))), 1));
pParticle->SetLifetime(std::max(static_cast<int>(pParticle->GetLifetime() * throttleFactor), 1));
}
pParticle->SetTeam(m_Team);
pParticle->SetIgnoresTeamHits(true);

// Add to accumulative recoil impulse generated, F = m * a
// If enabled, that is
if ((*eItr)->PushesEmitter() && (GetParent() || GetMass() > 0)) { pushImpulses -= emitVel * pParticle->GetMass(); }
if (emission.PushesEmitter() && (GetParent() || GetMass() > 0)) { pushImpulses -= emitVel * pParticle->GetMass(); }

// Set the emitted particle to not hit this emitter's parent, if applicable
if (m_EmissionsIgnoreThis)
Expand Down
2 changes: 1 addition & 1 deletion Entities/AEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ ClassInfoGetters;
static Entity::ClassInfo m_sClass;

// The list of MO instances that get emitted
std::list<Emission *> m_EmissionList;
std::vector<Emission> m_EmissionList;
// Sounds
SoundContainer *m_EmissionSound;
SoundContainer *m_BurstSound;
Expand Down
54 changes: 25 additions & 29 deletions Entities/PEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ namespace RTE {
{
MOSParticle::Create(reference);

for (std::list<Emission>::const_iterator itr = reference.m_EmissionList.begin(); itr != reference.m_EmissionList.end(); ++itr)
for (auto itr = reference.m_EmissionList.begin(); itr != reference.m_EmissionList.end(); ++itr) {
m_EmissionList.push_back(*itr);

}
m_EmissionSound = reference.m_EmissionSound;
m_BurstSound = reference.m_BurstSound;
m_EndSound = reference.m_EndSound;
Expand Down Expand Up @@ -140,7 +140,7 @@ namespace RTE {
float ppm;
reader >> ppm;
// Go through all emissions and set the rate so that it emulates the way it used to work, for mod backwards compatibility
for (std::list<Emission>::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
for (auto eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
(*eItr).m_PPM = ppm / m_EmissionList.size();
});
MatchProperty("NegativeThrottleMultiplier", { reader >> m_NegativeThrottleMultiplier; });
Expand All @@ -152,7 +152,7 @@ namespace RTE {
int burstSize;
reader >> burstSize;
// Go through all emissions and set the rate so that it emulates the way it used to work, for mod backwards compatibility
for (std::list<Emission>::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
for (auto eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
(*eItr).m_BurstSize = std::ceil((float)burstSize / (float)m_EmissionList.size());
});
MatchProperty("BurstScale", { reader >> m_BurstScale; });
Expand Down Expand Up @@ -180,7 +180,7 @@ namespace RTE {
{
MOSParticle::Save(writer);

for (std::list<Emission>::const_iterator itr = m_EmissionList.begin(); itr != m_EmissionList.end(); ++itr)
for (auto itr = m_EmissionList.begin(); itr != m_EmissionList.end(); ++itr)
{
writer.NewProperty("AddEmission");
writer << *itr;
Expand Down Expand Up @@ -237,11 +237,6 @@ namespace RTE {

void PEmitter::Destroy(bool notInherited)
{
/* Don't own these anymore
for (list<MovableObject *>::iterator itr = m_EmissionList.begin();
itr != m_EmissionList.end(); ++itr)
delete (*itr);
*/
// Stop playback of sounds gracefully
if (m_EmissionSound.IsBeingPlayed())
m_EndSound.Play(m_Pos);
Expand All @@ -265,7 +260,7 @@ namespace RTE {
void PEmitter::ResetEmissionTimers()
{
m_LastEmitTmr.Reset();
for (std::list<Emission>::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
for (auto eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
(*eItr).ResetEmissionTimers();
}

Expand Down Expand Up @@ -303,7 +298,7 @@ namespace RTE {
float velMin, velMax, velRange, spread;

// Go through all emissions and emit them according to their respective rates
for (std::list<Emission>::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
for (auto eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
{
// Only check emissions that push the emitter
if (eItr->PushesEmitter())
Expand Down Expand Up @@ -375,8 +370,9 @@ namespace RTE {
m_EmissionSound.Play(m_Pos);

// Reset the timers of all emissions so they will start/stop at the correct relative offsets from now
for (std::list<Emission>::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
(*eItr).ResetEmissionTimers();
for (Emission& emission : m_EmissionList) {
emission.ResetEmissionTimers();
}
}
// Update the distance attenuation
else
Expand Down Expand Up @@ -407,13 +403,13 @@ namespace RTE {
MovableObject *pParticle = 0;
Vector parentVel, emitVel, pushImpulses;
// Go through all emissions and emit them according to their respective rates
for (std::list<Emission>::iterator eItr = m_EmissionList.begin(); eItr != m_EmissionList.end(); ++eItr)
for (Emission &emission : m_EmissionList)
{
// Make sure the emissions only happen between the start time and end time
if (eItr->IsEmissionTime())
if (emission.IsEmissionTime())
{
// Apply the throttle factor to the emission rate
currentPPM = (*eItr).GetRate() * throttleFactor;
currentPPM = emission.GetRate() * throttleFactor;
emissions = 0;

// Only do all this if the PPM is acutally above zero
Expand All @@ -423,31 +419,31 @@ namespace RTE {
SPE = 60.0 / currentPPM;

// Add the last elapsed time to the accumulator
(*eItr).m_Accumulator += m_LastEmitTmr.GetElapsedSimTimeS();
emission.m_Accumulator += m_LastEmitTmr.GetElapsedSimTimeS();

// Now figure how many full emissions can fit in the current accumulator
emissions = std::floor((*eItr).m_Accumulator / SPE);
emissions = std::floor(emission.m_Accumulator / SPE);
// Deduct the about to be emitted emissions from the accumulator
(*eItr).m_Accumulator -= emissions * SPE;
emission.m_Accumulator -= emissions * SPE;

RTEAssert((*eItr).m_Accumulator >= 0, "Emission accumulator negative!");
RTEAssert(emission.m_Accumulator >= 0, "Emission accumulator negative!");
}

// Add extra emissions if bursting.
if (m_BurstTriggered)
emissions += (*eItr).GetBurstSize() * std::floor(throttleFactor);
emissions += emission.GetBurstSize() * std::floor(throttleFactor);

pParticle = 0;
emitVel.Reset();
parentVel = pRootParent->GetVel() * (*eItr).InheritsVelocity();
parentVel = pRootParent->GetVel() * emission.InheritsVelocity();

for (int i = 0; i < emissions; ++i)
{
velMin = (*eItr).GetMinVelocity() * (m_BurstTriggered ? m_BurstScale : 1.0);
velRange = (*eItr).GetMaxVelocity() - (*eItr).GetMinVelocity() * (m_BurstTriggered ? m_BurstScale : 1.0);
spread = (*eItr).GetSpread() * (m_BurstTriggered ? m_BurstScale : 1.0);
velMin = emission.GetMinVelocity() * (m_BurstTriggered ? m_BurstScale : 1.0);
velRange = emission.GetMaxVelocity() - emission.GetMinVelocity() * (m_BurstTriggered ? m_BurstScale : 1.0);
spread = emission.GetSpread() * (m_BurstTriggered ? m_BurstScale : 1.0);
// Make a copy after the reference particle
pParticle = dynamic_cast<MovableObject *>((*eItr).GetEmissionParticlePreset()->Clone());
pParticle = dynamic_cast<MovableObject *>(emission.GetEmissionParticlePreset()->Clone());
// Set up its position and velocity according to the parameters of this.
// Emission point offset not set
if (m_EmissionOffset.IsZero())
Expand All @@ -460,13 +456,13 @@ namespace RTE {
emitVel = RotateOffset(emitVel);
pParticle->SetVel(parentVel + emitVel);

if (pParticle->GetLifetime() != 0) { pParticle->SetLifetime(std::max(static_cast<int>(pParticle->GetLifetime() * (1.0F + ((*eItr).GetLifeVariation() * RandomNormalNum()))), 1)); }
if (pParticle->GetLifetime() != 0) { pParticle->SetLifetime(std::max(static_cast<int>(pParticle->GetLifetime() * (1.0F + (emission.GetLifeVariation() * RandomNormalNum()))), 1)); }
pParticle->SetTeam(m_Team);
pParticle->SetIgnoresTeamHits(true);

// Add to accumulative recoil impulse generated, F = m * a
// If enabled, that is
if ((*eItr).PushesEmitter())
if (emission.PushesEmitter())
pushImpulses -= emitVel * pParticle->GetMass();

// Set the emitted particle to not hit this emitter's parent, if applicable
Expand Down
Loading

0 comments on commit 78723ee

Please sign in to comment.