metaforce/Runtime/Graphics/CSimpleShadow.cpp

97 lines
4.0 KiB
C++
Raw Normal View History

#include "Runtime/Graphics/CSimpleShadow.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/Collision/CGameCollision.hpp"
2021-04-10 01:42:06 -07:00
namespace metaforce {
2018-02-04 22:56:09 -08:00
CSimpleShadow::CSimpleShadow(float scale, float userAlpha, float maxObjHeight, float displacement)
: x30_scale(scale), x38_userAlpha(userAlpha), x40_maxObjHeight(maxObjHeight), x44_displacement(displacement) {}
2018-02-04 22:56:09 -08:00
2018-12-07 21:30:43 -08:00
zeus::CAABox CSimpleShadow::GetMaxShadowBox(const zeus::CAABox& aabb) const {
float extent = x34_radius * x30_scale;
zeus::CVector3f center = aabb.center();
zeus::CAABox expandedAABB = aabb;
expandedAABB.accumulateBounds({center.x() + extent, center.y() + extent, center.z() - GetMaxObjectHeight()});
expandedAABB.accumulateBounds({center.x() - extent, center.y() - extent, center.z() - GetMaxObjectHeight()});
return expandedAABB;
2018-02-04 22:56:09 -08:00
}
2018-12-07 21:30:43 -08:00
zeus::CAABox CSimpleShadow::GetBounds() const {
float extent = x34_radius * x30_scale;
return {
{x0_xf.origin.x() - extent, x0_xf.origin.y() - extent, x0_xf.origin.z() - extent},
{x0_xf.origin.x() + extent, x0_xf.origin.y() + extent, x0_xf.origin.z() + extent},
};
2018-02-04 22:56:09 -08:00
}
void CSimpleShadow::Render(TLockedToken<CTexture>& tex) {
2018-12-07 21:30:43 -08:00
if (!x48_24_collision)
return;
2019-07-21 01:42:52 -07:00
SCOPED_GRAPHICS_DEBUG_GROUP("CSimpleShadow::Render", zeus::skGrey);
2018-02-04 22:56:09 -08:00
2018-12-07 21:30:43 -08:00
CGraphics::DisableAllLights();
CGraphics::SetModelMatrix(x0_xf);
2022-07-29 13:16:55 -07:00
tex->Load(GX_TEXMAP0, EClampMode::Repeat);
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::kEnvModulate);
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::kEnvPassthru);
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false);
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha,
ERglLogicOp::Clear);
2022-07-29 13:16:55 -07:00
CGraphics::StreamBegin(GX_QUADS);
2018-12-07 21:30:43 -08:00
float radius = x34_radius * x30_scale;
2022-05-23 22:44:20 -07:00
CGraphics::StreamColor(zeus::CColor{1.f, x3c_heightAlpha * x38_userAlpha});
CGraphics::StreamTexcoord(0.f, 0.f);
CGraphics::StreamVertex(-radius, 0.f, -radius);
CGraphics::StreamTexcoord(0.f, 1.f);
CGraphics::StreamVertex(radius, 0.f, -radius);
CGraphics::StreamTexcoord(1.f, 1.f);
CGraphics::StreamVertex(radius, 0.f, radius);
CGraphics::StreamTexcoord(1.f, 0.f);
CGraphics::StreamVertex(-radius, 0.f, radius);
CGraphics::StreamEnd();
}
2018-12-07 21:30:43 -08:00
void CSimpleShadow::Calculate(const zeus::CAABox& aabb, const zeus::CTransform& xf, const CStateManager& mgr) {
x48_24_collision = false;
float halfHeight = (aabb.max.z() - aabb.min.z()) * 0.5f;
zeus::CVector3f pos = xf.origin + zeus::CVector3f(0.f, 0.f, halfHeight);
CRayCastResult res = mgr.RayStaticIntersection(pos, zeus::skDown, x40_maxObjHeight,
2018-12-07 21:30:43 -08:00
CMaterialFilter::MakeExclude({EMaterialTypes::SeeThrough}));
float height = x40_maxObjHeight;
if (res.IsValid()) {
x48_24_collision = true;
height = res.GetT();
}
2018-02-04 22:56:09 -08:00
2018-12-07 21:30:43 -08:00
if (height > 0.1f + halfHeight) {
EntityList nearList;
2022-11-17 02:06:40 -08:00
mgr.BuildNearList(nearList, pos, zeus::skDown, x40_maxObjHeight, CMaterialFilter::MakeInclude(CMaterialList(EMaterialTypes::Floor)), nullptr);
TUniqueId cid = kInvalidUniqueId;
2021-06-07 12:29:18 -07:00
CRayCastResult resD = CGameCollision::RayDynamicIntersection(mgr, cid, pos, zeus::skDown, x40_maxObjHeight,
CMaterialFilter::skPassEverything, nearList);
2018-12-07 21:30:43 -08:00
if (resD.IsValid() && resD.GetT() < height) {
x48_24_collision = true;
height = resD.GetT();
res = resD;
2018-02-04 22:56:09 -08:00
}
2018-12-07 21:30:43 -08:00
}
2018-12-07 21:30:43 -08:00
if (x48_24_collision) {
x3c_heightAlpha = 1.f - height / x40_maxObjHeight;
x0_xf = zeus::lookAt(res.GetPlane().normal(), zeus::skZero3f);
2018-12-07 21:30:43 -08:00
x0_xf.origin = res.GetPlane().normal() * x44_displacement + res.GetPoint();
if (x48_25_alwaysCalculateRadius || !x48_26_radiusCalculated) {
float xExtent = aabb.max.x() - aabb.min.x();
float yExtent = aabb.max.y() - aabb.min.y();
x34_radius = std::sqrt(xExtent * xExtent + yExtent * yExtent) * 0.5f;
x48_26_radiusCalculated = true;
2018-02-04 22:56:09 -08:00
}
2018-12-07 21:30:43 -08:00
}
}
2018-02-04 22:56:09 -08:00
2021-04-10 01:42:06 -07:00
} // namespace metaforce