2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-05-13 23:11:20 +00:00
metaforce/Runtime/World/CMorphBallShadow.cpp
Lioncash 40fc3f9dd8 CModelBoo: Remove usages of const_cast
Many functions are modifying internals of CBooModel and const-casting
is performed in order to work around functions being const when they
really shouldn't be.

This amends the function signatures in order to allow these functions to
exist without const_cast, making code much nicer to read.
2020-03-25 02:01:46 -04:00

142 lines
4.9 KiB
C++

#include "Runtime/World/CMorphBallShadow.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Graphics/CBooRenderer.hpp"
#include "Runtime/Particle/CGenDescription.hpp"
#include "Runtime/World/CPlayer.hpp"
#include "Runtime/World/CWorld.hpp"
namespace urde {
void CMorphBallShadow::GatherAreas(const CStateManager& mgr) {
x18_areas.clear();
for (const CGameArea& area : *mgr.GetWorld()) {
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded;
if (area.IsPostConstructed())
occState = area.GetPostConstructed()->x10dc_occlusionState;
if (occState == CGameArea::EOcclusionState::Visible)
x18_areas.push_back(area.GetAreaId());
}
}
void CMorphBallShadow::RenderIdBuffer(const zeus::CAABox& aabb, const CStateManager& mgr, CPlayer& player) {
xb8_shadowVolume = aabb;
x0_actors.clear();
x18_areas.clear();
x30_worldModelBits.clear();
g_Renderer->x318_26_requestRGBA6 = true;
if (!g_Renderer->x318_27_currentRGBA6) {
xd0_hasIds = false;
return;
}
GatherAreas(mgr);
SViewport backupVp = g_Viewport;
g_Renderer->BindBallShadowIdTarget();
CGraphics::g_BooMainCommandQueue->clearTarget();
zeus::CTransform backupViewMtx = CGraphics::g_ViewMatrix;
CGraphics::CProjectionState backupProjection = CGraphics::g_Proj;
zeus::CVector2f backupDepth = CGraphics::g_CachedDepthRange;
zeus::CTransform viewMtx(
zeus::skRight, zeus::skDown, zeus::skForward,
zeus::CVector3f((aabb.min.x() + aabb.max.x()) * 0.5f, (aabb.min.y() + aabb.max.y()) * 0.5f, aabb.max.z()));
CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_FAR);
float vpX = (aabb.max.x() - aabb.min.x()) * 0.5f;
float vpY = (aabb.max.y() - aabb.min.y()) * 0.5f;
float vpZ = (aabb.max.z() - aabb.min.z()) + FLT_EPSILON;
CGraphics::SetOrtho(-vpX, vpX, vpY, -vpY, 0.f, vpZ);
rstl::reserved_vector<TUniqueId, 1024> nearItems;
mgr.BuildNearList(nearItems, aabb, CMaterialFilter::skPassEverything, &player);
CGraphics::SetViewPointMatrix(viewMtx);
int alphaVal = 4;
for (TUniqueId id : nearItems) {
if (alphaVal > 255)
break;
const CActor* actor = static_cast<const CActor*>(mgr.GetObjectById(id));
if (!actor || !actor->CanDrawStatic())
continue;
x0_actors.push_back(actor);
const CModelData* modelData = actor->GetModelData();
zeus::CTransform modelXf = actor->GetTransform() * zeus::CTransform::Scale(modelData->GetScale());
CGraphics::SetModelMatrix(modelXf);
CModelFlags flags(0, 0, 3, zeus::CColor{1.f, 1.f, 1.f, alphaVal / 255.f});
flags.m_extendedShader = EExtendedShader::SolidColor; // Do solid color draw
CBooModel& model = *modelData->PickStaticModel(CModelData::EWhichModel::Normal);
model.VerifyCurrentShader(flags.x1_matSetIdx);
model.DrawNormal(flags, nullptr, nullptr);
alphaVal += 4;
}
CGraphics::SetModelMatrix(zeus::CTransform());
g_Renderer->FindOverlappingWorldModels(x30_worldModelBits, aabb);
alphaVal = g_Renderer->DrawOverlappingWorldModelIDs(alphaVal, x30_worldModelBits, aabb);
g_Renderer->ResolveBallShadowIdTarget();
g_Renderer->BindMainDrawTarget();
CGraphics::SetViewPointMatrix(backupViewMtx);
CGraphics::SetProjectionState(backupProjection);
g_Renderer->SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height);
CGraphics::SetDepthRange(backupDepth[0], backupDepth[1]);
xd0_hasIds = alphaVal != 4;
}
bool CMorphBallShadow::AreasValid(const CStateManager& mgr) const {
auto it = x18_areas.begin();
for (const CGameArea& area : *mgr.GetWorld()) {
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded;
if (area.IsPostConstructed())
occState = area.GetPostConstructed()->x10dc_occlusionState;
if (occState != CGameArea::EOcclusionState::Visible)
continue;
if (it == x18_areas.end())
return false;
if (*it != area.GetAreaId())
return false;
++it;
}
return true;
}
void CMorphBallShadow::Render(const CStateManager& mgr, float alpha) {
if (!xd0_hasIds || !AreasValid(mgr))
return;
CModelFlags flags;
flags.x4_color.a() = alpha;
flags.m_extendedShader = EExtendedShader::MorphBallShadow;
flags.mbShadowBox = xb8_shadowVolume;
int alphaVal = 4;
for (const CActor* actor : x0_actors) {
const CModelData* modelData = actor->GetModelData();
zeus::CTransform modelXf = actor->GetTransform() * zeus::CTransform::Scale(modelData->GetScale());
CGraphics::SetModelMatrix(modelXf);
flags.x4_color.r() = alphaVal / 255.f;
CBooModel& model = *modelData->PickStaticModel(CModelData::EWhichModel::Normal);
model.VerifyCurrentShader(flags.x1_matSetIdx);
model.DrawNormal(flags, nullptr, nullptr);
alphaVal += 4;
}
CGraphics::SetModelMatrix(zeus::CTransform());
g_Renderer->DrawOverlappingWorldModelShadows(alphaVal, x30_worldModelBits, xb8_shadowVolume, alpha);
}
} // namespace urde