mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-05-13 23:11:20 +00:00
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.
142 lines
4.9 KiB
C++
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
|