Add CSimpleShadow

Former-commit-id: 19877f6fa2
This commit is contained in:
Henrique Gemignani Passos Lima 2022-11-17 06:56:21 +02:00
parent e99cd889cc
commit 70202ae4ba
13 changed files with 167 additions and 13 deletions

View File

@ -191,8 +191,8 @@ GetBounds__13CSimpleShadowCFv:
/* 80105CE8 00102C48 38 21 00 30 */ addi r1, r1, 0x30
/* 80105CEC 00102C4C 4E 80 00 20 */ blr
.global sub_80105cf0
sub_80105cf0:
.global SetAlwaysCalculateRadius__13CSimpleShadowFb
SetAlwaysCalculateRadius__13CSimpleShadowFb:
/* 80105CF0 00102C50 88 03 00 48 */ lbz r0, 0x48(r3)
/* 80105CF4 00102C54 50 80 36 72 */ rlwimi r0, r4, 6, 0x19, 0x19
/* 80105CF8 00102C58 98 03 00 48 */ stb r0, 0x48(r3)

View File

@ -2251,7 +2251,7 @@ lbl_800A2DE4:
/* 800A30C0 000A0020 4B FA FC AD */ bl CreateShadow__6CActorFb
/* 800A30C4 000A0024 80 7F 00 94 */ lwz r3, 0x94(r31)
/* 800A30C8 000A0028 38 80 00 00 */ li r4, 0
/* 800A30CC 000A002C 48 06 2C 25 */ bl sub_80105cf0
/* 800A30CC 000A002C 48 06 2C 25 */ bl SetAlwaysCalculateRadius__13CSimpleShadowFb
lbl_800A30D0:
/* 800A30D0 000A0030 80 9F 00 90 */ lwz r4, 0x90(r31)
/* 800A30D4 000A0034 28 04 00 00 */ cmplwi r4, 0

View File

@ -625,7 +625,7 @@ sub_801ad790:
/* 801AD7E0 001AA740 4B EA 55 8D */ bl CreateShadow__6CActorFb
/* 801AD7E4 001AA744 80 7F 00 94 */ lwz r3, 0x94(r31)
/* 801AD7E8 001AA748 38 80 00 00 */ li r4, 0
/* 801AD7EC 001AA74C 4B F5 85 05 */ bl sub_80105cf0
/* 801AD7EC 001AA74C 4B F5 85 05 */ bl SetAlwaysCalculateRadius__13CSimpleShadowFb
/* 801AD7F0 001AA750 7F E3 FB 78 */ mr r3, r31
/* 801AD7F4 001AA754 38 80 00 02 */ li r4, 2
/* 801AD7F8 001AA758 4B EC F9 19 */ bl BuildBodyController__10CPatternedF9EBodyType

View File

@ -156,7 +156,7 @@ LIBS = [
["MetroidPrime/CDamageVulnerability", False],
"MetroidPrime/CActorLights",
["MetroidPrime/Enemies/CPatternedInfo", True],
"MetroidPrime/CSimpleShadow",
["MetroidPrime/CSimpleShadow", False],
["MetroidPrime/CActorParameters", False],
"MetroidPrime/CInGameGuiManager",
"MetroidPrime/Enemies/CWarWasp",

View File

@ -31,6 +31,8 @@ public:
return CMaterialFilter(include, exclude, kFT_IncludeExclude);
}
static const CMaterialFilter& GetPassEverything() { return skPassEverything; }
bool Passes(const CMaterialList& other) const;
private:

View File

@ -20,6 +20,7 @@ public:
// TODO: figure out what's going on here
bool IsInvalid() const { return x20_valid == kI_Invalid; }
// GetPlane__14CRayCastResultCFv
const CPlane& GetPlane() const { return x10_plane; }
const CVector3f& GetPoint() const { return x4_point; }
// GetMaterial__14CRayCastResultCFv
// Transform__14CRayCastResultFRC12CTransform4f

View File

@ -135,6 +135,7 @@ public:
static void EndScene();
static void SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass);
static void StreamBegin(ERglPrimitive primitive);
static void StreamColor(uint color);
static void StreamColor(const CColor& color);
static void StreamTexcoord(float u, float v);
static void StreamVertex(float, float, float);

View File

@ -96,7 +96,5 @@ public:
};
extern CTevCombiners::CTevPass CTevPass_805a5ebc;
// TODO move to CGraphics
extern CTevCombiners::CTevPass* PTR_skPassThru_805a8828;
#endif // _CTEVCOMBINERS

View File

@ -3,6 +3,8 @@
#include "types.h"
#include "MetroidPrime/CStateManager.hpp"
class CAreaCollisionCache;
class CCollisionInfo;
class CCollisionPrimitive;
@ -30,6 +32,9 @@ public:
TUniqueId&, CCollisionInfo&, double&);
static CRayCastResult RayStaticIntersection(const CStateManager&, const CVector3f&,
const CVector3f&, float, const CMaterialFilter&);
static CRayCastResult RayDynamicIntersection(const CStateManager& mgr, TUniqueId& idOut, const CVector3f& pos,
const CVector3f& dir, float mag, const CMaterialFilter& filter,
const TEntityList& nearList);
static void Move(CStateManager& mgr, CPhysicsActor& actor, float dt, const TEntityList*);
};

View File

@ -3,20 +3,39 @@
#include "types.h"
#include "Kyoto/Math/CTransform4f.hpp"
#include "Kyoto/TToken.hpp"
class CAABox;
class CStateManager;
class CTransform4f;
class CTexture;
class CSimpleShadow {
public:
CAABox GetBounds() const;
const CTransform4f& GetTransform() const;
CAABox GetMaxShadowBox(const CAABox& bounds) const;
CSimpleShadow(float scale, float userAlpha, float maxObjHeight, float displacement);
void Calculate(const CAABox& bounds, const CTransform4f& xf, const CStateManager& mgr);
void Render(const CTexture* tex) const;
const CTransform4f& GetTransform() const;
void SetUserAlpha(float);
float GetMaxObjectHeight() const;
void SetAlwaysCalculateRadius(bool);
CAABox GetBounds() const;
CAABox GetMaxShadowBox(const CAABox& bounds) const;
bool Valid() const;
private:
// TODO
CTransform4f x0_xf;
float x30_scale;
float x34_radius;
float x38_userAlpha;
float x3c_heightAlpha;
float x40_maxObjHeight;
float x44_displacement;
bool x48_24_collision : 1;
bool x48_25_alwaysCalculateRadius : 1;
bool x48_26_radiusCalculated : 1;
};
#endif // _CSIMPLESHADOW

View File

@ -139,6 +139,9 @@ public:
const CActor*) const;
bool RayCollideWorld(const CVector3f& start, const CVector3f& end, const TEntityList& nearList,
const CMaterialFilter& filter, const CActor* damagee) const;
CRayCastResult RayStaticIntersection(const CVector3f& pos, const CVector3f& dir, float length,
const CMaterialFilter& filter) const;
CRayCastResult RayWorldIntersection(TUniqueId& idOut, const CVector3f& pos, const CVector3f& dir,
float length, const CMaterialFilter& filter,
const TEntityList& list) const;

View File

@ -0,0 +1,125 @@
#include "MetroidPrime/CSimpleShadow.hpp"
#include "MetroidPrime/CGameCollision.hpp"
#include "MetroidPrime/CStateManager.hpp"
#include "Collision/CMaterialFilter.hpp"
#include "Collision/CRayCastResult.hpp"
#include "MetaRender/CCubeRenderer.hpp"
#include "Kyoto/Graphics/CColor.hpp"
#include "Kyoto/Graphics/CGraphics.hpp"
#include "Kyoto/Graphics/CTexture.hpp"
#include "Kyoto/Math/CAABox.hpp"
CSimpleShadow::CSimpleShadow(float scale, float userAlpha, float maxObjHeight, float displacement)
: x0_xf(CTransform4f::Identity())
, x30_scale(scale)
, x34_radius(1.f)
, x38_userAlpha(userAlpha)
, x3c_heightAlpha(1.f)
, x40_maxObjHeight(maxObjHeight)
, x44_displacement(displacement)
, x48_24_collision(false)
, x48_25_alwaysCalculateRadius(true)
, x48_26_radiusCalculated(false) {}
void CSimpleShadow::Calculate(const CAABox& aabb, const CTransform4f& xf,
const CStateManager& mgr) {
x48_24_collision = false;
float halfHeight = (aabb.GetMaxPoint().GetZ() - aabb.GetMinPoint().GetZ()) * 0.5f;
float xExtent = aabb.GetMaxPoint().GetX() - aabb.GetMinPoint().GetX();
float yExtent = aabb.GetMaxPoint().GetY() - aabb.GetMinPoint().GetY();
CVector3f pos = xf.GetTranslation() + CVector3f(0.f, 0.f, halfHeight);
CVector3f dir(0.0f, 0.0f, -1.0f);
CRayCastResult res =
mgr.RayStaticIntersection(pos, dir, x40_maxObjHeight,
CMaterialFilter::MakeExclude(CMaterialList(kMT_SeeThrough)));
float height = x40_maxObjHeight;
if (res.IsValid()) {
x48_24_collision = true;
height = res.GetTime();
}
CVector3f resPoint = res.GetPoint();
CUnitVector3f resPlaneNormal = res.GetPlane().GetNormal();
if (height > 0.1f + halfHeight) {
TEntityList nearList;
mgr.BuildNearList(nearList, pos, dir, x40_maxObjHeight, CMaterialFilter::MakeInclude(CMaterialList(kMT_Floor)), nullptr);
TUniqueId cid = kInvalidUniqueId;
CRayCastResult resD =
CGameCollision::RayDynamicIntersection(mgr, cid, pos, dir, x40_maxObjHeight,
CMaterialFilter::GetPassEverything(), nearList);
if (resD.IsValid() && resD.GetTime() < height) {
resPoint = resD.GetPoint();
resPlaneNormal = resD.GetPlane().GetNormal();
x48_24_collision = true;
height = resD.GetTime();
}
}
if (x48_24_collision) {
x3c_heightAlpha = 1.f - height / x40_maxObjHeight;
CVector3f normalVector = resPlaneNormal;
x0_xf = CTransform4f::LookAt(normalVector, CVector3f::Zero());
x0_xf.SetTranslation(resPoint + x44_displacement * normalVector);
if (x48_25_alwaysCalculateRadius || !x48_26_radiusCalculated) {
x34_radius = sqrtf(xExtent * xExtent + yExtent * yExtent) * 0.5f;
x48_26_radiusCalculated = true;
}
}
}
void CSimpleShadow::Render(const CTexture* tex) const {
if (!x48_24_collision)
return;
CGraphics::DisableAllLights();
gpRender->SetModelMatrix(x0_xf);
tex->Load(GX_TEXMAP0, CTexture::kCM_Repeat);
CGraphics::SetTevOp(kTS_Stage0, CGraphics::kEnvModulate);
CGraphics::SetTevOp(kTS_Stage1, CGraphics::kEnvPassthru);
CGraphics::SetAlphaCompare(kAF_Always, 0, kAO_And, kAF_Always, 0);
CGraphics::SetDepthWriteMode(true, kE_LEqual, false);
CGraphics::SetBlendMode(kBM_Blend, kBF_SrcAlpha, kBF_InvSrcAlpha, kLO_Clear);
float radius = x34_radius * x30_scale;
CGraphics::StreamBegin(kP_Quads);
CGraphics::StreamColor(CCast::ToUint8((x3c_heightAlpha * x38_userAlpha) * 255.f) - 0x100);
CGraphics::StreamTexcoord(0.f, 0.f);
CGraphics::StreamVertex(CVector3f(-radius, 0.f, -radius));
CGraphics::StreamTexcoord(0.f, 1.f);
CGraphics::StreamVertex(CVector3f(radius, 0.f, -radius));
CGraphics::StreamTexcoord(1.f, 1.f);
CGraphics::StreamVertex(CVector3f(radius, 0.f, radius));
CGraphics::StreamTexcoord(1.f, 0.f);
CGraphics::StreamVertex(CVector3f(-radius, 0.f, radius));
CGraphics::StreamEnd();
}
const CTransform4f& CSimpleShadow::GetTransform() const { return x0_xf; }
void CSimpleShadow::SetUserAlpha(float alpha) { x38_userAlpha = alpha; }
float CSimpleShadow::GetMaxObjectHeight() const { return x40_maxObjHeight; }
void CSimpleShadow::SetAlwaysCalculateRadius(bool b) { x48_25_alwaysCalculateRadius = b; }
CAABox CSimpleShadow::GetBounds() const {
const CVector3f& translation = x0_xf.GetTranslation();
float extent = x34_radius * x30_scale;
return CAABox(translation - CVector3f(extent, extent, extent),
translation + CVector3f(extent, extent, extent));
}
CAABox CSimpleShadow::GetMaxShadowBox(const CAABox& aabb) const {
float extent = x34_radius * x30_scale;
CVector3f center = aabb.GetCenterPoint();
CAABox expandedAABB = aabb;
expandedAABB.AccumulateBounds(center + CVector3f(extent, extent, -GetMaxObjectHeight()));
expandedAABB.AccumulateBounds(center + CVector3f(-extent, -extent, -GetMaxObjectHeight()));
return expandedAABB;
}
bool CSimpleShadow::Valid() const { return x48_24_collision; }

View File

@ -191,7 +191,7 @@ void CCameraFilterPass::DrawWideScreen(const CColor& color, const CTexture* tex,
tex->Load(GX_TEXMAP0, CTexture::kCM_Repeat);
}
CGraphics::SetTevOp(kTS_Stage0, CTevPass_805a5ebc);
CGraphics::SetTevOp(kTS_Stage1, *PTR_skPassThru_805a8828);
CGraphics::SetTevOp(kTS_Stage1, CGraphics::kEnvPassthru);
{
CGraphics::StreamBegin(kP_TriangleStrip);