diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c3f672c5..dd82ae9f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,11 +61,12 @@ Metaforce -> decomp - `std::max` -> `rstl::max_val` - `std::clamp` -> `CMath::Clamp` (depends on context) -### Converting Vector / Transforms +### Converting globals and getters Metaforce -> decomp - `zeus::CTransform::frontVector()` -> `CTransform4f::GetForward()` - `zeus::skForward` -> `CVector3f::Forward` +- `g_Renderer` -> `gpRender` ### Class definitions & constructors diff --git a/include/MetaRender/CCubeRenderer.hpp b/include/MetaRender/CCubeRenderer.hpp index cfcf5aec..3e595c0c 100644 --- a/include/MetaRender/CCubeRenderer.hpp +++ b/include/MetaRender/CCubeRenderer.hpp @@ -88,6 +88,9 @@ public: virtual void SetWorldLightFadeLevel(); virtual void Something(); virtual void PrepareDynamicLights(); + + + void AllocatePhazonSuitMaskTexture(); }; extern CCubeRenderer* gpRender; diff --git a/include/MetroidPrime/CActorLights.hpp b/include/MetroidPrime/CActorLights.hpp index 94ec4dc3..e7425ac1 100644 --- a/include/MetroidPrime/CActorLights.hpp +++ b/include/MetroidPrime/CActorLights.hpp @@ -22,10 +22,16 @@ public: ~CActorLights(); void BuildConstantAmbientLighting(); + void BuildConstantAmbientLighting(const CColor&); bool BuildAreaLightList(const CStateManager& mgr, const CGameArea& area, const CAABox& bounds); void BuildDynamicLightList(const CStateManager& mgr, const CAABox& bounds); bool GetNeedsRelight() const { return x298_24_dirty == TRUE; } + bool HasShadowLight() const { return x29c_shadowLightArrIdx != -1; } + s32 GetShadowLightIndex() const { return x2a0_shadowLightIdx; } + + void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; } + void SetShadowDynamicRangeThreshold(float t) { x2d0_shadowDynamicRangeThreshold = t; } private: rstl::reserved_vector< CLight, 4 > x0_areaLights; diff --git a/include/MetroidPrime/CStateManager.hpp b/include/MetroidPrime/CStateManager.hpp index e981a641..d73213ed 100644 --- a/include/MetroidPrime/CStateManager.hpp +++ b/include/MetroidPrime/CStateManager.hpp @@ -120,6 +120,9 @@ public: TUniqueId GetIdForScript(TEditorId eid) const; TIdListResult GetIdListForScript(TEditorId) const; + TAreaId GetNextAreaId() const { return x8cc_nextAreaId; } + void SetCurrentAreaId(TAreaId); + CMazeState* CurrentMaze(); const CMazeState* GetCurrentMaze() const; void SetCurrentMaze(rstl::single_ptr< CMazeState > maze); diff --git a/include/MetroidPrime/CWorldShadow.hpp b/include/MetroidPrime/CWorldShadow.hpp index a50c9e14..91dc6d39 100644 --- a/include/MetroidPrime/CWorldShadow.hpp +++ b/include/MetroidPrime/CWorldShadow.hpp @@ -24,6 +24,12 @@ class CWorldShadow { public: CWorldShadow(uint w, uint h, bool rgba8); ~CWorldShadow(); + + void EnableModelProjectedShadow(const CTransform4f& pos, uint lightIdx, float f1); + void DisableModelProjectedShadow(); + void BuildLightShadowTexture(const CStateManager& mgr, TAreaId aid, uint lightIdx, const CAABox& aabb, + bool motionBlur, bool lighten); + void ResetBlur(); }; CHECK_SIZEOF(CWorldShadow, 0x8c) diff --git a/include/MetroidPrime/Player/CGrappleArm.hpp b/include/MetroidPrime/Player/CGrappleArm.hpp index 8d22ec1f..7457a144 100644 --- a/include/MetroidPrime/Player/CGrappleArm.hpp +++ b/include/MetroidPrime/Player/CGrappleArm.hpp @@ -10,8 +10,19 @@ public: CGrappleArm(const CVector3f& scale); ~CGrappleArm(); + void PreRender(CStateManager& mgr, const CFrustumPlanes& frustum, const CVector3f& camPos); + + bool GetActive() const { return x3b2_24_active; } + private: - u8 x0_pad[0x3b4]; + u8 x0_pad[0x3b0]; + s16 x3b0_rumbleHandle; + bool x3b2_24_active : 1; + bool x3b2_25_beamActive : 1; + bool x3b2_26_grappleHit : 1; + bool x3b2_27_armMoving : 1; + bool x3b2_28_isGrappling : 1; + bool x3b2_29_suitLoading : 1; }; CHECK_SIZEOF(CGrappleArm, 0x3b4) diff --git a/include/MetroidPrime/Player/CPlayerGun.hpp b/include/MetroidPrime/Player/CPlayerGun.hpp index 0338950c..2736e5e4 100644 --- a/include/MetroidPrime/Player/CPlayerGun.hpp +++ b/include/MetroidPrime/Player/CPlayerGun.hpp @@ -95,6 +95,9 @@ public: CPlayerGun(TUniqueId); ~CPlayerGun(); + void AddToRenderer(const CFrustumPlanes& frustum, const CStateManager& mgr) const; + void PreRender(CStateManager&, const CFrustumPlanes&, const CVector3f&); + void InitBeamData(); void InitBombData(); void InitMuzzleData(); diff --git a/include/MetroidPrime/Weapons/CGunWeapon.hpp b/include/MetroidPrime/Weapons/CGunWeapon.hpp index 897f97cc..0facca31 100644 --- a/include/MetroidPrime/Weapons/CGunWeapon.hpp +++ b/include/MetroidPrime/Weapons/CGunWeapon.hpp @@ -5,6 +5,7 @@ #include "types.h" #include "MetroidPrime/Player/CPlayerState.hpp" +#include "MetroidPrime/Weapons/WeaponCommon.hpp" #include "MetroidPrime/Weapons/WeaponTypes.hpp" #include "Kyoto/Math/CVector3f.hpp" @@ -59,6 +60,29 @@ public: kFFT_Thawed, }; + // Virtual Methods + virtual void Reset(CStateManager& mgr); + virtual void PlayAnim(NWeaponTypes::EGunAnimType type, bool loop); + virtual void PreRenderGunFx(const CStateManager& mgr, const CTransform4f& xf); + virtual void PostRenderGunFx(const CStateManager& mgr, const CTransform4f& xf); + virtual void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const CTransform4f& xf); + virtual void Fire(bool underwater, float dt, EChargeState chargeState, const CTransform4f& xf, CStateManager& mgr, + TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); + virtual void EnableFx(bool enable); + virtual void EnableSecondaryFx(ESecondaryFxType type); + virtual void Draw(bool drawSuitArm, const CStateManager& mgr, const CTransform4f& xf, const CModelFlags& flags, + const CActorLights* lights); + virtual void DrawMuzzleFx(const CStateManager& mgr) const; + virtual void Update(float dt, CStateManager& mgr); + virtual void Load(CStateManager& mgr, bool subtypeBasePose); + virtual void Unload(CStateManager& mgr); + virtual bool IsLoaded() const; + + rstl::optional_object< CModelData >& SolidModelData() { return x10_solidModelData; } + + CAABox GetBounds() const; + CAABox GetBounds(const CTransform4f& xf) const; + private: // x0 is vtable CVector3f x4_scale; diff --git a/include/MetroidPrime/Weapons/CIceBeam.hpp b/include/MetroidPrime/Weapons/CIceBeam.hpp index ec6b6c49..6bfef51a 100644 --- a/include/MetroidPrime/Weapons/CIceBeam.hpp +++ b/include/MetroidPrime/Weapons/CIceBeam.hpp @@ -7,7 +7,7 @@ class CIceBeam : public CGunWeapon { public: CIceBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, const CVector3f& scale); - + ~CIceBeam(); private: u8 x21c_pad[0x30]; }; diff --git a/include/MetroidPrime/Weapons/CPhazonBeam.hpp b/include/MetroidPrime/Weapons/CPhazonBeam.hpp index e0386f04..a124fbf3 100644 --- a/include/MetroidPrime/Weapons/CPhazonBeam.hpp +++ b/include/MetroidPrime/Weapons/CPhazonBeam.hpp @@ -7,7 +7,7 @@ class CPhazonBeam : public CGunWeapon { public: CPhazonBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, const CVector3f& scale); - + ~CPhazonBeam(); private: u8 x21c_pad[0x60]; }; diff --git a/include/MetroidPrime/Weapons/CPlasmaBeam.hpp b/include/MetroidPrime/Weapons/CPlasmaBeam.hpp index b57a7c3a..00e692ce 100644 --- a/include/MetroidPrime/Weapons/CPlasmaBeam.hpp +++ b/include/MetroidPrime/Weapons/CPlasmaBeam.hpp @@ -7,7 +7,7 @@ class CPlasmaBeam : public CGunWeapon { public: CPlasmaBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, const CVector3f& scale); - + ~CPlasmaBeam(); private: u8 x21c_pad[0x24]; }; diff --git a/include/MetroidPrime/Weapons/CPowerBeam.hpp b/include/MetroidPrime/Weapons/CPowerBeam.hpp index 4029c960..2ba92856 100644 --- a/include/MetroidPrime/Weapons/CPowerBeam.hpp +++ b/include/MetroidPrime/Weapons/CPowerBeam.hpp @@ -7,6 +7,7 @@ class CPowerBeam : public CGunWeapon { public: CPowerBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, const CVector3f& scale); + ~CPowerBeam(); private: u8 x21c_pad[0x2C]; diff --git a/include/MetroidPrime/Weapons/CWaveBeam.hpp b/include/MetroidPrime/Weapons/CWaveBeam.hpp index 63e5367b..090d2838 100644 --- a/include/MetroidPrime/Weapons/CWaveBeam.hpp +++ b/include/MetroidPrime/Weapons/CWaveBeam.hpp @@ -7,7 +7,7 @@ class CWaveBeam : public CGunWeapon { public: CWaveBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, const CVector3f& scale); - + ~CWaveBeam(); private: u8 x21c_pad[0x40]; }; diff --git a/include/MetroidPrime/Weapons/WeaponCommon.hpp b/include/MetroidPrime/Weapons/WeaponCommon.hpp new file mode 100644 index 00000000..bf9e0bb8 --- /dev/null +++ b/include/MetroidPrime/Weapons/WeaponCommon.hpp @@ -0,0 +1,22 @@ +#ifndef _WEAPONCOMMON_HPP +#define _WEAPONCOMMON_HPP + +namespace NWeaponTypes { + +enum EGunAnimType { + kGAT_BasePosition, + kGAT_Shoot, + kGAT_ChargeUp, + kGAT_ChargeLoop, + kGAT_ChargeShoot, + kGAT_FromMissile, + kGAT_ToMissile, + kGAT_MissileShoot, + kGAT_MissileReload, + kGAT_FromBeam, + kGAT_ToBeam +}; + +} + +#endif _WEAPONCOMMON_HPP diff --git a/src/MetroidPrime/Player/CPlayerGun.cpp b/src/MetroidPrime/Player/CPlayerGun.cpp index 0dc57b45..191b8dbb 100644 --- a/src/MetroidPrime/Player/CPlayerGun.cpp +++ b/src/MetroidPrime/Player/CPlayerGun.cpp @@ -1,8 +1,11 @@ #include "MetroidPrime/Player/CPlayerGun.hpp" +#include "MetroidPrime/CAnimData.hpp" #include "MetroidPrime/CAnimRes.hpp" #include "MetroidPrime/CRainSplashGenerator.hpp" #include "MetroidPrime/CWorldShadow.hpp" +#include "MetroidPrime/CStateManager.hpp" +#include "MetroidPrime/CWorld.hpp" #include "MetroidPrime/Player/CGrappleArm.hpp" #include "MetroidPrime/Tweaks/CTweakGunRes.hpp" #include "MetroidPrime/Tweaks/CTweakPlayerGun.hpp" @@ -15,12 +18,15 @@ #include "MetroidPrime/Weapons/GunController/CGunMotion.hpp" #include "MetroidPrime/Weapons/WeaponTypes.hpp" +#include "Kyoto/Math/CMath.hpp" #include "Kyoto/Graphics/CModelFlags.hpp" #include "Kyoto/Particles/CElementGen.hpp" #include "Collision/CMaterialFilter.hpp" #include "Collision/CMaterialList.hpp" +#include "MetaRender/CCubeRenderer.hpp" + static float kVerticalAngleTable[3] = {-30.f, 0.f, 30.f}; static float kHorizontalAngleTable[3] = {30.f, 30.f, 30.f}; static float kVerticalVarianceTable[3] = {30.f, 30.f, 30.f}; @@ -275,3 +281,53 @@ CPlayerGun::CPlayerGun(TUniqueId playerId) } CPlayerGun::~CPlayerGun() {} + +void CPlayerGun::AddToRenderer(const CFrustumPlanes& frustum, const CStateManager&) const { + rstl::optional_object< CModelData >& model = x72c_currentBeam->SolidModelData(); + if (model) + model->RenderParticles(frustum); +} + +void CPlayerGun::PreRender(CStateManager& mgr, const CFrustumPlanes& frustum, const CVector3f& camPos) { + const CPlayerState& playerState = *mgr.GetPlayerState(); + if (playerState.GetCurrentVisor() == CPlayerState::kPV_Scan) + return; + + CPlayerState::EPlayerVisor activeVisor = playerState.GetActiveVisor(mgr); + switch (activeVisor) { + case CPlayerState::kPV_Thermal: + float rgb = CMath::Clamp(0.6f, 0.5f * x380_shotSmokeTimer + 0.6f - x378_shotSmokeStartTimer, 1.f); + x0_lights.BuildConstantAmbientLighting(CColor(rgb, rgb, rgb, 1.f)); + break; + + case CPlayerState::kPV_Combat: { + CAABox aabb = x72c_currentBeam->GetBounds(CTransform4f::Translate(camPos) * x4a8_gunWorldXf); + if (mgr.GetNextAreaId() != kInvalidAreaId) { + x0_lights.SetFindShadowLight(true); + x0_lights.SetShadowDynamicRangeThreshold(0.25f); + x0_lights.BuildAreaLightList(mgr, mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()), aabb); + } + x0_lights.BuildDynamicLightList(mgr, aabb); + if (x0_lights.HasShadowLight()) { + if (x72c_currentBeam->IsLoaded()) { + x82c_shadow->BuildLightShadowTexture(mgr, mgr.GetNextAreaId(), x0_lights.GetShadowLightIndex(), aabb, true, + false); + } + } else { + x82c_shadow->ResetBlur(); + } + break; + } + default: + break; + } + + if (x740_grappleArm->GetActive()) + x740_grappleArm->PreRender(mgr, frustum, camPos); + + if (x678_morph.GetGunState() != CGunMorph::kGS_OutWipeDone || activeVisor == CPlayerState::kPV_XRay) + x6e0_rightHandModel.AnimationData()->PreRender(); + + if (x833_28_phazonBeamActive) + gpRender->AllocatePhazonSuitMaskTexture(); +}