From fd4981295eeaf06abd6545135a173a5973e58bb9 Mon Sep 17 00:00:00 2001 From: Henrique Gemignani Passos Lima Date: Fri, 11 Nov 2022 02:26:17 +0200 Subject: [PATCH] Add nearly matched CHUDBillboardEffect Former-commit-id: b2cfeb8f1557f84e005c4d2043a9121d6b3dcbf0 --- .../ScriptObjects/CHUDBillboardEffect.s | 46 +++---- configure.py | 2 +- include/Kyoto/Particles/CElementGen.hpp | 1 + include/Kyoto/Particles/CParticleElectric.hpp | 47 +++++++ include/MetroidPrime/CWorld.hpp | 1 + include/MetroidPrime/Cameras/CGameCamera.hpp | 1 + .../ScriptObjects/CHUDBillboardEffect.hpp | 47 +++++++ .../ScriptObjects/CHUDBillboardEffect.cpp | 115 ++++++++++++++++++ 8 files changed, 236 insertions(+), 24 deletions(-) create mode 100644 include/Kyoto/Particles/CParticleElectric.hpp create mode 100644 include/MetroidPrime/ScriptObjects/CHUDBillboardEffect.hpp create mode 100644 src/MetroidPrime/ScriptObjects/CHUDBillboardEffect.cpp diff --git a/asm/MetroidPrime/ScriptObjects/CHUDBillboardEffect.s b/asm/MetroidPrime/ScriptObjects/CHUDBillboardEffect.s index 1f8aec01..2272c3cb 100644 --- a/asm/MetroidPrime/ScriptObjects/CHUDBillboardEffect.s +++ b/asm/MetroidPrime/ScriptObjects/CHUDBillboardEffect.s @@ -3,8 +3,8 @@ .section .data .balign 8 -.global lbl_803E0D70 -lbl_803E0D70: +.global __vt__19CHUDBillboardEffect +__vt__19CHUDBillboardEffect: # ROM: 0x3DDD70 .4byte 0 .4byte 0 @@ -53,11 +53,11 @@ lbl_805A76E8: .balign 8 # CHudBillboardEffect -.global lbl_805A8F70 -lbl_805A8F70: +.global g_BillboardCount__19CHUDBillboardEffect +g_BillboardCount__19CHUDBillboardEffect: .skip 0x4 -.global lbl_805A8F74 -lbl_805A8F74: +.global g_IndirectTexturedBillboardCount__19CHUDBillboardEffect +g_IndirectTexturedBillboardCount__19CHUDBillboardEffect: .skip 0x4 .global lbl_805A8F78 lbl_805A8F78: @@ -159,7 +159,7 @@ Think__19CHUDBillboardEffectFfR13CStateManager: /* 8012FB80 0012CAE0 4E 80 04 21 */ bctrl /* 8012FB84 0012CAE4 FF E0 08 90 */ fmr f31, f1 /* 8012FB88 0012CAE8 83 FD 00 E8 */ lwz r31, 0xe8(r29) -/* 8012FB8C 0012CAEC 48 00 06 D9 */ bl CalcGenRate__19CHudBillboardEffectFv +/* 8012FB8C 0012CAEC 48 00 06 D9 */ bl CalcGenRate__19CHUDBillboardEffectFv /* 8012FB90 0012CAF0 81 9F 00 00 */ lwz r12, 0(r31) /* 8012FB94 0012CAF4 EC 3F 00 72 */ fmuls f1, f31, f1 /* 8012FB98 0012CAF8 7F E3 FB 78 */ mr r3, r31 @@ -352,12 +352,12 @@ __dt__19CHUDBillboardEffectFv: /* 8012FE24 0012CD84 93 C1 00 08 */ stw r30, 8(r1) /* 8012FE28 0012CD88 7C 7E 1B 79 */ or. r30, r3, r3 /* 8012FE2C 0012CD8C 41 82 00 B0 */ beq lbl_8012FEDC -/* 8012FE30 0012CD90 3C 60 80 3E */ lis r3, lbl_803E0D70@ha -/* 8012FE34 0012CD94 38 03 0D 70 */ addi r0, r3, lbl_803E0D70@l +/* 8012FE30 0012CD90 3C 60 80 3E */ lis r3, __vt__19CHUDBillboardEffect@ha +/* 8012FE34 0012CD94 38 03 0D 70 */ addi r0, r3, __vt__19CHUDBillboardEffect@l /* 8012FE38 0012CD98 90 1E 00 00 */ stw r0, 0(r30) -/* 8012FE3C 0012CD9C 80 6D A3 B0 */ lwz r3, lbl_805A8F70@sda21(r13) +/* 8012FE3C 0012CD9C 80 6D A3 B0 */ lwz r3, g_BillboardCount__19CHUDBillboardEffect@sda21(r13) /* 8012FE40 0012CDA0 38 03 FF FF */ addi r0, r3, -1 -/* 8012FE44 0012CDA4 90 0D A3 B0 */ stw r0, lbl_805A8F70@sda21(r13) +/* 8012FE44 0012CDA4 90 0D A3 B0 */ stw r0, g_BillboardCount__19CHUDBillboardEffect@sda21(r13) /* 8012FE48 0012CDA8 80 7E 00 E8 */ lwz r3, 0xe8(r30) /* 8012FE4C 0012CDAC 81 83 00 00 */ lwz r12, 0(r3) /* 8012FE50 0012CDB0 81 8C 00 74 */ lwz r12, 0x74(r12) @@ -370,9 +370,9 @@ __dt__19CHUDBillboardEffectFv: /* 8012FE6C 0012CDCC 48 1E 77 D9 */ bl IsIndirectTextured__11CElementGenCFv /* 8012FE70 0012CDD0 54 60 06 3F */ clrlwi. r0, r3, 0x18 /* 8012FE74 0012CDD4 41 82 00 10 */ beq lbl_8012FE84 -/* 8012FE78 0012CDD8 80 6D A3 B4 */ lwz r3, lbl_805A8F74@sda21(r13) +/* 8012FE78 0012CDD8 80 6D A3 B4 */ lwz r3, g_IndirectTexturedBillboardCount__19CHUDBillboardEffect@sda21(r13) /* 8012FE7C 0012CDDC 38 03 FF FF */ addi r0, r3, -1 -/* 8012FE80 0012CDE0 90 0D A3 B4 */ stw r0, lbl_805A8F74@sda21(r13) +/* 8012FE80 0012CDE0 90 0D A3 B4 */ stw r0, g_IndirectTexturedBillboardCount__19CHUDBillboardEffect@sda21(r13) lbl_8012FE84: /* 8012FE84 0012CDE4 34 1E 00 E8 */ addic. r0, r30, 0xe8 /* 8012FE88 0012CDE8 41 82 00 24 */ beq lbl_8012FEAC @@ -466,9 +466,9 @@ lbl_8012FFBC: /* 8012FFC8 0012CF28 41 82 00 08 */ beq lbl_8012FFD0 /* 8012FFCC 0012CF2C 48 1E 59 65 */ bl Free__7CMemoryFPCv lbl_8012FFD0: -/* 8012FFD0 0012CF30 3C 60 80 3E */ lis r3, lbl_803E0D70@ha +/* 8012FFD0 0012CF30 3C 60 80 3E */ lis r3, __vt__19CHUDBillboardEffect@ha /* 8012FFD4 0012CF34 38 80 00 00 */ li r4, 0 -/* 8012FFD8 0012CF38 38 03 0D 70 */ addi r0, r3, lbl_803E0D70@l +/* 8012FFD8 0012CF38 38 03 0D 70 */ addi r0, r3, __vt__19CHUDBillboardEffect@l /* 8012FFDC 0012CF3C 38 60 00 01 */ li r3, 1 /* 8012FFE0 0012CF40 90 1F 00 00 */ stw r0, 0(r31) /* 8012FFE4 0012CF44 C0 02 99 40 */ lfs f0, lbl_805AB660@sda21(r2) @@ -550,9 +550,9 @@ lbl_80130104: /* 80130108 0012D068 48 1E 75 3D */ bl IsIndirectTextured__11CElementGenCFv /* 8013010C 0012D06C 54 60 06 3F */ clrlwi. r0, r3, 0x18 /* 80130110 0012D070 41 82 00 8C */ beq lbl_8013019C -/* 80130114 0012D074 80 6D A3 B4 */ lwz r3, lbl_805A8F74@sda21(r13) +/* 80130114 0012D074 80 6D A3 B4 */ lwz r3, g_IndirectTexturedBillboardCount__19CHUDBillboardEffect@sda21(r13) /* 80130118 0012D078 38 03 00 01 */ addi r0, r3, 1 -/* 8013011C 0012D07C 90 0D A3 B4 */ stw r0, lbl_805A8F74@sda21(r13) +/* 8013011C 0012D07C 90 0D A3 B4 */ stw r0, g_IndirectTexturedBillboardCount__19CHUDBillboardEffect@sda21(r13) /* 80130120 0012D080 48 00 00 7C */ b lbl_8013019C lbl_80130124: /* 80130124 0012D084 3C 60 80 3D */ lis r3, lbl_803D0048@ha @@ -588,10 +588,10 @@ lbl_80130184: /* 80130194 0012D0F4 38 80 00 00 */ li r4, 0 /* 80130198 0012D0F8 48 21 0C A9 */ bl __dt__6CTokenFv lbl_8013019C: -/* 8013019C 0012D0FC 80 6D A3 B0 */ lwz r3, lbl_805A8F70@sda21(r13) +/* 8013019C 0012D0FC 80 6D A3 B0 */ lwz r3, g_BillboardCount__19CHUDBillboardEffect@sda21(r13) /* 801301A0 0012D100 7F 84 E3 78 */ mr r4, r28 /* 801301A4 0012D104 38 03 00 01 */ addi r0, r3, 1 -/* 801301A8 0012D108 90 0D A3 B0 */ stw r0, lbl_805A8F70@sda21(r13) +/* 801301A8 0012D108 90 0D A3 B0 */ stw r0, g_BillboardCount__19CHUDBillboardEffect@sda21(r13) /* 801301AC 0012D10C 80 7F 00 E8 */ lwz r3, 0xe8(r31) /* 801301B0 0012D110 81 83 00 00 */ lwz r12, 0(r3) /* 801301B4 0012D114 81 8C 00 30 */ lwz r12, 0x30(r12) @@ -646,11 +646,11 @@ lbl_80130258: /* 8013025C 0012D1BC 38 63 C7 38 */ addi r3, r3, lbl_8046C738@l /* 80130260 0012D1C0 4E 80 00 20 */ blr -.global CalcGenRate__19CHudBillboardEffectFv -CalcGenRate__19CHudBillboardEffectFv: +.global CalcGenRate__19CHUDBillboardEffectFv +CalcGenRate__19CHUDBillboardEffectFv: /* 80130264 0012D1C4 94 21 FF E0 */ stwu r1, -0x20(r1) -/* 80130268 0012D1C8 80 AD A3 B0 */ lwz r5, lbl_805A8F70@sda21(r13) -/* 8013026C 0012D1CC 80 8D A3 B4 */ lwz r4, lbl_805A8F74@sda21(r13) +/* 80130268 0012D1C8 80 AD A3 B0 */ lwz r5, g_BillboardCount__19CHUDBillboardEffect@sda21(r13) +/* 8013026C 0012D1CC 80 8D A3 B4 */ lwz r4, g_IndirectTexturedBillboardCount__19CHUDBillboardEffect@sda21(r13) /* 80130270 0012D1D0 7C 05 22 14 */ add r0, r5, r4 /* 80130274 0012D1D4 2C 00 00 04 */ cmpwi r0, 4 /* 80130278 0012D1D8 41 81 00 0C */ bgt lbl_80130284 diff --git a/configure.py b/configure.py index ce0c4118..81702c79 100755 --- a/configure.py +++ b/configure.py @@ -180,7 +180,7 @@ LIBS = [ "MetroidPrime/CFluidPlane", "MetroidPrime/CFluidPlaneManager", ["MetroidPrime/ScriptObjects/CScriptGrapplePoint", True], - "MetroidPrime/ScriptObjects/CHUDBillboardEffect", + ["MetroidPrime/ScriptObjects/CHUDBillboardEffect", False], "MetroidPrime/Enemies/CFlickerBat", "MetroidPrime/BodyState/CBodyStateCmdMgr", ["MetroidPrime/BodyState/CBodyStateInfo", False], diff --git a/include/Kyoto/Particles/CElementGen.hpp b/include/Kyoto/Particles/CElementGen.hpp index d110b769..e29942c1 100644 --- a/include/Kyoto/Particles/CElementGen.hpp +++ b/include/Kyoto/Particles/CElementGen.hpp @@ -75,6 +75,7 @@ public: int GetEmitterTime() const; int GetCumulativeParticleCount() const { return x260_cumulativeParticles; } + bool IsIndirectTextured() const; // { return x28_loadedGenDesc->x54_x40_TEXR && x28_loadedGenDesc->x58_x44_TIND; } float GetExternalVar(int index) const; static void Initialize(); diff --git a/include/Kyoto/Particles/CParticleElectric.hpp b/include/Kyoto/Particles/CParticleElectric.hpp new file mode 100644 index 00000000..57bbed6a --- /dev/null +++ b/include/Kyoto/Particles/CParticleElectric.hpp @@ -0,0 +1,47 @@ +#ifndef _CPARTICLEELECTRIC +#define _CPARTICLEELECTRIC + +#include "Kyoto/Particles/CParticleGen.hpp" + +#include "Kyoto/TToken.hpp" + +class CElectricDescription; + +class CParticleElectric : public CParticleGen { +public: + explicit CParticleElectric(TToken desc); + + ~CParticleElectric() override; + void Update(double) override; + void Render() const override; + void SetOrientation(const CTransform4f& orientation) override; + void SetTranslation(const CVector3f& translation) override; + void SetGlobalOrientation(const CTransform4f& orientation) override; + void SetGlobalTranslation(const CVector3f& translation) override; + void SetGlobalScale(const CVector3f& scale) override; + void SetLocalScale(const CVector3f& scale) override; + void SetParticleEmission(bool emission) override; + void SetModulationColor(const CColor& col) override; + void SetGeneratorRate(float rate) {} + const CTransform4f& GetOrientation() const override; + const CVector3f& GetTranslation() const override; + CTransform4f GetGlobalOrientation() const override; + CVector3f GetGlobalTranslation() const override; + CVector3f GetGlobalScale() const override; + bool GetParticleEmission() const override; + CColor GetModulationColor() const override; + bool IsSystemDeletable() const override; + CAABox GetBounds() const override; + int GetParticleCount() const override; + bool SystemHasLight() const override; + CLight GetLight() override; + void DestroyParticles() override; + void AddModifier(CWarp*) override; + uint Get4CharId() const override; + +private: + uchar x4_pad[0x43c]; +}; +CHECK_SIZEOF(CParticleElectric, 0x458) + +#endif // _CPARTICLEELECTRIC diff --git a/include/MetroidPrime/CWorld.hpp b/include/MetroidPrime/CWorld.hpp index cae7fae0..f61ab47e 100644 --- a/include/MetroidPrime/CWorld.hpp +++ b/include/MetroidPrime/CWorld.hpp @@ -81,6 +81,7 @@ public: const CGameArea* GetArea(TAreaId id) const { return x18_areas[id.Value()].get(); } bool IsAreaValid(TAreaId id) const { return GetArea(id)->IsLoaded(); } CAssetId GetWorldAssetId() const { return x8_mlvlId; } + TAreaId GetCurrentAreaId() const { return x68_curAreaId; } TAreaId GetAreaIdForSaveId(int saveId) const; const rstl::vector< CRelay >& GetRelays() const { return x2c_relays; } diff --git a/include/MetroidPrime/Cameras/CGameCamera.hpp b/include/MetroidPrime/Cameras/CGameCamera.hpp index 64eed4dd..930dac58 100644 --- a/include/MetroidPrime/Cameras/CGameCamera.hpp +++ b/include/MetroidPrime/Cameras/CGameCamera.hpp @@ -29,6 +29,7 @@ public: TUniqueId GetWatchedObject() const { return xe8_watchedObject; } float GetFov() const { return x15c_currentFov; } void SetFov(float fov) { x15c_currentFov = fov; } + float GetNearClipDistance() const { return x160_znear; } void SetFovInterpolation(float start, float fov, float time, float delayTime); void UpdatePerspective(float dt); diff --git a/include/MetroidPrime/ScriptObjects/CHUDBillboardEffect.hpp b/include/MetroidPrime/ScriptObjects/CHUDBillboardEffect.hpp new file mode 100644 index 00000000..a7c52b63 --- /dev/null +++ b/include/MetroidPrime/ScriptObjects/CHUDBillboardEffect.hpp @@ -0,0 +1,47 @@ +#ifndef _CHUDBILLBOARDEFFECT +#define _CHUDBILLBOARDEFFECT + +#include "MetroidPrime/CEffect.hpp" + +class CGenDescription ; +class CElectricDescription; +class CParticleGen; + +class CHUDBillboardEffect : public CEffect { +public: + CHUDBillboardEffect(const rstl::optional_object< TToken< CGenDescription > >& particle, + const rstl::optional_object< TToken< CElectricDescription > >& electric, + TUniqueId uid, bool active, const rstl::string& name, float dist, + const CVector3f& scale0, const CColor& color, const CVector3f& scale1, + const CVector3f& translation); + ~CHUDBillboardEffect() override; + + void Accept(IVisitor& visitor) override; + void Think(float dt, CStateManager& mgr) override; + void PreRender(CStateManager& mgr, const CFrustumPlanes& frustum) override; + void AddToRenderer(const CFrustumPlanes& frustum, const CStateManager& mgr) const override; + void Render(const CStateManager& mgr) const override; + bool IsElementGen() const { return x104_26_isElementGen; } + void SetRunIndefinitely(bool b) { x104_27_runIndefinitely = b; } + CParticleGen* GetParticleGen() const { return xe8_generator.get(); } + + static float GetNearClipDistance(const CStateManager& mgr); + static const CVector3f& GetScaleForPOV(const CStateManager& mgr); + +private: + rstl::single_ptr< CParticleGen > xe8_generator; + CVector3f xec_translation; + CVector3f xf8_localScale; + bool x104_24_renderAsParticleGen : 1l; // = true; + bool x104_25_enableRender : 1l; // = false; + bool x104_26_isElementGen : 1l; // = false; + bool x104_27_runIndefinitely : 1l; // = false; + float x108_timeoutTimer; // = 0.f; + + static int g_IndirectTexturedBillboardCount; + static int g_BillboardCount; + + static float CalcGenRate(); +}; + +#endif // _CHUDBILLBOARDEFFECT diff --git a/src/MetroidPrime/ScriptObjects/CHUDBillboardEffect.cpp b/src/MetroidPrime/ScriptObjects/CHUDBillboardEffect.cpp new file mode 100644 index 00000000..65dc42a7 --- /dev/null +++ b/src/MetroidPrime/ScriptObjects/CHUDBillboardEffect.cpp @@ -0,0 +1,115 @@ +#include "MetroidPrime/ScriptObjects/CHUDBillboardEffect.hpp" + +#include "MetroidPrime/CStateManager.hpp" +#include "MetroidPrime/CWorld.hpp" +#include "MetroidPrime/Cameras/CCameraManager.hpp" +#include "MetroidPrime/Cameras/CGameCamera.hpp" +#include "MetroidPrime/Player/CPlayer.hpp" + +#include "MetaRender/CCubeRenderer.hpp" + +#include "Kyoto/Particles/CElementGen.hpp" +#include "Kyoto/Particles/CParticleElectric.hpp" + +#include "rstl/math.hpp" + +int CHUDBillboardEffect::g_BillboardCount = 0; +int CHUDBillboardEffect::g_IndirectTexturedBillboardCount = 0; + +float CHUDBillboardEffect::CalcGenRate() { + float f1 = (g_BillboardCount + g_IndirectTexturedBillboardCount <= 4) + ? 0.f + : g_BillboardCount * 0.2f + g_IndirectTexturedBillboardCount * 0.1f; + return 1.f - rstl::min_val(0.8f, f1); +} + +const CVector3f& CHUDBillboardEffect::GetScaleForPOV(const CStateManager& mgr) { + static CVector3f result(0.155f, 1.f, 0.155f); + return result; +} + +float CHUDBillboardEffect::GetNearClipDistance(const CStateManager& mgr) { + return mgr.GetCameraManager()->GetCurrentCamera(mgr).GetNearClipDistance() + 0.01f; +} + +CHUDBillboardEffect::CHUDBillboardEffect( + const rstl::optional_object< TToken< CGenDescription > >& particle, + const rstl::optional_object< TToken< CElectricDescription > >& electric, TUniqueId uid, + bool active, const rstl::string& name, float dist, const CVector3f& scale0, const CColor& color, + const CVector3f& scale1, const CVector3f& translation) +: CEffect(uid, CEntityInfo(kInvalidAreaId, CEntity::NullConnectionList), active, name, + CTransform4f::Identity()) + +, xec_translation(translation.GetX(), translation.GetY() + dist, translation.GetZ()) +, xf8_localScale(CVector3f::ByElementMultiply(scale1, scale0)) +, x104_24_renderAsParticleGen(true) +, x104_25_enableRender(false) +, x104_26_isElementGen(false) +, x104_27_runIndefinitely(false) +, x108_timeoutTimer(0.f) { + + if (particle) { + x104_26_isElementGen = true; + xe8_generator = new CElementGen(*particle); + if (static_cast< CElementGen& >(*xe8_generator).IsIndirectTextured()) + ++g_IndirectTexturedBillboardCount; + } else { + xe8_generator = new CParticleElectric(TToken< CElectricDescription >(*electric)); + } + ++g_BillboardCount; + xe8_generator->SetModulationColor(color); + xe8_generator->SetLocalScale(xf8_localScale); +} + +CHUDBillboardEffect::~CHUDBillboardEffect() { + --g_BillboardCount; + if (xe8_generator->Get4CharId() == 'PART') + if (static_cast< CElementGen& >(*xe8_generator).IsIndirectTextured()) + --g_IndirectTexturedBillboardCount; +} + +void CHUDBillboardEffect::AddToRenderer(const CFrustumPlanes& frustum, + const CStateManager& mgr) const { + if (x104_25_enableRender && x104_24_renderAsParticleGen) { + gpRender->AddParticleGen(*xe8_generator); + } +} + +void CHUDBillboardEffect::PreRender(CStateManager& mgr, const CFrustumPlanes& frustum) { + if (mgr.GetPlayer()->GetCameraState() == CPlayer::kCS_FirstPerson) { + CTransform4f camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + xe8_generator->SetGlobalTranslation(camXf * xec_translation); + xe8_generator->SetGlobalOrientation(camXf); + x104_25_enableRender = true; + } else { + x104_25_enableRender = false; + } + x104_24_renderAsParticleGen = !mgr.RenderLast(GetUniqueId()); +} + +void CHUDBillboardEffect::Render(const CStateManager& mgr) const { + if (x104_25_enableRender && !x104_24_renderAsParticleGen) { + xe8_generator->Render(); + } +} + +void CHUDBillboardEffect::Think(float dt, CStateManager& mgr) { + if (GetActive()) { + mgr.SetActorAreaId(*this, mgr.GetWorld()->GetCurrentAreaId()); + float oldGenRate = xe8_generator->GetGeneratorRate(); + xe8_generator->SetGeneratorRate(oldGenRate * CalcGenRate()); + xe8_generator->Update(dt); + xe8_generator->SetGeneratorRate(oldGenRate); + if (!x104_27_runIndefinitely) { + x108_timeoutTimer += dt; + if (x108_timeoutTimer > 30.f) { + mgr.FreeScriptObject(GetUniqueId()); + return; + } + } + if (xe8_generator->IsSystemDeletable()) + mgr.FreeScriptObject(GetUniqueId()); + } +} + +void CHUDBillboardEffect::Accept(IVisitor& visitor) { visitor.Visit(*this); }