mirror of https://github.com/AxioDL/metaforce.git
Finish CParticleElectric
This commit is contained in:
parent
92122a9b31
commit
f8f3bf407a
|
@ -17,7 +17,7 @@ static logvisor::Module Log("urde::CElementGen");
|
||||||
|
|
||||||
URDE_DECL_SPECIALIZE_SHADER(CElementGenShaders)
|
URDE_DECL_SPECIALIZE_SHADER(CElementGenShaders)
|
||||||
|
|
||||||
CRandom16 CElementGen::g_GlobalSeed = 99;
|
u16 CElementGen::g_GlobalSeed = 99;
|
||||||
|
|
||||||
int CElementGen::g_ParticleAliveCount;
|
int CElementGen::g_ParticleAliveCount;
|
||||||
int CElementGen::g_ParticleSystemAliveCount;
|
int CElementGen::g_ParticleSystemAliveCount;
|
||||||
|
@ -691,8 +691,8 @@ void CElementGen::UpdateChildParticleSystems(double dt)
|
||||||
CSpawnSystemKeyframeData* kssm = desc->xd0_xbc_KSSM.get();
|
CSpawnSystemKeyframeData* kssm = desc->xd0_xbc_KSSM.get();
|
||||||
if (kssm && x84_prevFrame != x74_curFrame && x74_curFrame < x268_PSLT)
|
if (kssm && x84_prevFrame != x74_curFrame && x74_curFrame < x268_PSLT)
|
||||||
{
|
{
|
||||||
CRandom16 backupSeed = g_GlobalSeed;
|
u16 backupSeed = g_GlobalSeed;
|
||||||
CRandom16 incSeed = backupSeed;
|
u16 incSeed = backupSeed;
|
||||||
|
|
||||||
std::vector<CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo>& systems =
|
std::vector<CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo>& systems =
|
||||||
kssm->GetSpawnedSystemsAtFrame(x74_curFrame);
|
kssm->GetSpawnedSystemsAtFrame(x74_curFrame);
|
||||||
|
@ -706,7 +706,7 @@ void CElementGen::UpdateChildParticleSystems(double dt)
|
||||||
std::unique_ptr<CParticleGen> chGen = ConstructChildParticleSystem(token);
|
std::unique_ptr<CParticleGen> chGen = ConstructChildParticleSystem(token);
|
||||||
x290_activePartChildren.emplace_back(std::move(chGen));
|
x290_activePartChildren.emplace_back(std::move(chGen));
|
||||||
}
|
}
|
||||||
incSeed.SetSeed(incSeed.GetSeed() + 1);
|
incSeed += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_GlobalSeed = backupSeed;
|
g_GlobalSeed = backupSeed;
|
||||||
|
|
|
@ -26,9 +26,9 @@ class CParticleElectric;
|
||||||
|
|
||||||
class CElementGen : public CParticleGen
|
class CElementGen : public CParticleGen
|
||||||
{
|
{
|
||||||
static CRandom16 g_GlobalSeed;
|
static u16 g_GlobalSeed;
|
||||||
public:
|
public:
|
||||||
static void SetGlobalSeed(u16 seed) { g_GlobalSeed.SetSeed(seed); }
|
static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; }
|
||||||
enum class EModelOrientationType
|
enum class EModelOrientationType
|
||||||
{
|
{
|
||||||
Normal,
|
Normal,
|
||||||
|
|
|
@ -6,146 +6,758 @@
|
||||||
#include "CElementGen.hpp"
|
#include "CElementGen.hpp"
|
||||||
#include "Graphics/CModel.hpp"
|
#include "Graphics/CModel.hpp"
|
||||||
#include "Graphics/CGraphics.hpp"
|
#include "Graphics/CGraphics.hpp"
|
||||||
|
#include "CParticleGlobals.hpp"
|
||||||
|
#include "zeus/CRelAngle.hpp"
|
||||||
|
#include "zeus/CQuaternion.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
|
||||||
CRandom16 CParticleElectric::g_GlobalSeed = 99;
|
u16 CParticleElectric::g_GlobalSeed = 99;
|
||||||
|
|
||||||
void CParticleElectric::RenderSwooshes()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CParticleElectric::CParticleElectric(const TToken<CElectricDescription>& token)
|
CParticleElectric::CParticleElectric(const TToken<CElectricDescription>& token)
|
||||||
: x1c_elecDesc(token)
|
: x1c_elecDesc(token), x14c_randState(g_GlobalSeed++)
|
||||||
{
|
{
|
||||||
x450_24 = true;
|
x450_24_emitting = true;
|
||||||
/* x438_28_x450_28 = true; demo */
|
x450_29_transformDirty = true;
|
||||||
x450_29 = true; // are 28 and 29 the same between retail and demo?
|
|
||||||
CElectricDescription* desc = x1c_elecDesc.GetObj();
|
CElectricDescription* desc = x1c_elecDesc.GetObj();
|
||||||
if (desc->x10_SSEG)
|
|
||||||
desc->x10_SSEG->GetValue(x28_currentFrame, x150_SSEG);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x150_SSEG++;
|
|
||||||
x154_SCNT = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desc->xc_SCNT)
|
if (CIntElement* sseg = desc->x10_SSEG.get())
|
||||||
desc->xc_SCNT->GetValue(x28_currentFrame, x154_SCNT);
|
sseg->GetValue(x28_currentFrame, x150_SSEG);
|
||||||
std::max(0, std::min(x154_SCNT, 32));
|
|
||||||
|
|
||||||
if (desc->x0_LIFE)
|
if (CIntElement* scnt = desc->xc_SCNT.get())
|
||||||
desc->x0_LIFE->GetValue(x28_currentFrame, x2c_LIFE);
|
scnt->GetValue(x28_currentFrame, x154_SCNT);
|
||||||
|
|
||||||
|
x154_SCNT = std::min(x154_SCNT, 32);
|
||||||
|
|
||||||
|
if (CIntElement* life = desc->x0_LIFE.get())
|
||||||
|
life->GetValue(0, x2c_LIFE);
|
||||||
else
|
else
|
||||||
x2c_LIFE = 0x7FFFFF;
|
x2c_LIFE = INT_MAX;
|
||||||
|
|
||||||
if (desc->x40_SSWH)
|
if (desc->x40_SSWH)
|
||||||
{
|
{
|
||||||
x450_27_HaveSSWH = true;
|
x450_27_haveSSWH = true;
|
||||||
for (int i = 0 ; i < x154_SCNT ; i++)
|
x1e0_swooshGenerators.reserve(x154_SCNT);
|
||||||
x1e0_lineManagers[i].SSWH.reset(new CParticleSwoosh(desc->x40_SSWH.m_token, x150_SSEG));
|
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();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++x150_SSEG;
|
||||||
|
x420_calculatedVerts.resize(x150_SSEG);
|
||||||
|
x440_fractalOffsets.resize(x150_SSEG);
|
||||||
|
x430_fractalMags.resize(x150_SSEG);
|
||||||
|
|
||||||
if (desc->x50_GPSM)
|
if (desc->x50_GPSM)
|
||||||
{
|
{
|
||||||
x450_25_HaveGPSM = true;
|
x450_25_haveGPSM = true;
|
||||||
for (int i = 0 ; i < x154_SCNT ; i++)
|
x400_gpsmGenerators.reserve(x154_SCNT);
|
||||||
x1e0_lineManagers[i].GPSM.reset(new CElementGen(desc->x50_GPSM.m_token,
|
for (int i=0 ; i<x154_SCNT ; ++i)
|
||||||
|
{
|
||||||
|
x400_gpsmGenerators.emplace_back(new CElementGen(desc->x50_GPSM.m_token,
|
||||||
CElementGen::EModelOrientationType::Normal,
|
CElementGen::EModelOrientationType::Normal,
|
||||||
CElementGen::EOptionalSystemFlags::One));
|
CElementGen::EOptionalSystemFlags::One));
|
||||||
|
x400_gpsmGenerators.back()->SetParticleEmission(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc->x60_EPSM)
|
if (desc->x60_EPSM)
|
||||||
{
|
{
|
||||||
x450_26_HaveEPSM = true;
|
x450_26_haveEPSM = true;
|
||||||
for (int i = 0 ; i < x154_SCNT ; i++)
|
x410_epsmGenerators.reserve(x154_SCNT);
|
||||||
x1e0_lineManagers[i].EPSM.reset(new CElementGen(desc->x60_EPSM.m_token,
|
for (int i=0 ; i<x154_SCNT ; ++i)
|
||||||
|
{
|
||||||
|
x410_epsmGenerators.emplace_back(new CElementGen(desc->x60_EPSM.m_token,
|
||||||
CElementGen::EModelOrientationType::Normal,
|
CElementGen::EModelOrientationType::Normal,
|
||||||
CElementGen::EOptionalSystemFlags::One));
|
CElementGen::EOptionalSystemFlags::One));
|
||||||
|
x410_epsmGenerators.back()->SetParticleEmission(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
void CParticleElectric::SetupLineGXMaterial()
|
void CParticleElectric::SetupLineGXMaterial()
|
||||||
{
|
{
|
||||||
|
// Konst color/alpha 0
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::RenderLines()
|
void CParticleElectric::RenderLines()
|
||||||
{
|
{
|
||||||
|
m_nextLineRenderer = 0;
|
||||||
CGraphics::DisableAllLights();
|
CGraphics::DisableAllLights();
|
||||||
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false);
|
// Z-test, no write
|
||||||
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear);
|
// Additive blend
|
||||||
|
|
||||||
zeus::CTransform viewXfrm = CGraphics::g_ViewMatrix;
|
CGraphics::SetModelMatrix(zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation *
|
||||||
zeus::CTransform localScale;
|
zeus::CTransform::Translate(x38_translation) * x44_orientation *
|
||||||
localScale.Scale(xec_localScale);
|
zeus::CTransform::Scale(xe0_globalScale) * zeus::CTransform::Scale(xec_localScale));
|
||||||
zeus::CTransform globalScale;
|
// Disable culling
|
||||||
globalScale.Scale(xe0_globalScale);
|
|
||||||
zeus::CTransform localTranslation;
|
|
||||||
localTranslation.Translate(x38_translation);
|
|
||||||
zeus::CTransform globalTranslation;
|
|
||||||
globalTranslation.Translate(xa4_globalTranslation);
|
|
||||||
CGraphics::SetModelMatrix(xb0_globalOrientation * globalTranslation * localTranslation * x44_orientation * globalScale);
|
|
||||||
CGraphics::SetCullMode(ERglCullMode::None);
|
|
||||||
SetupLineGXMaterial();
|
SetupLineGXMaterial();
|
||||||
/* Iterate line managers */
|
for (CParticleElectricManager& elec : x3e8_electricManagers)
|
||||||
|
{
|
||||||
CGraphics::SetCullMode(ERglCullMode::Front);
|
CLineManager& line = *x2e4_lineManagers[elec.x0_idx];
|
||||||
//CGraphics::SetLineWidth(1.f, ERglTexOffset);
|
if (x1c_elecDesc->x28_LWD1)
|
||||||
CGraphics::SetViewPointMatrix(viewXfrm);
|
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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CParticleElectric::Update(double)
|
// Enable culling
|
||||||
|
// Line Width 1
|
||||||
|
}
|
||||||
|
|
||||||
|
void CParticleElectric::UpdateCachedTransform()
|
||||||
{
|
{
|
||||||
return false;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::Render()
|
void CParticleElectric::Render()
|
||||||
{
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::SetOrientation(const zeus::CTransform& orientation)
|
void CParticleElectric::SetOrientation(const zeus::CTransform& orientation)
|
||||||
{
|
{
|
||||||
x44_orientation = orientation;
|
x44_orientation = orientation;
|
||||||
x450_28 = true;
|
x74_invOrientation = x44_orientation.inverse();
|
||||||
|
x450_29_transformDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::SetTranslation(const zeus::CVector3f& translation)
|
void CParticleElectric::SetTranslation(const zeus::CVector3f& translation)
|
||||||
{
|
{
|
||||||
x38_translation = translation;
|
x38_translation = translation;
|
||||||
x450_28 = true;
|
x450_29_transformDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::SetGlobalOrientation(const zeus::CTransform& orientation)
|
void CParticleElectric::SetGlobalOrientation(const zeus::CTransform& orientation)
|
||||||
{
|
{
|
||||||
xb0_globalOrientation = orientation;
|
xb0_globalOrientation = orientation;
|
||||||
x450_28 = true;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::SetGlobalTranslation(const zeus::CVector3f& translation)
|
void CParticleElectric::SetGlobalTranslation(const zeus::CVector3f& translation)
|
||||||
{
|
{
|
||||||
xa4_globalTranslation = translation;
|
xa4_globalTranslation = translation;
|
||||||
x450_28 = true;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::SetGlobalScale(const zeus::CVector3f& scale)
|
void CParticleElectric::SetGlobalScale(const zeus::CVector3f& scale)
|
||||||
{
|
{
|
||||||
xe0_globalScale = scale;
|
xe0_globalScale = scale;
|
||||||
x450_28 = true;
|
x450_29_transformDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::SetLocalScale(const zeus::CVector3f& scale)
|
void CParticleElectric::SetLocalScale(const zeus::CVector3f& scale)
|
||||||
{
|
{
|
||||||
xec_localScale = scale;
|
xec_localScale = scale;
|
||||||
x450_29 = true;
|
x450_29_transformDirty = true;
|
||||||
if (x450_27_HaveSSWH)
|
|
||||||
|
if (x450_27_haveSSWH)
|
||||||
{
|
{
|
||||||
|
for (CParticleElectricManager& elec : x3e8_electricManagers)
|
||||||
|
{
|
||||||
|
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
|
||||||
|
swoosh.SetLocalScale(xec_localScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::SetParticleEmission(bool)
|
if (x450_25_haveGPSM)
|
||||||
{
|
{
|
||||||
|
for (int i=0 ; i<x154_SCNT ; ++i)
|
||||||
|
x400_gpsmGenerators[i]->SetLocalScale(xec_localScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x450_26_haveEPSM)
|
||||||
|
{
|
||||||
|
for (int i=0 ; i<x154_SCNT ; ++i)
|
||||||
|
x410_epsmGenerators[i]->SetLocalScale(xec_localScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CParticleElectric::SetParticleEmission(bool e)
|
||||||
|
{
|
||||||
|
x450_24_emitting = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::SetModulationColor(const zeus::CColor& color)
|
void CParticleElectric::SetModulationColor(const zeus::CColor& color)
|
||||||
|
@ -185,37 +797,90 @@ const zeus::CColor& CParticleElectric::GetModulationColor() const
|
||||||
|
|
||||||
bool CParticleElectric::IsSystemDeletable() const
|
bool CParticleElectric::IsSystemDeletable() const
|
||||||
{
|
{
|
||||||
|
if (x450_24_emitting && x28_currentFrame < x2c_LIFE)
|
||||||
return false;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
rstl::optional_object<zeus::CAABox> CParticleElectric::GetBounds() const
|
rstl::optional_object<zeus::CAABox> CParticleElectric::GetBounds() const
|
||||||
{
|
{
|
||||||
|
if (GetParticleCount() <= 0)
|
||||||
return {};
|
return {};
|
||||||
|
else
|
||||||
|
return x160_systemBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CParticleElectric::GetParticleCount() const
|
u32 CParticleElectric::GetParticleCount() const
|
||||||
{
|
{
|
||||||
return 0;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CParticleElectric::SystemHasLight() const
|
bool CParticleElectric::SystemHasLight() const
|
||||||
{
|
{
|
||||||
|
if (x450_25_haveGPSM)
|
||||||
|
return x400_gpsmGenerators.front()->SystemHasLight();
|
||||||
|
else if (x450_26_haveEPSM)
|
||||||
|
return x410_epsmGenerators.front()->SystemHasLight();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLight CParticleElectric::GetLight() const
|
CLight CParticleElectric::GetLight() const
|
||||||
{
|
{
|
||||||
return CLight(zeus::CVector3f::skZero, zeus::CVector3f::skZero,
|
if (x450_25_haveGPSM)
|
||||||
zeus::CColor::skBlack, 0.f, 1.f, 0.f, 0.f, 1.f, 0.f);
|
return x400_gpsmGenerators.front()->GetLight();
|
||||||
|
else if (x450_26_haveEPSM)
|
||||||
|
return x410_epsmGenerators.front()->GetLight();
|
||||||
|
return CLight::BuildLocalAmbient(GetGlobalTranslation(), zeus::CColor::skOrange);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CParticleElectric::GetParticleEmission() const
|
bool CParticleElectric::GetParticleEmission() const
|
||||||
{
|
{
|
||||||
return false;
|
return x450_24_emitting;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CParticleElectric::DestroyParticles()
|
void CParticleElectric::DestroyParticles()
|
||||||
{
|
{
|
||||||
|
// Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "CParticleGen.hpp"
|
#include "CParticleGen.hpp"
|
||||||
#include "CToken.hpp"
|
#include "CToken.hpp"
|
||||||
#include "CRandom16.hpp"
|
#include "CRandom16.hpp"
|
||||||
|
#include "Graphics/CLineRenderer.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -13,78 +14,100 @@ class CElementGen;
|
||||||
|
|
||||||
class CParticleElectric : public CParticleGen
|
class CParticleElectric : public CParticleGen
|
||||||
{
|
{
|
||||||
static CRandom16 g_GlobalSeed;
|
static u16 g_GlobalSeed;
|
||||||
public:
|
public:
|
||||||
static void SetGlobalSeed(u16 seed) { g_GlobalSeed.SetSeed(seed); }
|
static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; }
|
||||||
struct CLineManager
|
class CLineManager
|
||||||
{
|
{
|
||||||
std::unique_ptr<CParticleSwoosh> SSWH;
|
friend class CParticleElectric;
|
||||||
std::unique_ptr<CElementGen> GPSM;
|
std::vector<zeus::CVector3f> x0_verts;
|
||||||
std::unique_ptr<CElementGen> EPSM;
|
float x10_widths[3] = {1.f, 2.f, 3.f};
|
||||||
|
zeus::CColor x1c_colors[3];
|
||||||
|
zeus::CAABox x28_aabb = zeus::CAABox::skInvertedBox;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CParticleElectricManager
|
||||||
|
{
|
||||||
|
friend class CParticleElectric;
|
||||||
|
u32 x0_idx;
|
||||||
|
u32 x4_slif;
|
||||||
|
u32 x8_startFrame;
|
||||||
|
u32 xc_endFrame;
|
||||||
|
int x10_gpsmIdx = -1;
|
||||||
|
int x14_epsmIdx = -1;
|
||||||
|
public:
|
||||||
|
CParticleElectricManager(u32 idx, u32 slif, u32 startFrame)
|
||||||
|
: x0_idx(idx), x4_slif(slif), x8_startFrame(startFrame), xc_endFrame(startFrame + slif) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TLockedToken<CElectricDescription> x1c_elecDesc;
|
TLockedToken<CElectricDescription> x1c_elecDesc;
|
||||||
int x28_currentFrame = 0;
|
int x28_currentFrame = 0;
|
||||||
int x2c_LIFE = 0x7FFFFF;
|
int x2c_LIFE;
|
||||||
double x30 = 0.0;
|
double x30_curTime = 0.0;
|
||||||
zeus::CVector3f x38_translation;
|
zeus::CVector3f x38_translation;
|
||||||
zeus::CTransform x44_orientation;
|
zeus::CTransform x44_orientation;
|
||||||
|
zeus::CTransform x74_invOrientation;
|
||||||
zeus::CVector3f xa4_globalTranslation;
|
zeus::CVector3f xa4_globalTranslation;
|
||||||
zeus::CTransform xb0_globalOrientation;
|
zeus::CTransform xb0_globalOrientation;
|
||||||
zeus::CVector3f xe0_globalScale;
|
zeus::CVector3f xe0_globalScale;
|
||||||
zeus::CVector3f xec_localScale;
|
zeus::CVector3f xec_localScale;
|
||||||
|
zeus::CTransform xf8_cachedXf;
|
||||||
float x128 = 0.f;
|
float x128 = 0.f;
|
||||||
float x12c = 0.f;
|
float x12c = 0.f;
|
||||||
zeus::CVector3f x130;
|
zeus::CAABox x130_buildBounds = zeus::CAABox::skInvertedBox;
|
||||||
zeus::CVector3f x13c;
|
|
||||||
CRandom16 x14c_randState;
|
CRandom16 x14c_randState;
|
||||||
int x150_SSEG = 8;
|
int x150_SSEG = 8;
|
||||||
int x154_SCNT = 1;
|
int x154_SCNT = 1;
|
||||||
int x158 = 0;
|
int x158 = 0;
|
||||||
float x15c = 0.f;
|
float x15c_genRem = 0.f;
|
||||||
zeus::CAABox x160_systemBounds = zeus::CAABox::skInvertedBox;
|
zeus::CAABox x160_systemBounds = zeus::CAABox::skInvertedBox;
|
||||||
bool x184 = false;
|
std::experimental::optional<zeus::CVector3f> x178_overrideIPos;
|
||||||
bool x194 = false;
|
std::experimental::optional<zeus::CVector3f> x188_overrideIVel;
|
||||||
bool x1b4 = false;
|
std::experimental::optional<zeus::CVector3f> x198_overrideFPos;
|
||||||
|
std::experimental::optional<zeus::CVector3f> x1a8_overrideFVel;
|
||||||
zeus::CColor x1b8_moduColor;
|
zeus::CColor x1b8_moduColor;
|
||||||
rstl::reserved_vector<bool,32> x1c0_;
|
rstl::reserved_vector<bool, 32> x1bc_allocated;
|
||||||
rstl::reserved_vector<CLineManager, 32> x1e0_lineManagers;
|
rstl::reserved_vector<std::unique_ptr<CParticleSwoosh>, 32> x1e0_swooshGenerators;
|
||||||
int x414 = 0;
|
rstl::reserved_vector<std::unique_ptr<CLineManager>, 32> x2e4_lineManagers;
|
||||||
int x418 = 0;
|
std::list<CParticleElectricManager> x3e8_electricManagers;
|
||||||
int x41c = 0;
|
std::vector<std::unique_ptr<CElementGen>> x400_gpsmGenerators;
|
||||||
int x424 = 0;
|
std::vector<std::unique_ptr<CElementGen>> x410_epsmGenerators;
|
||||||
int x428 = 0;
|
std::vector<zeus::CVector3f> x420_calculatedVerts;
|
||||||
int x42c = 0;
|
std::vector<float> x430_fractalMags;
|
||||||
int x434 = 0;
|
std::vector<zeus::CVector3f> x440_fractalOffsets;
|
||||||
int x438 = 0;
|
|
||||||
int x43c = 0;
|
size_t m_nextLineRenderer = 0;
|
||||||
int x444 = 0;
|
std::vector<std::unique_ptr<CLineRenderer>> m_lineRenderers;
|
||||||
int x448 = 0; // retail
|
|
||||||
int x44c = 0; // retail
|
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool x450_24 : 1; bool x450_25_HaveGPSM : 1; bool x450_26_HaveEPSM : 1;
|
bool x450_24_emitting : 1; bool x450_25_haveGPSM : 1; bool x450_26_haveEPSM : 1;
|
||||||
bool x450_27_HaveSSWH : 1; bool x450_28: 1; bool x450_29 : 1;
|
bool x450_27_haveSSWH : 1; bool x450_28_haveLWD: 1; bool x450_29_transformDirty : 1;
|
||||||
};
|
};
|
||||||
u8 dummy = 0;
|
u32 dummy = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
CParticleElectric(const TToken<CElectricDescription>& desc);
|
|
||||||
|
|
||||||
void SetupLineGXMaterial();
|
void SetupLineGXMaterial();
|
||||||
bool Update(double);
|
void DrawLineStrip(const std::vector<zeus::CVector3f>& verts, float width, const zeus::CColor& color);
|
||||||
void RenderLines();
|
void RenderLines();
|
||||||
void RenderSwooshes();
|
void RenderSwooshes();
|
||||||
void Render();
|
void UpdateCachedTransform();
|
||||||
void CalculateFractal(s32, s32, float, float);
|
void UpdateLine(int idx, int frame);
|
||||||
|
void UpdateElectricalEffects();
|
||||||
|
void CalculateFractal(int start, int end, float ampl, float ampd);
|
||||||
void CalculatePoints();
|
void CalculatePoints();
|
||||||
|
void CreateNewParticles(int count);
|
||||||
|
void AddElectricalEffects();
|
||||||
|
void BuildBounds();
|
||||||
|
|
||||||
|
public:
|
||||||
|
CParticleElectric(const TToken<CElectricDescription>& desc);
|
||||||
|
|
||||||
|
bool Update(double);
|
||||||
|
void Render();
|
||||||
void SetOrientation(const zeus::CTransform&);
|
void SetOrientation(const zeus::CTransform&);
|
||||||
void SetTranslation(const zeus::CVector3f&);
|
void SetTranslation(const zeus::CVector3f&);
|
||||||
void SetGlobalOrientation(const zeus::CTransform&);
|
void SetGlobalOrientation(const zeus::CTransform&);
|
||||||
|
|
|
@ -227,7 +227,7 @@ bool CParticleSwoosh::Update(double dt)
|
||||||
CParticleGlobals::UpdateParticleLifetimeTweenValues(0);
|
CParticleGlobals::UpdateParticleLifetimeTweenValues(0);
|
||||||
CGlobalRandom gr(x1c0_rand);
|
CGlobalRandom gr(x1c0_rand);
|
||||||
|
|
||||||
float evalTime = x28_curFrame * (1.f / 60.f);
|
double evalTime = x28_curFrame / 60.0;
|
||||||
float time = 1.f;
|
float time = 1.f;
|
||||||
if (CRealElement* timeElem = x1c_desc->x4_TIME.get())
|
if (CRealElement* timeElem = x1c_desc->x4_TIME.get())
|
||||||
timeElem->GetValue(x28_curFrame, time);
|
timeElem->GetValue(x28_curFrame, time);
|
||||||
|
@ -290,7 +290,7 @@ bool CParticleSwoosh::Update(double dt)
|
||||||
|
|
||||||
UpdateTranslationAndOrientation();
|
UpdateTranslationAndOrientation();
|
||||||
|
|
||||||
evalTime += (1.f / 60.f);
|
evalTime += (1.0 / 60.0);
|
||||||
x28_curFrame += 1;
|
x28_curFrame += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,6 +159,25 @@ public:
|
||||||
void DestroyParticles();
|
void DestroyParticles();
|
||||||
void Reset() {}
|
void Reset() {}
|
||||||
FourCC Get4CharId() const { return FOURCC('SWHC'); }
|
FourCC Get4CharId() const { return FOURCC('SWHC'); }
|
||||||
|
|
||||||
|
void DoElectricWarmup()
|
||||||
|
{
|
||||||
|
for (int i=0 ; i<x15c_swooshes.size() ; ++i)
|
||||||
|
{
|
||||||
|
x1d0_26_disableUpdate = true;
|
||||||
|
Update(0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoElectricCreate(const std::vector<zeus::CVector3f>& offsets)
|
||||||
|
{
|
||||||
|
int curIdx = x158_curParticle;
|
||||||
|
for (int i=0 ; i<x15c_swooshes.size() ; ++i)
|
||||||
|
{
|
||||||
|
curIdx = (curIdx + 1) % x15c_swooshes.size();
|
||||||
|
x15c_swooshes[curIdx].xc_translation = offsets[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
|
||||||
CRandom16 CProjectileWeapon::g_GlobalSeed = 99;
|
u16 CProjectileWeapon::g_GlobalSeed = 99;
|
||||||
|
|
||||||
CProjectileWeapon::CProjectileWeapon(const TToken<CWeaponDescription>& wDesc, const zeus::CVector3f&, const zeus::CTransform&,
|
CProjectileWeapon::CProjectileWeapon(const TToken<CWeaponDescription>& wDesc, const zeus::CVector3f&, const zeus::CTransform&,
|
||||||
const zeus::CVector3f&, s32)
|
const zeus::CVector3f&, s32)
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace urde
|
||||||
class CModel;
|
class CModel;
|
||||||
class CProjectileWeapon
|
class CProjectileWeapon
|
||||||
{
|
{
|
||||||
static CRandom16 g_GlobalSeed;
|
static u16 g_GlobalSeed;
|
||||||
TLockedToken<CWeaponDescription> x4_weaponDesc;
|
TLockedToken<CWeaponDescription> x4_weaponDesc;
|
||||||
CRandom16 x10_random;
|
CRandom16 x10_random;
|
||||||
zeus::CTransform x14_;
|
zeus::CTransform x14_;
|
||||||
|
@ -68,7 +68,7 @@ public:
|
||||||
void Update(float);
|
void Update(float);
|
||||||
void UpdateParticleFx();
|
void UpdateParticleFx();
|
||||||
void UpdateChildParticleSystems(float);
|
void UpdateChildParticleSystems(float);
|
||||||
static void SetGlobalSeed(u16 seed) { g_GlobalSeed.SetSeed(seed); }
|
static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue