metaforce/Runtime/Particle/CParticleElectric.cpp

887 lines
27 KiB
C++
Raw Normal View History

#include "CParticleElectric.hpp"
2016-03-06 02:55:09 +00:00
#include "CElectricDescription.hpp"
2016-02-26 05:38:11 +00:00
#include "CGenDescription.hpp"
#include "CSwooshDescription.hpp"
2016-03-06 02:55:09 +00:00
#include "CParticleSwoosh.hpp"
#include "CElementGen.hpp"
2016-03-04 23:04:53 +00:00
#include "Graphics/CModel.hpp"
#include "Graphics/CGraphics.hpp"
2017-06-11 02:57:35 +00:00
#include "CParticleGlobals.hpp"
#include "zeus/CRelAngle.hpp"
#include "zeus/CQuaternion.hpp"
2016-03-04 23:04:53 +00:00
namespace urde
{
2017-06-11 02:57:35 +00:00
u16 CParticleElectric::g_GlobalSeed = 99;
2016-03-06 02:55:09 +00:00
CParticleElectric::CParticleElectric(const TToken<CElectricDescription>& token)
2017-06-11 02:57:35 +00:00
: x1c_elecDesc(token), x14c_randState(g_GlobalSeed++)
2016-02-13 05:49:59 +00:00
{
2017-06-11 02:57:35 +00:00
x450_24_emitting = true;
x450_29_transformDirty = true;
2016-03-06 02:55:09 +00:00
CElectricDescription* desc = x1c_elecDesc.GetObj();
2017-06-11 02:57:35 +00:00
if (CIntElement* sseg = desc->x10_SSEG.get())
sseg->GetValue(x28_currentFrame, x150_SSEG);
if (CIntElement* scnt = desc->xc_SCNT.get())
scnt->GetValue(x28_currentFrame, x154_SCNT);
x154_SCNT = std::min(x154_SCNT, 32);
2016-03-06 02:55:09 +00:00
2017-06-11 02:57:35 +00:00
if (CIntElement* life = desc->x0_LIFE.get())
life->GetValue(0, x2c_LIFE);
2016-03-06 02:55:09 +00:00
else
2017-06-11 02:57:35 +00:00
x2c_LIFE = INT_MAX;
2016-03-07 08:07:55 +00:00
if (desc->x40_SSWH)
2016-03-06 02:55:09 +00:00
{
2017-06-11 02:57:35 +00:00
x450_27_haveSSWH = true;
x1e0_swooshGenerators.reserve(x154_SCNT);
for (int i=0 ; i<x154_SCNT ; ++i)
{
x1e0_swooshGenerators.emplace_back(new CParticleSwoosh(desc->x40_SSWH.m_token, x150_SSEG));
x1e0_swooshGenerators.back()->DoElectricWarmup();
}
2016-03-06 02:55:09 +00:00
}
2017-06-11 02:57:35 +00:00
++x150_SSEG;
x420_calculatedVerts.resize(x150_SSEG);
x440_fractalOffsets.resize(x150_SSEG);
x430_fractalMags.resize(x150_SSEG);
if (desc->x50_GPSM)
2016-03-06 02:55:09 +00:00
{
2017-06-11 02:57:35 +00:00
x450_25_haveGPSM = true;
x400_gpsmGenerators.reserve(x154_SCNT);
for (int i=0 ; i<x154_SCNT ; ++i)
{
x400_gpsmGenerators.emplace_back(new CElementGen(desc->x50_GPSM.m_token,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One));
x400_gpsmGenerators.back()->SetParticleEmission(false);
}
2016-03-06 02:55:09 +00:00
}
if (desc->x60_EPSM)
2016-03-06 02:55:09 +00:00
{
2017-06-11 02:57:35 +00:00
x450_26_haveEPSM = true;
x410_epsmGenerators.reserve(x154_SCNT);
for (int i=0 ; i<x154_SCNT ; ++i)
{
x410_epsmGenerators.emplace_back(new CElementGen(desc->x60_EPSM.m_token,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One));
x410_epsmGenerators.back()->SetParticleEmission(false);
}
2016-03-06 02:55:09 +00:00
}
2017-06-11 02:57:35 +00:00
if (x1c_elecDesc->x28_LWD1 || x1c_elecDesc->x2c_LWD2 || x1c_elecDesc->x30_LWD3)
{
x450_28_haveLWD = true;
for (int i=0 ; i<x154_SCNT ; ++i)
x2e4_lineManagers.emplace_back(new CLineManager());
}
}
void CParticleElectric::RenderSwooshes()
{
for (CParticleElectricManager& elec : x3e8_electricManagers)
x1e0_swooshGenerators[elec.x0_idx]->Render();
2016-02-13 05:49:59 +00:00
}
void CParticleElectric::SetupLineGXMaterial()
{
2017-06-11 02:57:35 +00:00
// Konst color/alpha 0
}
2017-06-11 02:57:35 +00:00
void CParticleElectric::DrawLineStrip(const std::vector<zeus::CVector3f>& verts, float width,
const zeus::CColor& color)
{
size_t useIdx = m_nextLineRenderer;
if (++m_nextLineRenderer > m_lineRenderers.size())
m_lineRenderers.resize(m_nextLineRenderer);
if (!m_lineRenderers[useIdx])
m_lineRenderers[useIdx] = std::make_unique<CLineRenderer>(CLineRenderer::EPrimitiveMode::LineStrip,
x150_SSEG, nullptr, true);
CLineRenderer& renderer = *m_lineRenderers[useIdx];
zeus::CColor useColor = x1b8_moduColor * color;
renderer.Reset();
for (const zeus::CVector3f& vert : verts)
renderer.AddVertex(vert, useColor, width);
renderer.Render();
}
2016-02-26 03:31:00 +00:00
void CParticleElectric::RenderLines()
{
2017-06-11 02:57:35 +00:00
m_nextLineRenderer = 0;
2016-02-26 03:31:00 +00:00
CGraphics::DisableAllLights();
2017-06-11 02:57:35 +00:00
// Z-test, no write
// Additive blend
CGraphics::SetModelMatrix(zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation *
zeus::CTransform::Translate(x38_translation) * x44_orientation *
zeus::CTransform::Scale(xe0_globalScale) * zeus::CTransform::Scale(xec_localScale));
// Disable culling
SetupLineGXMaterial();
for (CParticleElectricManager& elec : x3e8_electricManagers)
{
CLineManager& line = *x2e4_lineManagers[elec.x0_idx];
if (x1c_elecDesc->x28_LWD1)
DrawLineStrip(line.x0_verts, line.x10_widths[0], line.x1c_colors[0]);
if (x1c_elecDesc->x2c_LWD2)
DrawLineStrip(line.x0_verts, line.x10_widths[1], line.x1c_colors[1]);
if (x1c_elecDesc->x30_LWD3)
DrawLineStrip(line.x0_verts, line.x10_widths[2], line.x1c_colors[2]);
}
// Enable culling
// Line Width 1
}
void CParticleElectric::UpdateCachedTransform()
2016-02-13 05:49:59 +00:00
{
2017-06-11 02:57:35 +00:00
xf8_cachedXf = zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation *
zeus::CTransform::Translate(x38_translation) * x44_orientation;
x450_29_transformDirty = false;
}
void CParticleElectric::UpdateLine(int idx, int frame)
{
CLineManager& line = *x2e4_lineManagers[idx];
if (CColorElement* lcl1 = x1c_elecDesc->x34_LCL1.get())
lcl1->GetValue(frame, line.x1c_colors[0]);
if (CColorElement* lcl2 = x1c_elecDesc->x38_LCL2.get())
lcl2->GetValue(frame, line.x1c_colors[1]);
if (CColorElement* lcl3 = x1c_elecDesc->x3c_LCL3.get())
lcl3->GetValue(frame, line.x1c_colors[2]);
if (CRealElement* lwd1 = x1c_elecDesc->x28_LWD1.get())
lwd1->GetValue(frame, line.x10_widths[0]);
if (CRealElement* lwd2 = x1c_elecDesc->x2c_LWD2.get())
lwd2->GetValue(frame, line.x10_widths[1]);
if (CRealElement* lwd3 = x1c_elecDesc->x30_LWD3.get())
lwd3->GetValue(frame, line.x10_widths[2]);
}
void CParticleElectric::UpdateElectricalEffects()
{
for (auto it = x3e8_electricManagers.begin() ; it != x3e8_electricManagers.end() ;)
{
CParticleElectricManager& elec = *it;
if (elec.x4_slif < 1)
{
x1bc_allocated[elec.x0_idx] = false;
if (elec.x10_gpsmIdx != -1)
x400_gpsmGenerators[elec.x10_gpsmIdx]->SetParticleEmission(false);
if (elec.x14_epsmIdx != -1)
x410_epsmGenerators[elec.x14_epsmIdx]->SetParticleEmission(false);
it = x3e8_electricManagers.erase(it);
continue;
}
CParticleGlobals::SetParticleLifetime(elec.xc_endFrame - elec.x8_startFrame);
int frame = x28_currentFrame - elec.x8_startFrame;
CParticleGlobals::UpdateParticleLifetimeTweenValues(frame);
if (x450_27_haveSSWH)
{
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
zeus::CColor color = zeus::CColor::skWhite;
if (CColorElement* colr = x1c_elecDesc->x14_COLR.get())
colr->GetValue(frame, color);
swoosh.SetModulationColor(color * x1b8_moduColor);
}
if (x450_28_haveLWD)
UpdateLine(elec.x0_idx, frame);
elec.x4_slif -= 1;
++it;
}
}
void CParticleElectric::CalculateFractal(int start, int end, float ampl, float ampd)
{
float tmp = (end - start) / float(x430_fractalMags.size()) * ampl;
int storeIdx = (start + end) / 2;
x430_fractalMags[storeIdx] = (x430_fractalMags[start] + x430_fractalMags[end]) * 0.5f +
tmp * x14c_randState.Float() - tmp * 0.5f + ampd * x14c_randState.Float() - ampd * 0.5f;
if ((start + end) & 1)
x430_fractalMags[end-1] = x430_fractalMags[end];
if (storeIdx - start > 1)
CalculateFractal(start, storeIdx, ampl, ampd);
if (end - storeIdx > 1)
CalculateFractal(storeIdx, end, ampl, ampd);
}
void CParticleElectric::CalculatePoints()
{
zeus::CVector3f pos, vel;
if (CEmitterElement* iemt = x1c_elecDesc->x18_IEMT.get())
iemt->GetValue(x28_currentFrame, pos, vel);
if (x178_overrideIPos)
pos = *x178_overrideIPos;
if (x188_overrideIVel)
vel = *x188_overrideIVel;
rstl::reserved_vector<zeus::CVector3f, 4> points;
if (!vel.isZero())
{
points.push_back(pos);
points.push_back(pos + vel);
points.push_back(pos + vel * 2.f);
}
else
{
points.push_back(pos);
}
zeus::CVector3f fpos = zeus::CVector3f::skForward;
zeus::CVector3f fvel;
if (CEmitterElement* femt = x1c_elecDesc->x1c_FEMT.get())
femt->GetValue(x28_currentFrame, fpos, fvel);
if (x198_overrideFPos)
fpos = *x198_overrideFPos;
if (x1a8_overrideFVel)
fvel = *x1a8_overrideFVel;
if (!fvel.isZero())
{
if (points.size() == 3)
{
points.push_back(fpos);
points[2] = fpos + fvel;
}
else
{
points.push_back(fpos + fvel * 2.f);
points.push_back(fpos + fvel);
points.push_back(fpos);
}
}
else
{
points.push_back(fpos);
}
if (points.size() == 4)
{
int segs = x150_SSEG - 1;
float segDiv = 1.f / float(segs);
float curDiv = segDiv;
for (int i=1 ; i<segs ; ++i)
{
float t = segDiv * x14c_randState.Range(-0.45f, 0.45f) + curDiv;
x420_calculatedVerts[i] = zeus::getBezierPoint(points[0], points[1], points[2], points[3], t);
curDiv += segDiv;
}
x420_calculatedVerts[segs] = points[3];
}
else
{
x420_calculatedVerts[0] = pos;
int segs = x150_SSEG - 1;
float segDiv = 1.f / float(segs);
zeus::CVector3f accum = x420_calculatedVerts[0];
zeus::CVector3f segDelta = (fpos - pos) * segDiv;
for (int i=1 ; i<segs ; ++i)
{
float r = x14c_randState.Range(-0.45f, 0.45f);
x420_calculatedVerts[i] = segDelta * r + accum;
accum += segDelta;
}
x420_calculatedVerts[segs] = fpos;
}
for (int i=0 ; i<x150_SSEG ; ++i)
x430_fractalMags[i] = 0.f;
float amplVal = 1.f;
if (CRealElement* ampl = x1c_elecDesc->x20_AMPL.get())
{
ampl->GetValue(x28_currentFrame, amplVal);
amplVal *= 2.f;
}
float ampdVal = 0.f;
if (CRealElement* ampd = x1c_elecDesc->x24_AMPD.get())
ampd->GetValue(x28_currentFrame, ampdVal);
CalculateFractal(0, x420_calculatedVerts.size() - 1, amplVal, ampdVal);
zeus::CVector3f v0 = x420_calculatedVerts[0] - x420_calculatedVerts[1];
zeus::CVector3f v1 = x420_calculatedVerts[x420_calculatedVerts.size() - 1] - x420_calculatedVerts[1];
zeus::CVector3f upVec = zeus::CVector3f::skUp;
if (v0.canBeNormalized() && v1.canBeNormalized())
{
v0.normalize();
v1.normalize();
float dot = v0.dot(v1);
if (dot < 0)
dot = -dot;
if (std::fabs(dot - 1.f) < 0.00001f)
upVec = zeus::lookAt(x420_calculatedVerts[0], x420_calculatedVerts[1]).basis[2];
else
upVec = v0.cross(v1).normalized();
}
else if (x420_calculatedVerts[0] != x420_calculatedVerts[1])
{
upVec = zeus::lookAt(x420_calculatedVerts[0], x420_calculatedVerts[1]).basis[2];
}
float commonRand = x14c_randState.Range(0.f, 360.f);
for (int i=1 ; i<x420_calculatedVerts.size() - 1 ; ++i)
{
zeus::CVector3f delta = x420_calculatedVerts[i] - x420_calculatedVerts[i-1];
if (!delta.isZero())
{
zeus::CRelAngle angle =
zeus::degToRad(x430_fractalMags[i] / amplVal * 16.f * x14c_randState.Range(-1.f, 1.f) + commonRand);
x440_fractalOffsets[i] = zeus::CQuaternion::fromAxisAngle(delta, angle).transform(x430_fractalMags[i] * upVec);
}
}
for (int i=1 ; i<x420_calculatedVerts.size() - 1 ; ++i)
x420_calculatedVerts[i] += x440_fractalOffsets[i];
if (x1c_elecDesc->x70_ZERY)
for (int i=0 ; i<x420_calculatedVerts.size() ; ++i)
x420_calculatedVerts[i] = 0.f;
}
void CParticleElectric::CreateNewParticles(int count)
{
int allocIdx = 0;
for (int i=0 ; i<count ; ++i)
{
if (x3e8_electricManagers.size() < x154_SCNT)
{
zeus::CTransform cachedRot = xf8_cachedXf.getRotation();
int toAdd = x1bc_allocated.size() - allocIdx;
for (int j=0 ; j<toAdd ; ++j, ++allocIdx)
{
if (x1bc_allocated[allocIdx])
continue;
x1bc_allocated[allocIdx] = true;
int lifetime = 1;
if (CIntElement* slif = x1c_elecDesc->x4_SLIF.get())
slif->GetValue(x28_currentFrame, lifetime);
x3e8_electricManagers.push_back(CParticleElectricManager(allocIdx, lifetime, x28_currentFrame));
CParticleElectricManager& elec = x3e8_electricManagers.back();
CParticleGlobals::SetParticleLifetime(elec.xc_endFrame - elec.x8_startFrame);
int frame = x28_currentFrame - elec.x8_startFrame;
CParticleGlobals::UpdateParticleLifetimeTweenValues(frame);
CalculatePoints();
if (x450_27_haveSSWH)
{
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[allocIdx];
swoosh.SetParticleEmission(true);
swoosh.SetGlobalTranslation(xf8_cachedXf.origin);
swoosh.SetGlobalOrientation(cachedRot);
swoosh.SetGlobalScale(xe0_globalScale);
swoosh.SetLocalScale(xec_localScale);
zeus::CColor color = zeus::CColor::skWhite;
if (CColorElement* colr = x1c_elecDesc->x14_COLR.get())
colr->GetValue(frame, color);
swoosh.SetModulationColor(color * x1b8_moduColor);
swoosh.DoElectricCreate(x420_calculatedVerts);
}
if (x450_28_haveLWD)
{
CLineManager& line = *x2e4_lineManagers[allocIdx];
line.x0_verts = x420_calculatedVerts;
UpdateLine(allocIdx, 0);
if (x450_27_haveSSWH)
{
x130_buildBounds = zeus::CAABox::skInvertedBox;
for (const zeus::CVector3f& vec : x420_calculatedVerts)
x130_buildBounds.accumulateBounds(vec);
line.x28_aabb = x130_buildBounds;
}
}
if (x450_25_haveGPSM)
{
for (int k=0 ; k<x154_SCNT ; ++k)
{
CElementGen& gen = *x400_gpsmGenerators[k];
if (!gen.GetParticleEmission())
{
zeus::CTransform scale =
zeus::CTransform::Scale(xe0_globalScale) * zeus::CTransform::Scale(xec_localScale);
gen.SetTranslation(scale * x420_calculatedVerts.front());
gen.SetParticleEmission(true);
elec.x10_gpsmIdx = k;
}
}
}
if (x450_26_haveEPSM)
{
for (int k=0 ; k<x154_SCNT ; ++k)
{
CElementGen& gen = *x410_epsmGenerators[k];
if (!gen.GetParticleEmission())
{
zeus::CTransform scale =
zeus::CTransform::Scale(xe0_globalScale) * zeus::CTransform::Scale(xec_localScale);
gen.SetTranslation(scale * x420_calculatedVerts.back());
gen.SetParticleEmission(true);
elec.x14_epsmIdx = k;
}
}
}
break;
}
}
}
}
void CParticleElectric::AddElectricalEffects()
{
float genRate = 0.f;
if (CRealElement* grat = x1c_elecDesc->x8_GRAT.get())
{
if (grat->GetValue(x28_currentFrame, genRate))
{
x3e8_electricManagers.clear();
for (int i=0 ; i<x1bc_allocated.size() ; ++i)
x1bc_allocated[i] = false;
return;
}
else
{
genRate = std::max(0.f, genRate);
}
}
x15c_genRem += genRate;
int partCount = std::floor(x15c_genRem);
x15c_genRem -= partCount;
CreateNewParticles(partCount);
}
void CParticleElectric::BuildBounds()
{
if (GetParticleCount() <= 0)
{
x160_systemBounds = zeus::CAABox::skInvertedBox;
return;
}
x160_systemBounds = zeus::CAABox::skInvertedBox;
if (x450_27_haveSSWH)
{
for (CParticleElectricManager& elec : x3e8_electricManagers)
{
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
if (auto bounds = swoosh.GetBounds())
x160_systemBounds.accumulateBounds(*bounds);
}
}
else if (x450_28_haveLWD)
{
zeus::CAABox tmp = zeus::CAABox::skInvertedBox;
for (CParticleElectricManager& elec : x3e8_electricManagers)
{
CLineManager& line = *x2e4_lineManagers[elec.x0_idx];
tmp.accumulateBounds(line.x28_aabb);
}
if (!tmp.invalid())
{
x160_systemBounds.accumulateBounds(tmp.getTransformedAABox(
zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation *
zeus::CTransform::Translate(x38_translation) * x44_orientation *
zeus::CTransform::Scale(xe0_globalScale)));
}
}
if (x450_25_haveGPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
if (auto bounds = x400_gpsmGenerators[i]->GetBounds())
x160_systemBounds.accumulateBounds(*bounds);
}
if (x450_26_haveEPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
if (auto bounds = x410_epsmGenerators[i]->GetBounds())
x160_systemBounds.accumulateBounds(*bounds);
}
}
bool CParticleElectric::Update(double dt)
{
CGlobalRandom gr(x14c_randState);
bool ret = false;
if (x450_25_haveGPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
if (!x400_gpsmGenerators[i]->IsSystemDeletable())
break;
}
if (x450_26_haveEPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
if (!x410_epsmGenerators[i]->IsSystemDeletable())
break;
}
bool emitting = x450_24_emitting && x28_currentFrame < x2c_LIFE;
double evalTime = x28_currentFrame / 60.0;
x30_curTime += dt;
if (x450_29_transformDirty)
{
UpdateCachedTransform();
zeus::CTransform globalOrient = xf8_cachedXf.getRotation();
if (x450_27_haveSSWH)
{
for (CParticleElectricManager& elec : x3e8_electricManagers)
{
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
swoosh.SetGlobalTranslation(xf8_cachedXf.origin);
swoosh.SetGlobalOrientation(globalOrient);
swoosh.SetGlobalScale(xe0_globalScale);
swoosh.SetLocalScale(xec_localScale);
}
}
if (x450_25_haveGPSM)
{
for (CParticleElectricManager& elec : x3e8_electricManagers)
{
CElementGen& gen = *x400_gpsmGenerators[elec.x0_idx];
gen.SetGlobalTranslation(xf8_cachedXf.origin);
gen.SetGlobalOrientation(globalOrient);
gen.SetGlobalScale(xe0_globalScale);
gen.SetLocalScale(xec_localScale);
}
}
if (x450_26_haveEPSM)
{
for (CParticleElectricManager& elec : x3e8_electricManagers)
{
CElementGen& gen = *x410_epsmGenerators[elec.x0_idx];
gen.SetGlobalTranslation(xf8_cachedXf.origin);
gen.SetGlobalOrientation(globalOrient);
gen.SetGlobalScale(xe0_globalScale);
gen.SetLocalScale(xec_localScale);
}
}
ret = true;
}
while (evalTime < x30_curTime)
{
CParticleGlobals::SetEmitterTime(x28_currentFrame);
UpdateElectricalEffects();
if (emitting)
AddElectricalEffects();
if (x450_25_haveGPSM)
{
if (x28_currentFrame >= x2c_LIFE)
for (int i=0 ; i<x154_SCNT ; ++i)
x400_gpsmGenerators[i]->EndLifetime();
for (int i=0 ; i<x154_SCNT ; ++i)
x400_gpsmGenerators[i]->Update(1.0 / 60.0);
}
if (x450_26_haveEPSM)
{
if (x28_currentFrame >= x2c_LIFE)
for (int i=0 ; i<x154_SCNT ; ++i)
x410_epsmGenerators[i]->EndLifetime();
for (int i=0 ; i<x154_SCNT ; ++i)
x410_epsmGenerators[i]->Update(1.0 / 60.0);
}
ret = true;
evalTime += (1.0 / 60.0);
x28_currentFrame += 1;
}
if (ret)
BuildBounds();
return ret;
2016-02-13 05:49:59 +00:00
}
void CParticleElectric::Render()
{
2017-06-11 02:57:35 +00:00
if (x3e8_electricManagers.size())
{
if (x450_29_transformDirty)
UpdateCachedTransform();
if (x450_27_haveSSWH)
RenderSwooshes();
if (x450_28_haveLWD)
RenderLines();
}
if (x450_25_haveGPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
x400_gpsmGenerators[i]->Render();
}
if (x450_26_haveEPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
x410_epsmGenerators[i]->Render();
}
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
void CParticleElectric::SetOrientation(const zeus::CTransform& orientation)
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
x44_orientation = orientation;
2017-06-11 02:57:35 +00:00
x74_invOrientation = x44_orientation.inverse();
x450_29_transformDirty = true;
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
void CParticleElectric::SetTranslation(const zeus::CVector3f& translation)
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
x38_translation = translation;
2017-06-11 02:57:35 +00:00
x450_29_transformDirty = true;
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
void CParticleElectric::SetGlobalOrientation(const zeus::CTransform& orientation)
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
xb0_globalOrientation = orientation;
2017-06-11 02:57:35 +00:00
x450_29_transformDirty = true;
if (x450_27_haveSSWH)
{
for (CParticleElectricManager& elec : x3e8_electricManagers)
{
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
swoosh.SetGlobalOrientation(xb0_globalOrientation);
}
}
if (x450_25_haveGPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
x400_gpsmGenerators[i]->SetGlobalOrientation(xb0_globalOrientation);
}
if (x450_26_haveEPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
x410_epsmGenerators[i]->SetGlobalOrientation(xb0_globalOrientation);
}
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
void CParticleElectric::SetGlobalTranslation(const zeus::CVector3f& translation)
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
xa4_globalTranslation = translation;
2017-06-11 02:57:35 +00:00
x450_29_transformDirty = true;
if (x450_27_haveSSWH)
{
for (CParticleElectricManager& elec : x3e8_electricManagers)
{
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
swoosh.SetGlobalTranslation(xa4_globalTranslation);
}
}
if (x450_25_haveGPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
x400_gpsmGenerators[i]->SetGlobalTranslation(xa4_globalTranslation);
}
if (x450_26_haveEPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
x410_epsmGenerators[i]->SetGlobalTranslation(xa4_globalTranslation);
}
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
void CParticleElectric::SetGlobalScale(const zeus::CVector3f& scale)
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
xe0_globalScale = scale;
2017-06-11 02:57:35 +00:00
x450_29_transformDirty = true;
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
void CParticleElectric::SetLocalScale(const zeus::CVector3f& scale)
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
xec_localScale = scale;
2017-06-11 02:57:35 +00:00
x450_29_transformDirty = true;
if (x450_27_haveSSWH)
{
for (CParticleElectricManager& elec : x3e8_electricManagers)
{
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
swoosh.SetLocalScale(xec_localScale);
}
}
if (x450_25_haveGPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
x400_gpsmGenerators[i]->SetLocalScale(xec_localScale);
}
if (x450_26_haveEPSM)
2016-02-26 03:31:00 +00:00
{
2017-06-11 02:57:35 +00:00
for (int i=0 ; i<x154_SCNT ; ++i)
x410_epsmGenerators[i]->SetLocalScale(xec_localScale);
2016-02-26 03:31:00 +00:00
}
2016-02-13 05:49:59 +00:00
}
2017-06-11 02:57:35 +00:00
void CParticleElectric::SetParticleEmission(bool e)
2016-02-13 05:49:59 +00:00
{
2017-06-11 02:57:35 +00:00
x450_24_emitting = e;
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
void CParticleElectric::SetModulationColor(const zeus::CColor& color)
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
x1b8_moduColor = color;
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
const zeus::CTransform& CParticleElectric::GetOrientation() const
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
return x44_orientation;
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
const zeus::CVector3f& CParticleElectric::GetTranslation() const
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
return x38_translation;
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
const zeus::CTransform& CParticleElectric::GetGlobalOrientation() const
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
return xb0_globalOrientation;
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
const zeus::CVector3f& CParticleElectric::GetGlobalTranslation() const
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
return xa4_globalTranslation;
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
const zeus::CVector3f& CParticleElectric::GetGlobalScale() const
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
return xe0_globalScale;
2016-02-13 05:49:59 +00:00
}
2016-03-04 23:04:53 +00:00
const zeus::CColor& CParticleElectric::GetModulationColor() const
2016-02-13 05:49:59 +00:00
{
2016-02-26 03:31:00 +00:00
return x1b8_moduColor;
2016-02-13 05:49:59 +00:00
}
bool CParticleElectric::IsSystemDeletable() const
{
2017-06-11 02:57:35 +00:00
if (x450_24_emitting && x28_currentFrame < x2c_LIFE)
return false;
if (x3e8_electricManagers.size())
return false;
if (x450_25_haveGPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
if (!x400_gpsmGenerators[i]->IsSystemDeletable())
return false;
}
if (x450_26_haveEPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
if (!x410_epsmGenerators[i]->IsSystemDeletable())
return false;
}
return true;
2016-02-13 05:49:59 +00:00
}
2017-01-21 06:03:37 +00:00
rstl::optional_object<zeus::CAABox> CParticleElectric::GetBounds() const
2016-02-13 05:49:59 +00:00
{
2017-06-11 02:57:35 +00:00
if (GetParticleCount() <= 0)
return {};
else
return x160_systemBounds;
2016-02-13 05:49:59 +00:00
}
u32 CParticleElectric::GetParticleCount() const
{
2017-06-11 02:57:35 +00:00
u32 ret = 0;
for (const CParticleElectricManager& elec : x3e8_electricManagers)
{
if (x450_27_haveSSWH)
ret += x1e0_swooshGenerators[elec.x0_idx]->GetParticleCount();
if (x450_28_haveLWD)
ret += x150_SSEG;
}
if (x450_25_haveGPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
ret += x400_gpsmGenerators[i]->GetParticleCount();
}
if (x450_26_haveEPSM)
{
for (int i=0 ; i<x154_SCNT ; ++i)
ret += x410_epsmGenerators[i]->GetParticleCount();
}
return ret;
2016-02-13 05:49:59 +00:00
}
bool CParticleElectric::SystemHasLight() const
{
2017-06-11 02:57:35 +00:00
if (x450_25_haveGPSM)
return x400_gpsmGenerators.front()->SystemHasLight();
else if (x450_26_haveEPSM)
return x410_epsmGenerators.front()->SystemHasLight();
2016-02-17 03:42:27 +00:00
return false;
2016-02-13 05:49:59 +00:00
}
CLight CParticleElectric::GetLight() const
{
2017-06-11 02:57:35 +00:00
if (x450_25_haveGPSM)
return x400_gpsmGenerators.front()->GetLight();
else if (x450_26_haveEPSM)
return x410_epsmGenerators.front()->GetLight();
return CLight::BuildLocalAmbient(GetGlobalTranslation(), zeus::CColor::skOrange);
2016-02-13 05:49:59 +00:00
}
bool CParticleElectric::GetParticleEmission() const
{
2017-06-11 02:57:35 +00:00
return x450_24_emitting;
2016-02-13 05:49:59 +00:00
}
void CParticleElectric::DestroyParticles()
{
2017-06-11 02:57:35 +00:00
// Empty
}
}