#ifndef __URDE_CELEMENTGEN_HPP__ #define __URDE_CELEMENTGEN_HPP__ #include "RetroTypes.hpp" #include "zeus/CTransform.hpp" #include "zeus/CVector3f.hpp" #include "zeus/CColor.hpp" #include "zeus/CAABox.hpp" #include "CToken.hpp" #include "Graphics/CLight.hpp" #include "Graphics/CGraphics.hpp" #include "CRandom16.hpp" #include "CParticleGen.hpp" #include "CElementGenShaders.hpp" #include "Graphics/CLineRenderer.hpp" #include "Particle/CGenDescription.hpp" namespace urde { class CWarp; class CLight; class IGenDescription; class CGenDescription; class CParticleSwoosh; class CParticleElectric; class CElementGen : public CParticleGen { static CRandom16 g_GlobalSeed; public: static void SetGlobalSeed(u16 seed) { g_GlobalSeed.SetSeed(seed); } enum class EModelOrientationType { Normal, One }; enum class EOptionalSystemFlags { None, One, Two }; enum class LightType { None = 0, Custom = 1, Directional = 2, Spot = 3 }; class CParticleListItem { friend class CElementGen; s16 x0_partIdx; zeus::CVector3f x4_viewPoint; public: CParticleListItem(s16 idx) : x0_partIdx(idx) { ++g_ParticleAliveCount; } ~CParticleListItem() { --g_ParticleAliveCount; } }; struct CParticle { int x0_endFrame = 0; zeus::CVector3f x4_pos; zeus::CVector3f x10_prevPos; zeus::CVector3f x1c_vel; int x28_startFrame = 0; float x2c_lineLengthOrSize = 0.f; float x30_lineWidthOrRota = 0.f; zeus::CColor x34_color = {0.f, 0.f, 0.f, 1.f}; }; static CParticle* g_currentParticle; private: friend class CElementGenShaders; TLockedToken x1c_genDesc; EModelOrientationType x28_orientType; std::vector x30_particleLists; std::vector x60_parentMatrices; u32 x4c_internalStartFrame = 0; u32 x50_curFrame = 0; double x58_curSeconds = 0.f; float x60_timeDeltaScale; u32 x64_prevFrame = -1; bool x68_particleEmission = true; float x6c_generatorRemainder = 0.f; int x90_MAXP = 0; u16 x94_randomSeed = 99; float x78_generatorRate = 1.f; zeus::CVector3f x7c_translation; zeus::CVector3f x88_globalTranslation; zeus::CVector3f xf4_POFS; zeus::CVector3f xa0_globalScale = {1.f, 1.f, 1.f}; zeus::CTransform xac_globalScaleTransform = zeus::CTransform::Identity(); zeus::CTransform xdc_globalScaleTransformInverse = zeus::CTransform::Identity(); zeus::CVector3f x10c_localScale = {1.f, 1.f, 1.f}; zeus::CTransform x118_localScaleTransform = zeus::CTransform::Identity(); zeus::CTransform x148_localScaleTransformInverse = zeus::CTransform::Identity(); zeus::CTransform x178_orientation = zeus::CTransform::Identity(); zeus::CTransform x1a8_orientationInverse = zeus::CTransform::Identity(); zeus::CTransform x1d8_globalOrientation = zeus::CTransform::Identity(); u32 x208_activeParticleCount = 0; u32 x20c_recursiveParticleCount = 0; u32 x210_curEmitterFrame = 0; int x268_PSLT = 90;//0x7fffff; zeus::CVector3f x218_PSIV; bool x224_24_translationDirty = false; bool x224_25_LIT_; bool x224_26_AAPH; bool x224_27_ZBUF; bool x224_28_zTest = false; bool x224_29_MBLR; bool x224_30_VMD1; bool x224_31_VMD2; bool x225_24_VMD3; bool x225_25_VMD4; bool x225_28_warmedUp = false; bool x225_29_modelsUseLights = false; bool x226_enableOPTS; int x228_MBSP = 0; int m_maxMBSP = 0; union { struct { bool x26c_24_ : 1; bool x26c_31_LINE : 1; bool x26d_24_FXLL : 1; }; u32 _dummy = 0; }; ERglLightBits x22c_backupLightActive = ERglLightBits::None; CRandom16 x27c_randState; std::vector> x290_activePartChildren; int x2a0_CSSD = 0; std::vector> x248_finishPartChildren; int x2a4_SISY = 16; int x2a8_PISY = 16; u32 x260_cumulativeParticles = 0; /* Retail */ std::vector> x260_swhcChildren; int x2ac_SSSD = 0; zeus::CVector3f x2b0_SSPO; std::vector> x280_elscChildren; int x2bc_SESD = 0; zeus::CVector3f x2c0_SEPO; float x2a0 = 0.f; float x2a4 = 0.f; zeus::CVector3f x2a8_aabbMin; zeus::CVector3f x2b4_aabbMax; float x2c0_maxSize = 0.f; zeus::CAABox x2c4_systemBounds = zeus::CAABox::skInvertedBox; LightType x308_lightType; zeus::CColor x2e0_LCLR = zeus::CColor::skWhite; float x2e4_LINT = 1.f; zeus::CVector3f x2e8_LOFF; zeus::CVector3f x2f4_LDIR = {1.f, 0.f, 0.f}; EFalloffType x32c_falloffType = EFalloffType::Linear; float x304_LFOR = 1.f; float x308_LSLA = 45.f; zeus::CColor x30c_moduColor = {1.f, 1.f, 1.f, 1.f}; std::unique_ptr m_lineRenderer; CElementGenShaders::EShaderClass m_shaderClass; void AccumulateBounds(zeus::CVector3f& pos, float size); public: CElementGen(const TToken& gen, EModelOrientationType orientType, EOptionalSystemFlags flags); ~CElementGen(); boo::GraphicsDataToken m_gfxToken; boo::IShaderDataBinding* m_normalDataBind = nullptr; boo::IShaderDataBinding* m_redToAlphaDataBind = nullptr; boo::IGraphicsBufferD* m_instBuf = nullptr; boo::IGraphicsBufferD* m_uniformBuf = nullptr; CGenDescription* GetDesc() {return x1c_genDesc.GetObj();} static s32 g_FreeIndex; static bool g_StaticListInitialized; static int g_ParticleAliveCount; static int g_ParticleSystemAliveCount; static bool sMoveRedToAlphaBuffer; static void Initialize(); static void Shutdown(); void SetGeneratorRateScalar(float scalar) { if (scalar >= 0.0f) x78_generatorRate = scalar; else x78_generatorRate = 0.0f; for (std::unique_ptr& child : x290_activePartChildren) child->SetGeneratorRateScalar(x78_generatorRate); for (std::unique_ptr& child : x248_finishPartChildren) child->SetGeneratorRateScalar(x78_generatorRate); } void UpdateExistingParticles(); void CreateNewParticles(int); void UpdatePSTranslationAndOrientation(); void UpdateChildParticleSystems(double); CElementGen* ConstructChildParticleSystem(const TToken&); void UpdateLightParameters(); void BuildParticleSystemBounds(); u32 GetEmitterTime() const { /* Game returns x74, guessing x50 is what it's asking for */ return x50_curFrame; } u32 GetSystemCount(); u32 GetCumulativeParticleCount() const { return x260_cumulativeParticles; } u32 GetParticleCountAllInternal() const; u32 GetParticleCountAll() const {return x20c_recursiveParticleCount;} void EndLifetime(); void ForceParticleCreation(int amount); bool InternalUpdate(double); void RenderModels(); void RenderLines(); void RenderParticles(); void RenderParticlesIndirectTexture(); void Update(double); void Render(); void SetOrientation(const zeus::CTransform&); void SetTranslation(const zeus::CVector3f&); void SetGlobalOrientation(const zeus::CTransform&); void SetGlobalTranslation(const zeus::CVector3f&); void SetGlobalScale(const zeus::CVector3f&); void SetLocalScale(const zeus::CVector3f&); void SetParticleEmission(bool); void SetModulationColor(const zeus::CColor&); const zeus::CTransform& GetOrientation() const; const zeus::CVector3f& GetTranslation() const; const zeus::CTransform& GetGlobalOrientation() const; const zeus::CVector3f& GetGlobalTranslation() const; const zeus::CVector3f& GetGlobalScale() const; const zeus::CColor& GetModulationColor() const; bool IsSystemDeletable() const; rstl::optional_object GetBounds() const; u32 GetParticleCount() const; bool SystemHasLight() const; CLight GetLight() const; bool GetParticleEmission() const; void DestroyParticles(); void Reset(); size_t GetNumActiveChildParticles() const { return x290_activePartChildren.size(); } CElementGen& GetActiveChildParticle(size_t idx) const { return *x290_activePartChildren[idx]; } static void SetMoveRedToAlphaBuffer(bool); }; ENABLE_BITWISE_ENUM(CElementGen::EOptionalSystemFlags) } #endif // __URDE_CELEMENTGEN_HPP__