diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp index abc0aa7cc..4a05e651c 100644 --- a/Runtime/Particle/CElementGen.cpp +++ b/Runtime/Particle/CElementGen.cpp @@ -453,7 +453,7 @@ CElementGen::~CElementGen() g_ParticleAliveCount -= x30_particles.size(); } -void CElementGen::Update(double t) +bool CElementGen::Update(double t) { CParticleGlobals::SParticleSystem* prevSystem = CParticleGlobals::g_currentParticleSystem; CParticleGlobals::SParticleSystem thisSystem { FOURCC('PART'), this }; @@ -470,8 +470,9 @@ void CElementGen::Update(double t) InternalUpdate(pswt / 60.0); x26d_25_warmedUp = true; } - InternalUpdate(t); + bool ret = InternalUpdate(t); CParticleGlobals::g_currentParticleSystem = prevSystem; + return ret; } bool CElementGen::InternalUpdate(double dt) diff --git a/Runtime/Particle/CElementGen.hpp b/Runtime/Particle/CElementGen.hpp index 77ae057e4..48aa8c483 100644 --- a/Runtime/Particle/CElementGen.hpp +++ b/Runtime/Particle/CElementGen.hpp @@ -209,7 +209,7 @@ public: void RenderParticles(); void RenderParticlesIndirectTexture(); - void Update(double); + bool Update(double); void Render(); void SetOrientation(const zeus::CTransform&); void SetTranslation(const zeus::CVector3f&); diff --git a/Runtime/Particle/CParticleElectric.cpp b/Runtime/Particle/CParticleElectric.cpp index d5ab7c46e..d9ee0f6b3 100644 --- a/Runtime/Particle/CParticleElectric.cpp +++ b/Runtime/Particle/CParticleElectric.cpp @@ -96,8 +96,9 @@ void CParticleElectric::RenderLines() CGraphics::SetViewPointMatrix(viewXfrm); } -void CParticleElectric::Update(double) +bool CParticleElectric::Update(double) { + return false; } void CParticleElectric::Render() diff --git a/Runtime/Particle/CParticleElectric.hpp b/Runtime/Particle/CParticleElectric.hpp index 47b9b34fe..abd87190d 100644 --- a/Runtime/Particle/CParticleElectric.hpp +++ b/Runtime/Particle/CParticleElectric.hpp @@ -79,7 +79,7 @@ public: CParticleElectric(const TToken& desc); void SetupLineGXMaterial(); - void Update(double); + bool Update(double); void RenderLines(); void RenderSwooshes(); void Render(); diff --git a/Runtime/Particle/CParticleGen.hpp b/Runtime/Particle/CParticleGen.hpp index 7b9a265e1..2ffd94144 100644 --- a/Runtime/Particle/CParticleGen.hpp +++ b/Runtime/Particle/CParticleGen.hpp @@ -19,7 +19,7 @@ class CParticleGen public: virtual ~CParticleGen() = default; - virtual void Update(double)=0; + virtual bool Update(double)=0; virtual void Render()=0; virtual void SetOrientation(const zeus::CTransform&)=0; virtual void SetTranslation(const zeus::CVector3f&)=0; diff --git a/Runtime/Particle/CParticleSwoosh.cpp b/Runtime/Particle/CParticleSwoosh.cpp index 21280dd15..6ed891350 100644 --- a/Runtime/Particle/CParticleSwoosh.cpp +++ b/Runtime/Particle/CParticleSwoosh.cpp @@ -1,101 +1,323 @@ #include "CParticleSwoosh.hpp" +#include "CSwooshDescription.hpp" +#include "CParticleGlobals.hpp" +#include namespace urde { -CParticleSwoosh::CParticleSwoosh(const TToken& desc, int) +int CParticleSwoosh::g_ParticleSystemAliveCount = 0; + +CParticleSwoosh::CParticleSwoosh(const TToken& desc, int leng) + : x1c_desc(desc), x1c0_rand(x1c_desc->x45_26_CRND ? + std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()).count() : 99) { + x1d0_24_emitting = true; + ++g_ParticleSystemAliveCount; + + if (leng > 0) + x1b4_LENG = leng; + else if (CIntElement* leng = x1c_desc->x10_LENG.get()) + leng->GetValue(0, x1b4_LENG); + x1b4_LENG += 1; + + if (CIntElement* side = x1c_desc->x18_SIDE.get()) + side->GetValue(0, x1b8_SIDE); + + x1d0_28_LLRD = x1c_desc->x44_24_LLRD; + x1d0_29_VLS1 = x1c_desc->x44_26_VLS1; + x1d0_30_VLS2 = x1c_desc->x44_27_VLS2; + + if (IsValid()) + { + if (CIntElement* pslt = x1c_desc->x0_PSLT.get()) + pslt->GetValue(0, x2c_PSLT); + else + x2c_PSLT = INT_MAX; + + x1d0_25_AALP = x1c_desc->x44_31_AALP; + + if (CIntElement* spln = x1c_desc->x38_SPLN.get()) + spln->GetValue(0, x1b0_SPLN); + if (x1b0_SPLN < 0) + x1b0_SPLN = 0; + + x15c_swooshes.clear(); + x15c_swooshes.reserve(x1b4_LENG); + for (int i=0 ; ix8_LRAD.get()) + lrad->GetValue(x15c_swooshes[i].x68_frame, ret); + return ret; +} + +float CParticleSwoosh::GetRightRadius(int i) const +{ + float ret = 0.f; + if (CRealElement* rrad = x1c_desc->xc_RRAD.get()) + rrad->GetValue(x15c_swooshes[i].x68_frame, ret); + return ret; +} + +void CParticleSwoosh::UpdateSwooshTranslation(const zeus::CVector3f& translation) +{ + x15c_swooshes[x158_curParticle].xc_translation = x11c_invScaleXf * translation; +} + +void CParticleSwoosh::UpdateTranslationAndOrientation() +{ + +} + +bool CParticleSwoosh::Update(double dt) +{ + if (!IsValid()) + return false; + + CParticleGlobals::SetParticleLifetime(x1b4_LENG); + CParticleGlobals::SetEmitterTime(x28_curFrame); + CParticleGlobals::UpdateParticleLifetimeTweenValues(0); + CGlobalRandom gr(x1c0_rand); + + float evalTime = x28_curFrame * (1.f / 60.f); + float time = 1.f; + if (CRealElement* timeElem = x1c_desc->x4_TIME.get()) + timeElem->GetValue(x28_curFrame, time); + + x30_curTime += std::max(0.0, dt * time); + while (!x1d0_26_ && evalTime < x30_curTime) + { + x1d0_26_ = false; + + x158_curParticle += 1; + if (x158_curParticle >= x15c_swooshes.size()) + x158_curParticle = 0; + + if (x1d0_24_emitting && x28_curFrame < x2c_PSLT) + { + UpdateSwooshTranslation(x38_translation); + + if (CRealElement* irot = x1c_desc->x1c_IROT.get()) + irot->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x30_irot); + else + x15c_swooshes[x158_curParticle].x30_irot = 0.f; + + x15c_swooshes[x158_curParticle].x34_ = 0.f; + x15c_swooshes[x158_curParticle].x70_ = x28_curFrame; + + if (!x15c_swooshes[x158_curParticle].x0_active) + { + x1ac_particleCount += 1; + x15c_swooshes[x158_curParticle].x0_active = true; + } + + x15c_swooshes[x158_curParticle].x38_orientation = x44_orientation; + + if (CVectorElement* ivel = x1c_desc->x28_IVEL.get()) + { + ivel->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x74_velocity); + x15c_swooshes[x158_curParticle].x74_velocity = x44_orientation * x15c_swooshes[x158_curParticle].x74_velocity; + } + + if (CVectorElement* pofs = x1c_desc->x24_POFS.get()) + pofs->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x18_offset); + + x15c_swooshes[x158_curParticle].x24_ = x15c_swooshes[x158_curParticle].x18_offset; + + if (CColorElement* colr = x1c_desc->x14_COLR.get()) + colr->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x6c_color); + else + x15c_swooshes[x158_curParticle].x6c_color = zeus::CColor::skWhite; + + int tspn = 0; + if (CIntElement* tspnElem = x1c_desc->x40_TSPN.get()) + tspnElem->GetValue(x28_curFrame, tspn); + x1cc_TSPN = tspn; + } + else if (x15c_swooshes[x158_curParticle].x0_active) + { + x1ac_particleCount = std::max(0, int(x1ac_particleCount) - 1); + x15c_swooshes[x158_curParticle].x0_active = false; + } + + UpdateTranslationAndOrientation(); + + evalTime += (1.f / 60.f); + x28_curFrame += 1; + } + + return false; +} + +void CParticleSwoosh::RenderNSidedSpline() +{ + +} + +void CParticleSwoosh::RenderNSidedNoSpline() +{ + +} + +void CParticleSwoosh::Render3SidedSolidSpline() +{ + +} + +void CParticleSwoosh::Render3SidedSolidNoSplineNoGaps() +{ + +} + +void CParticleSwoosh::Render2SidedSpline() +{ + +} + +void CParticleSwoosh::Render2SidedNoSplineGaps() +{ + +} + +void CParticleSwoosh::Render2SidedNoSplineNoGaps() +{ + } void CParticleSwoosh::Render() { } -void CParticleSwoosh::SetOrientation(const zeus::CTransform&) +void CParticleSwoosh::SetOrientation(const zeus::CTransform& xf) { + x44_orientation = xf; + x74_invOrientation = xf.inverse(); + x15c_swooshes[x158_curParticle].x38_orientation = xf; } -void CParticleSwoosh::SetTranslation(const zeus::CVector3f&) +void CParticleSwoosh::SetTranslation(const zeus::CVector3f& translation) { + x38_translation = translation; + UpdateSwooshTranslation(x38_translation); } -void CParticleSwoosh::SetGlobalOrientation(const zeus::CTransform&) +void CParticleSwoosh::SetGlobalOrientation(const zeus::CTransform& xf) { + xb0_globalOrientation = xf.getRotation(); } -void CParticleSwoosh::SetGlobalTranslation(const zeus::CVector3f&) +void CParticleSwoosh::SetGlobalTranslation(const zeus::CVector3f& translation) { + xa4_globalTranslation = translation; } -void CParticleSwoosh::SetGlobalScale(const zeus::CVector3f&) +void CParticleSwoosh::SetGlobalScale(const zeus::CVector3f& scale) { + xe0_globalScale = scale; + xec_scaleXf = zeus::CTransform::Scale(scale); + x11c_invScaleXf = zeus::CTransform::Scale(1.f / scale); } -void CParticleSwoosh::SetLocalScale(const zeus::CVector3f&) +void CParticleSwoosh::SetLocalScale(const zeus::CVector3f& scale) { + x14c_localScale = scale; } -void CParticleSwoosh::SetParticleEmission(bool) +void CParticleSwoosh::SetParticleEmission(bool e) { + x1d0_24_emitting = e; } -void CParticleSwoosh::SetModulationColor(const zeus::CColor&) +void CParticleSwoosh::SetModulationColor(const zeus::CColor& color) { + x20c_moduColor = color; } const zeus::CTransform& CParticleSwoosh::GetOrientation() const { - static zeus::CTransform dummy; - return dummy; + return x44_orientation; } const zeus::CVector3f& CParticleSwoosh::GetTranslation() const { - static zeus::CVector3f dummy; - return dummy; + return x38_translation; } const zeus::CTransform& CParticleSwoosh::GetGlobalOrientation() const { - static zeus::CTransform dummy; - return dummy; + return xb0_globalOrientation; } const zeus::CVector3f& CParticleSwoosh::GetGlobalTranslation() const { - static zeus::CVector3f dummy; - return dummy; + return xa4_globalTranslation; } const zeus::CVector3f& CParticleSwoosh::GetGlobalScale() const { - static zeus::CVector3f dummy; - return dummy; + return xe0_globalScale; } const zeus::CColor& CParticleSwoosh::GetModulationColor() const { - static zeus::CColor dummy; - return dummy; + return x20c_moduColor; } bool CParticleSwoosh::IsSystemDeletable() const { - return false; + if (x1d0_24_emitting && x28_curFrame < x2c_PSLT) + return false; + + if (GetParticleCount() >= 2) + return false; + + return true; } rstl::optional_object CParticleSwoosh::GetBounds() const { - return {}; + if (GetParticleCount() <= 1) + { + zeus::CVector3f trans = x38_translation + xa4_globalTranslation; + return zeus::CAABox(trans, trans); + } + else + { + zeus::CTransform xf = zeus::CTransform::Translate(xa4_globalTranslation) * + xb0_globalOrientation * xec_scaleXf; + return zeus::CAABox(x1f0_ - x208_maxRadius, x1fc_ + x208_maxRadius).getTransformedAABox(xf); + } } u32 CParticleSwoosh::GetParticleCount() const { - return 0; + return x1ac_particleCount; } bool CParticleSwoosh::SystemHasLight() const @@ -105,17 +327,17 @@ bool CParticleSwoosh::SystemHasLight() const CLight CParticleSwoosh::GetLight() const { - return CLight(zeus::CVector3f::skZero, zeus::CVector3f::skZero, - zeus::CColor::skBlack, 0.f, 1.f, 0.f, 0.f, 1.f, 0.f); + return CLight::BuildLocalAmbient(zeus::CVector3f::skZero, zeus::CColor::skWhite); } bool CParticleSwoosh::GetParticleEmission() const { - return false; + return x1d0_24_emitting; } void CParticleSwoosh::DestroyParticles() { + // Empty } } diff --git a/Runtime/Particle/CParticleSwoosh.hpp b/Runtime/Particle/CParticleSwoosh.hpp index 828dd46af..047f51426 100644 --- a/Runtime/Particle/CParticleSwoosh.hpp +++ b/Runtime/Particle/CParticleSwoosh.hpp @@ -3,6 +3,7 @@ #include "CParticleGen.hpp" #include "CToken.hpp" +#include "CRandom16.hpp" namespace urde { @@ -10,10 +11,108 @@ class CSwooshDescription; class CParticleSwoosh : public CParticleGen { + struct SSwooshData + { + bool x0_active; + float x4_; + float x8_; + zeus::CVector3f xc_translation; + zeus::CVector3f x18_offset; + zeus::CVector3f x24_; + float x30_irot; + float x34_; + zeus::CTransform x38_orientation; + int x68_frame; + zeus::CColor x6c_color; + int x70_; + zeus::CVector3f x74_velocity; + + SSwooshData(const zeus::CVector3f& translation, const zeus::CVector3f& offset, float irot, float f2, int w, bool active, + const zeus::CTransform& orient, const zeus::CVector3f& vel, float f3, float f4, + const zeus::CColor& color) + : x0_active(active), x4_(f3), x8_(f4), xc_translation(translation), x18_offset(offset), x24_(offset), + x30_irot(irot), x34_(f2), x38_orientation(orient), x6c_color(color), x70_(w), x74_velocity(vel) {} + }; + + TLockedToken x1c_desc; + u32 x28_curFrame = 0; + int x2c_PSLT = 0; + double x30_curTime = 0.0; + zeus::CVector3f x38_translation; + zeus::CTransform x44_orientation; + zeus::CTransform x74_invOrientation; + zeus::CVector3f xa4_globalTranslation; + zeus::CTransform xb0_globalOrientation; + zeus::CVector3f xe0_globalScale = {1.f, 1.f, 1.f}; + zeus::CTransform xec_scaleXf; + zeus::CTransform x11c_invScaleXf; + zeus::CVector3f x14c_localScale = {1.f, 1.f, 1.f}; + u32 x158_curParticle = 0; + std::vector x15c_swooshes; + std::vector x16c_; + std::vector x17c_; + std::vector x18c_; + std::vector x19c_; + u32 x1ac_particleCount = 0; + int x1b0_SPLN = 0; + int x1b4_LENG = 0; + int x1b8_SIDE = 0; + CRandom16 x1c0_rand; + float x1c4_ = 0.f; + float x1c8_ = 0.f; + float x1cc_TSPN; + + union + { + struct + { + bool x1d0_24_emitting : 1; + bool x1d0_25_AALP : 1; + bool x1d0_26_ : 1; + bool x1d0_27_ : 1; + bool x1d0_28_LLRD : 1; + bool x1d0_29_VLS1 : 1; + bool x1d0_30_VLS2 : 1; + bool x1d0_31_ : 1; + bool x1d1_24_ : 1; + }; + u32 _dummy = 0; + }; + + float x1d4_ = 0.f; + float x1d8_ = 0.f; + float x1dc_ = 0.f; + float x1e0_ = 0.f; + u32 x1e4_ = 0; + float x1e8_ = 1.f; + u32 x1ec_ = 0; + zeus::CVector3f x1f0_; + zeus::CVector3f x1fc_; + float x208_maxRadius = 0.f; + zeus::CColor x20c_moduColor = zeus::CColor::skWhite; + + static int g_ParticleSystemAliveCount; + + bool IsValid() const { return x1b4_LENG >= 2 && x1b8_SIDE >= 2; } + void UpdateMaxRadius(float r); + float GetLeftRadius(int i) const; + float GetRightRadius(int i) const; + void UpdateSwooshTranslation(const zeus::CVector3f& translation); + void UpdateTranslationAndOrientation(); + + void RenderNSidedSpline(); + void RenderNSidedNoSpline(); + void Render3SidedSolidSpline(); + void Render3SidedSolidNoSplineNoGaps(); + void Render2SidedSpline(); + void Render2SidedNoSplineGaps(); + void Render2SidedNoSplineNoGaps(); + public: CParticleSwoosh(const TToken& desc, int); + ~CParticleSwoosh(); - void Update(double); + bool Update(double); void Render(); void SetOrientation(const zeus::CTransform&); void SetTranslation(const zeus::CVector3f&);