diff --git a/DataSpec/DNACommon/ParticleCommon.cpp b/DataSpec/DNACommon/ParticleCommon.cpp index 2dc36ec52..cc8876fa6 100644 --- a/DataSpec/DNACommon/ParticleCommon.cpp +++ b/DataSpec/DNACommon/ParticleCommon.cpp @@ -119,7 +119,7 @@ void RealElementFactory::read(Athena::io::YAMLDocReader& r) m_elem.reset(new struct RECEXT); break; case SBIG('ITRL'): - m_elem.reset(new struct REITRL); + m_elem.reset(new struct REIntTimesReal); break; default: m_elem.reset(); @@ -252,7 +252,7 @@ void RealElementFactory::read(Athena::io::IStreamReader& r) m_elem.reset(new struct RECEXT); break; case SBIG('ITRL'): - m_elem.reset(new struct REITRL); + m_elem.reset(new struct REIntTimesReal); break; case SBIG('NONE'): m_elem.reset(); diff --git a/DataSpec/DNACommon/ParticleCommon.hpp b/DataSpec/DNACommon/ParticleCommon.hpp index faaf03ed9..c7e27e0d5 100644 --- a/DataSpec/DNACommon/ParticleCommon.hpp +++ b/DataSpec/DNACommon/ParticleCommon.hpp @@ -372,7 +372,7 @@ struct RECEXT : IRealElement const char* ClassID() const {return "CEXT";} }; -struct REITRL : IRealElement +struct REIntTimesReal : IRealElement { DECL_YAML IntElementFactory a; diff --git a/Runtime/Particle/CIntElement.cpp b/Runtime/Particle/CIntElement.cpp index e69de29bb..db544400d 100644 --- a/Runtime/Particle/CIntElement.cpp +++ b/Runtime/Particle/CIntElement.cpp @@ -0,0 +1,231 @@ +#include "CIntElement.hpp" +#include "CParticleGlobals.hpp" +#include "CRandom16.hpp" + +namespace Retro +{ + +CIEKeyframeEmitter::CIEKeyframeEmitter(CInputStream& in) +{ + x4_percent = in.readUint32Big(); + x8_unk1 = in.readUint32Big(); + xc_loop = in.readBool(); + xd_unk2 = in.readBool(); + x10_loopEnd = in.readUint32Big(); + x14_loopStart = in.readUint32Big(); + + u32 count = in.readUint32Big(); + x18_keys.reserve(count); + for (u32 i=0 ; i= x10_loopEnd) + { + int v1 = emitterTime - x14_loopStart; + int v2 = x10_loopEnd - x14_loopStart; + calcKey = v1 % v2; + calcKey += x14_loopStart; + } + } + else + { + int v1 = x10_loopEnd - 1; + if (v1 < emitterTime) + calcKey = v1; + } + valOut = x18_keys[calcKey]; + } + else + { + int ltPerc = CParticleGlobals::g_particleLifetimePercentTweenInt; + float ltPercRem = CParticleGlobals::g_particleLifetimePercentTweenIntFloatRem; + if (ltPerc == 100) + valOut = x18_keys[100]; + else + valOut = ltPercRem * x18_keys[ltPerc+1] + (1.0f - ltPercRem) * x18_keys[ltPerc]; + } + return false; +} + +bool CIEDeath::GetValue(int frame, int &valOut) const +{ + x4_a->GetValue(frame, valOut); + int b; + x8_b->GetValue(frame, b); + /* Not 100% sure about this, originally some kinda branchless comparison */ + return frame > b; +} + +bool CIEClamp::GetValue(int frame, int& valOut) const +{ + int a, b; + x4_min->GetValue(frame, a); + x8_max->GetValue(frame, b); + xc_val->GetValue(frame, valOut); + if (valOut > b) + valOut = b; + if (valOut < a) + valOut = a; + return false; +} + +bool CIETimeChain::GetValue(int frame, int& valOut) const +{ + int v; + xc_swFrame->GetValue(frame, v); + if (frame >= v) + return x8_b->GetValue(frame, valOut); + else + return x4_a->GetValue(frame, valOut); +} + +bool CIEAdd::GetValue(int frame, int& valOut) const +{ + int a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a + b; + return false; +} + +bool CIEConstant::GetValue(int frame, int& valOut) const +{ + valOut = x4_val; + return false; +} + +bool CIEImpulse::GetValue(int frame, int& valOut) const +{ + if (frame == 0) + x4_a->GetValue(frame, valOut); + else + valOut = 0; + return false; +} + +bool CIELifetimePercent::GetValue(int frame, int& valOut) const +{ + int a; + x4_percentVal->GetValue(frame, a); + a = std::max(0, a); + valOut = (a / 100.0f) * CParticleGlobals::g_particleLifetimeFloat; + return false; +} + +bool CIEInitialRandom::GetValue(int frame, int& valOut) const +{ + if (frame == 0) + { + int a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = CRandom16::GetRandomNumber()->Range(a, b); + } + return false; +} + +bool CIEPulse::GetValue(int frame, int& valOut) const +{ + int a, b; + x4_aDuration->GetValue(frame, a); + x8_bDuration->GetValue(frame, b); + int cv = std::max(1, a + b + 1); + + if (b >= 1) + { + int cv2 = frame % cv; + if (cv2 >= a) + x10_bVal->GetValue(frame, valOut); + else + xc_aVal->GetValue(frame, valOut); + } + else + xc_aVal->GetValue(frame, valOut); + + return false; +} + + +bool CIEMultiply::GetValue(int frame, int& valOut) const +{ + int a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a * b; + return false; +} + +bool CIESampleAndHold::GetValue(int frame, int& valOut) const +{ + if (x8_nextSampleFrame < frame) + { + int b, c; + xc_waitFramesMin->GetValue(frame, b); + x10_waitFramesMax->GetValue(frame, c); + /* const-correctness, who needs it? */ + ((CIESampleAndHold*)this)->x8_nextSampleFrame = CRandom16::GetRandomNumber()->Range(b, c) + frame; + x4_sampleSource->GetValue(frame, valOut); + ((CIESampleAndHold*)this)->x14_holdVal = valOut; + } + else + valOut = x14_holdVal; + return false; +} + +bool CIERandom::GetValue(int frame, int& valOut) const +{ + int a, b; + x4_min->GetValue(frame, a); + x8_max->GetValue(frame, b); + if (frame > 0) + valOut = CRandom16::GetRandomNumber()->Range(a, b); + else + valOut = CRandom16::GetRandomNumber()->Next(); + return false; +} + +bool CIETimeScale::GetValue(int frame, int& valOut) const +{ + float a; + x4_a->GetValue(frame, a); + valOut = float(frame) * a; + return false; +} + +bool CIEGTCP::GetValue(int frame, int& valOut) const +{ + /* TODO: Do */ + return false; +} + +bool CIEModulo::GetValue(int frame, int& valOut) const +{ + int a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + if (b != 0) + valOut = a % b; + else + valOut = a; + return false; +} + +bool CIESubtract::GetValue(int frame, int& valOut) const +{ + int a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a - b; + return false; +} + +} diff --git a/Runtime/Particle/CIntElement.hpp b/Runtime/Particle/CIntElement.hpp index 6dee4a2f3..61bd45b4b 100644 --- a/Runtime/Particle/CIntElement.hpp +++ b/Runtime/Particle/CIntElement.hpp @@ -45,10 +45,10 @@ class CIETimeChain : public CIntElement { std::unique_ptr x4_a; std::unique_ptr x8_b; - std::unique_ptr xc_c; + std::unique_ptr xc_swFrame; public: CIETimeChain(CIntElement* a, CIntElement* b, CIntElement* c) - : x4_a(a), x8_b(b), xc_c(c) {} + : x4_a(a), x8_b(b), xc_swFrame(c) {} bool GetValue(int frame, int& valOut) const; }; @@ -81,10 +81,10 @@ public: class CIELifetimePercent : public CIntElement { - std::unique_ptr x4_a; + std::unique_ptr x4_percentVal; public: CIELifetimePercent(CIntElement* a) - : x4_a(a) {} + : x4_percentVal(a) {} bool GetValue(int frame, int& valOut) const; }; @@ -100,13 +100,13 @@ public: class CIEPulse : public CIntElement { - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_c; - std::unique_ptr x10_d; + std::unique_ptr x4_aDuration; + std::unique_ptr x8_bDuration; + std::unique_ptr xc_aVal; + std::unique_ptr x10_bVal; public: CIEPulse(CIntElement* a, CIntElement* b, CIntElement* c, CIntElement* d) - : x4_a(a), x8_b(b), xc_c(c), x10_d(d) {} + : x4_aDuration(a), x8_bDuration(b), xc_aVal(c), x10_bVal(d) {} bool GetValue(int frame, int& valOut) const; }; @@ -122,22 +122,24 @@ public: class CIESampleAndHold : public CIntElement { - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_c; + std::unique_ptr x4_sampleSource; + int x8_nextSampleFrame = 0; + std::unique_ptr xc_waitFramesMin; + std::unique_ptr x10_waitFramesMax; + int x14_holdVal; public: CIESampleAndHold(CIntElement* a, CIntElement* b, CIntElement* c) - : x4_a(a), x8_b(b), xc_c(c) {} + : x4_sampleSource(a), xc_waitFramesMin(b), x10_waitFramesMax(c) {} bool GetValue(int frame, int& valOut) const; }; class CIERandom : public CIntElement { - std::unique_ptr x4_a; - std::unique_ptr x8_b; + std::unique_ptr x4_min; + std::unique_ptr x8_max; public: CIERandom(CIntElement* a, CIntElement* b) - : x4_a(a), x8_b(b) {} + : x4_min(a), x8_max(b) {} bool GetValue(int frame, int& valOut) const; }; diff --git a/Runtime/Particle/CParticleDataFactory.cpp b/Runtime/Particle/CParticleDataFactory.cpp index 18e4d93d7..ab1d578f2 100644 --- a/Runtime/Particle/CParticleDataFactory.cpp +++ b/Runtime/Particle/CParticleDataFactory.cpp @@ -643,7 +643,7 @@ CRealElement* CParticleDataFactory::GetRealElement(CInputStream& in) { CIntElement* a = GetIntElement(in); CRealElement* b = GetRealElement(in); - return new CREITRL(a, b); + return new CREIntTimesReal(a, b); } default: break; } diff --git a/Runtime/Particle/CRealElement.cpp b/Runtime/Particle/CRealElement.cpp index 4990c80a1..041330d13 100644 --- a/Runtime/Particle/CRealElement.cpp +++ b/Runtime/Particle/CRealElement.cpp @@ -2,7 +2,6 @@ #include "CParticleGlobals.hpp" #include "CRandom16.hpp" #include -#include namespace Retro { @@ -53,7 +52,7 @@ bool CREKeyframeEmitter::GetValue(int frame, float& valOut) const if (ltPerc == 100) valOut = x18_keys[100]; else - valOut = x18_keys[ltPerc+1] * ltPercRem + (1.0f - ltPercRem) * x18_keys[ltPerc]; + valOut = ltPercRem * x18_keys[ltPerc+1] + (1.0f - ltPercRem) * x18_keys[ltPerc]; } return false; } @@ -307,7 +306,7 @@ bool CRECEXT::GetValue(int frame, float& valOut) const return false; } -bool CREITRL::GetValue(int frame, float& valOut) const +bool CREIntTimesReal::GetValue(int frame, float& valOut) const { int a; x4_a->GetValue(frame, a); diff --git a/Runtime/Particle/CRealElement.hpp b/Runtime/Particle/CRealElement.hpp index e9af25079..9207401d8 100644 --- a/Runtime/Particle/CRealElement.hpp +++ b/Runtime/Particle/CRealElement.hpp @@ -292,12 +292,12 @@ public: bool GetValue(int frame, float& valOut) const; }; -class CREITRL : public CRealElement +class CREIntTimesReal : public CRealElement { std::unique_ptr x4_a; std::unique_ptr x8_b; public: - CREITRL(CIntElement* a, CRealElement* b) + CREIntTimesReal(CIntElement* a, CRealElement* b) : x4_a(a), x8_b(b) {} bool GetValue(int frame, float& valOut) const; }; diff --git a/Runtime/Particle/CVectorElement.cpp b/Runtime/Particle/CVectorElement.cpp index e69de29bb..2751ff16c 100644 --- a/Runtime/Particle/CVectorElement.cpp +++ b/Runtime/Particle/CVectorElement.cpp @@ -0,0 +1,165 @@ +#include "CVectorElement.hpp" +#include "CParticleGlobals.hpp" +#include "CRandom16.hpp" +#include + +namespace Retro +{ + +CVEKeyframeEmitter::CVEKeyframeEmitter(CInputStream& in) +{ + x4_percent = in.readUint32Big(); + x8_unk1 = in.readUint32Big(); + xc_loop = in.readBool(); + xd_unk2 = in.readBool(); + x10_loopEnd = in.readUint32Big(); + x14_loopStart = in.readUint32Big(); + + u32 count = in.readUint32Big(); + x18_keys.reserve(count); + for (u32 i=0 ; i= x10_loopEnd) + { + int v1 = emitterTime - x14_loopStart; + int v2 = x10_loopEnd - x14_loopStart; + calcKey = v1 % v2; + calcKey += x14_loopStart; + } + } + else + { + int v1 = x10_loopEnd - 1; + if (v1 < emitterTime) + calcKey = v1; + } + valOut = x18_keys[calcKey]; + } + else + { + int ltPerc = CParticleGlobals::g_particleLifetimePercentTweenInt; + float ltPercRem = CParticleGlobals::g_particleLifetimePercentTweenIntFloatRem; + if (ltPerc == 100) + valOut = x18_keys[100]; + else + valOut = ltPercRem * x18_keys[ltPerc+1] + (1.0f - ltPercRem) * x18_keys[ltPerc]; + } + return false; +} + +CVECone::CVECone(CVectorElement* a, CRealElement* b) +: x4_a(a), x8_b(b) +{ + Zeus::CVector3f av; + x4_a->GetValue(0, av); + Zeus::CVector3f avNorm = av.normalized(); + if (avNorm[0] > 0.8) + xc_vec1 = av.cross(Zeus::CVector3f(0.f, 1.f, 0.f)); + else + xc_vec1 = av.cross(Zeus::CVector3f(1.f, 0.f, 0.f)); + x18_vec2 = avNorm.cross(xc_vec1); +} + +bool CVECone::GetValue(int frame, Zeus::CVector3f& valOut) const +{ + float b; + x8_b->GetValue(frame, b); + Zeus::CVector3f av; + x4_a->GetValue(0, av); + float b2 = std::min(1.f, b); + while (true) + { + float rand = CRandom16::GetRandomNumber()->Float() - 0.5f; + float c = 2.f * b2 * rand; + + + c = c * c; + + } +} + +bool CVEMultiply::GetValue(int frame, Zeus::CVector3f& valOut) const +{ + Zeus::CVector3f a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a * b; + return false; +} + +bool CVERealToVector::GetValue(int frame, Zeus::CVector3f& valOut) const +{ + float a; + x4_a->GetValue(frame, a); + valOut = Zeus::CVector3f(a); + return false; +} + +bool CVEPulse::GetValue(int frame, Zeus::CVector3f& valOut) const +{ + int a, b; + x4_aDuration->GetValue(frame, a); + x8_bDuration->GetValue(frame, b); + int cv = std::max(1, a + b + 1); + + if (b >= 1) + { + int cv2 = frame % cv; + if (cv2 >= a) + x10_bVal->GetValue(frame, valOut); + else + xc_aVal->GetValue(frame, valOut); + } + else + xc_aVal->GetValue(frame, valOut); + + return false; +} + +bool CVEParticleVelocity::GetValue(int frame, Zeus::CVector3f& valOut) const +{ + /* TODO: Do */ + return false; +} + +bool CVESPOS::GetValue(int frame, Zeus::CVector3f& valOut) const +{ + /* TODO: Do */ + return false; +} + +bool CVEPLCO::GetValue(int frame, Zeus::CVector3f& valOut) const +{ + /* TODO: Do */ + return false; +} + +bool CVEPLOC::GetValue(int frame, Zeus::CVector3f& valOut) const +{ + /* TODO: Do */ + return false; +} + +bool CVEPSOR::GetValue(int frame, Zeus::CVector3f& valOut) const +{ + /* TODO: Do */ + return false; +} + +bool CVEPSOF::GetValue(int frame, Zeus::CVector3f& valOut) const +{ + /* TODO: Do */ + return false; +} + +} diff --git a/Runtime/Particle/CVectorElement.hpp b/Runtime/Particle/CVectorElement.hpp index 8cda91b6f..cab765ec6 100644 --- a/Runtime/Particle/CVectorElement.hpp +++ b/Runtime/Particle/CVectorElement.hpp @@ -6,13 +6,28 @@ namespace Retro { +class CVEKeyframeEmitter : public CVectorElement +{ + u32 x4_percent; + u32 x8_unk1; + bool xc_loop; + bool xd_unk2; + u32 x10_loopEnd; + u32 x14_loopStart; + std::vector x18_keys; +public: + CVEKeyframeEmitter(CInputStream& in); + bool GetValue(int frame, Zeus::CVector3f& valOut) const; +}; + class CVECone : public CVectorElement { std::unique_ptr x4_a; std::unique_ptr x8_b; + Zeus::CVector3f xc_vec1; + Zeus::CVector3f x18_vec2; public: - CVECone(CVectorElement* a, CRealElement* b) - : x4_a(a), x8_b(b) {} + CVECone(CVectorElement* a, CRealElement* b); bool GetValue(int frame, Zeus::CVector3f& valOut) const; }; @@ -95,20 +110,6 @@ public: bool GetValue(int frame, Zeus::CVector3f& valOut) const; }; -class CVEKeyframeEmitter : public CVectorElement -{ - u32 x4_percent; - u32 x8_unk1; - bool xc_loop; - bool xd_unk2; - u32 x10_loopEnd; - u32 x14_loopStart; - std::vector x18_keys; -public: - CVEKeyframeEmitter(CInputStream& in); - bool GetValue(int frame, Zeus::CVector3f& valOut) const; -}; - class CVEMultiply : public CVectorElement { std::unique_ptr x4_a; @@ -130,13 +131,13 @@ public: class CVEPulse : public CVectorElement { - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_c; - std::unique_ptr x10_d; + std::unique_ptr x4_aDuration; + std::unique_ptr x8_bDuration; + std::unique_ptr xc_aVal; + std::unique_ptr x10_bVal; public: CVEPulse(CIntElement* a, CIntElement* b, CVectorElement* c, CVectorElement* d) - : x4_a(a), x8_b(b), xc_c(c), x10_d(d) {} + : x4_aDuration(a), x8_bDuration(b), xc_aVal(c), x10_bVal(d) {} bool GetValue(int frame, Zeus::CVector3f& valOut) const; };