metaforce/Runtime/World/CMorphBallShadow.cpp

151 lines
5.2 KiB
C++
Raw Normal View History

2017-03-05 07:57:12 +00:00
#include "CMorphBallShadow.hpp"
#include "CStateManager.hpp"
#include "World/CWorld.hpp"
#include "GameGlobalObjects.hpp"
#include "Graphics/CBooRenderer.hpp"
#include "World/CPlayer.hpp"
2017-03-05 23:03:23 +00:00
#include "Particle/CGenDescription.hpp"
2017-03-05 07:57:12 +00:00
namespace urde
{
2017-03-06 06:33:51 +00:00
void CMorphBallShadow::GatherAreas(const CStateManager& mgr)
2017-03-05 07:57:12 +00:00
{
x18_areas.clear();
for (const CGameArea& area : *mgr.GetWorld())
2017-03-05 07:57:12 +00:00
{
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());
2017-03-05 07:57:12 +00:00
}
}
2017-03-06 06:33:51 +00:00
void CMorphBallShadow::RenderIdBuffer(const zeus::CAABox& aabb, const CStateManager& mgr, CPlayer& player)
2017-03-05 07:57:12 +00:00
{
2017-03-06 06:33:51 +00:00
xb8_shadowVolume = aabb;
2017-03-05 07:57:12 +00:00
x0_actors.clear();
x18_areas.clear();
x30_worldModelBits.clear();
2017-03-06 06:33:51 +00:00
g_Renderer->x318_26_requestRGBA6 = true;
2017-03-05 07:57:12 +00:00
2017-03-06 06:33:51 +00:00
if (!g_Renderer->x318_27_currentRGBA6)
2017-03-05 07:57:12 +00:00
{
xd0_hasIds = false;
return;
}
GatherAreas(mgr);
SViewport backupVp = g_Viewport;
2017-03-05 07:57:12 +00:00
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::CVector3f::skRight, zeus::CVector3f::skDown, zeus::CVector3f::skForward,
zeus::CVector3f((aabb.min.x + aabb.max.x) * 0.5f,
(aabb.min.y + aabb.max.y) * 0.5f,
aabb.max.z));
2018-01-06 06:50:42 +00:00
CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_FAR);
2017-03-05 07:57:12 +00:00
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});
2017-03-10 20:52:53 +00:00
flags.m_extendedShader = EExtendedShader::SolidColor; // Do solid color draw
2017-03-05 07:57:12 +00:00
const CBooModel& model = *modelData->PickStaticModel(CModelData::EWhichModel::Normal);
2017-03-20 05:09:53 +00:00
const_cast<CBooModel&>(model).VerifyCurrentShader(flags.x1_matSetIdx);
2017-03-05 07:57:12 +00:00
model.DrawNormal(flags, nullptr, nullptr);
alphaVal += 4;
}
CGraphics::SetModelMatrix(zeus::CTransform::Identity());
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);
2017-03-05 07:57:12 +00:00
CGraphics::SetDepthRange(backupDepth[0], backupDepth[1]);
xd0_hasIds = alphaVal != 4;
}
2017-03-06 06:33:51 +00:00
bool CMorphBallShadow::AreasValid(const CStateManager& mgr) const
2017-03-05 07:57:12 +00:00
{
auto it = x18_areas.begin();
for (const CGameArea& area : *mgr.GetWorld())
2017-03-05 07:57:12 +00:00
{
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded;
if (area.IsPostConstructed())
occState = area.GetPostConstructed()->x10dc_occlusionState;
if (occState != CGameArea::EOcclusionState::Visible)
2017-03-05 07:57:12 +00:00
continue;
if (it == x18_areas.end())
return false;
if (*it != area.GetAreaId())
2017-03-05 07:57:12 +00:00
return false;
++it;
}
return true;
}
2017-03-06 06:33:51 +00:00
void CMorphBallShadow::Render(const CStateManager& mgr, float alpha)
2017-03-05 07:57:12 +00:00
{
if (!xd0_hasIds || !AreasValid(mgr))
return;
2017-03-06 06:33:51 +00:00
CModelFlags flags;
2017-03-20 05:09:53 +00:00
flags.x4_color.a = alpha;
2017-03-10 20:52:53 +00:00
flags.m_extendedShader = EExtendedShader::MorphBallShadow;
2017-03-06 06:33:51 +00:00
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);
2017-03-20 05:09:53 +00:00
flags.x4_color.r = alphaVal / 255.f;
2017-03-06 06:33:51 +00:00
const CBooModel& model = *modelData->PickStaticModel(CModelData::EWhichModel::Normal);
2017-03-20 05:09:53 +00:00
const_cast<CBooModel&>(model).VerifyCurrentShader(flags.x1_matSetIdx);
2017-03-06 06:33:51 +00:00
model.DrawNormal(flags, nullptr, nullptr);
alphaVal += 4;
}
CGraphics::SetModelMatrix(zeus::CTransform::Identity());
g_Renderer->DrawOverlappingWorldModelShadows(alphaVal, x30_worldModelBits, xb8_shadowVolume, alpha);
2017-03-05 07:57:12 +00:00
}
}