diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index d37afdc8d..129aca1b5 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -543,8 +543,15 @@ void CStateManager::DrawDebugStuff() const { if (CPathFindSearch* path = ai->GetSearchPath()) { path->DebugDraw(); } + } else if (const TCastToPtr light = ent) { + light->DebugDraw(); } } + + auto* gameArea = x850_world->GetArea(x850_world->GetCurrentAreaId()); + if (gameArea != nullptr) { + gameArea->DebugDraw(); + } if (xf70_currentMaze) { xf70_currentMaze->DebugRender(); } diff --git a/Runtime/World/CGameArea.cpp b/Runtime/World/CGameArea.cpp index 458728de9..ff2f8a18b 100644 --- a/Runtime/World/CGameArea.cpp +++ b/Runtime/World/CGameArea.cpp @@ -306,9 +306,9 @@ CDummyGameArea::CDummyGameArea(CInputStream& in, int idx, int mlvlVersion) { aabb.readBoundingBoxBig(in); xc_mrea = in.readUint32Big(); if (mlvlVersion > 15) { - x10_areaId = in.readUint32Big(); + x10_areaId = in.readUint32Big(); } else { - x10_areaId = -1; + x10_areaId = -1; } u32 attachAreaCount = in.readUint32Big(); @@ -1199,10 +1199,69 @@ void CGameArea::SetAreaAttributes(const CScriptAreaAttributes* areaAttributes) { x12c_postConstructed->x1128_worldLightingLevel = areaAttributes->GetWorldLightingLevel(); } -bool CGameArea::CAreaObjectList::IsQualified(const CEntity& ent) const { return (ent.GetAreaIdAlways() == x200c_areaIdx); } +bool CGameArea::CAreaObjectList::IsQualified(const CEntity& ent) const { + return (ent.GetAreaIdAlways() == x200c_areaIdx); +} void CGameArea::WarmupShaders(const SObjectTag& mreaTag) { // Calling this version of the constructor performs warmup implicitly [[maybe_unused]] CGameArea area(mreaTag.id); } +void CGameArea::DebugDraw() { + if (!m_debugSphereRes) { + const auto* tok = g_ResFactory->GetResourceIdByName("CMDL_DebugSphere"); + if (tok != nullptr && tok->type == FOURCC('CMDL')) { + m_debugSphereRes = CStaticRes(tok->id, zeus::skOne3f); + } + } + + if (m_debugSphereRes && !m_debugSphereModel) { + m_debugSphereModel = std::make_unique(*m_debugSphereRes); + } + + if (!m_debugConeRes) { + const auto* tok = g_ResFactory->GetResourceIdByName("CMDL_DebugLightCone"); + if (tok != nullptr && tok->type == FOURCC('CMDL')) { + m_debugConeRes = CStaticRes(tok->id, zeus::skOne3f); + } + } + + if (m_debugConeRes && !m_debugConeModel) { + m_debugConeModel = std::make_unique(*m_debugConeRes); + } + + if (IsPostConstructed()) { + for (const auto& light : x12c_postConstructed->x70_gfxLightsA) { + DebugDrawLight(light); + } + for (const auto& light : x12c_postConstructed->x90_gfxLightsB) { + DebugDrawLight(light); + } + } +} + +void CGameArea::DebugDrawLight(const CLight& light) { + if (light.GetType() == ELightType::LocalAmbient) { + return; + } + g_Renderer->SetGXRegister1Color(light.GetColor()); + CModelFlags modelFlags; + modelFlags.x0_blendMode = 5; + modelFlags.x4_color = zeus::skWhite; + modelFlags.x4_color.a() = 0.5f; + if ((light.GetType() == ELightType::Spot || light.GetType() == ELightType::Directional) && m_debugConeModel) { + m_debugConeModel->Render(CModelData::EWhichModel::Normal, + zeus::lookAt(light.GetPosition(), light.GetPosition() + light.GetDirection()) * + zeus::CTransform::Scale(zeus::clamp(-90.f, light.GetRadius(), 90.f)), + nullptr, modelFlags); + } else if (m_debugSphereModel) { + m_debugSphereModel->Render(CModelData::EWhichModel::Normal, zeus::CTransform::Translate(light.GetPosition()), + nullptr, modelFlags); + m_debugSphereModel->Render(CModelData::EWhichModel::Normal, + zeus::CTransform::Translate(light.GetPosition()) * + zeus::CTransform::Scale(light.GetRadius()), + nullptr, modelFlags); + } +} + } // namespace urde diff --git a/Runtime/World/CGameArea.hpp b/Runtime/World/CGameArea.hpp index eb9fdfa6a..b4625b852 100644 --- a/Runtime/World/CGameArea.hpp +++ b/Runtime/World/CGameArea.hpp @@ -15,7 +15,7 @@ #include "Runtime/World/CPathFindArea.hpp" #include "Runtime/World/CWorldLight.hpp" #include "Runtime/World/IGameArea.hpp" - +#include "Runtime/Character/CModelData.hpp" #include #include @@ -268,6 +268,10 @@ private: void UpdateThermalVisor(float dt); void UpdateWeaponWorldLighting(float dt); + std::optional m_debugSphereRes; + std::unique_ptr m_debugSphereModel; + std::optional m_debugConeRes; + std::unique_ptr m_debugConeModel; public: explicit CGameArea(CInputStream& in, int idx, int mlvlVersion); explicit CGameArea(CAssetId mreaId); // Warmup constructor @@ -362,6 +366,8 @@ public: CGameArea* GetNext() const { return x130_next; } static void WarmupShaders(const SObjectTag& mreaTag); + void DebugDraw(); + void DebugDrawLight(const CLight& light); }; } // namespace urde diff --git a/Runtime/World/CGameLight.cpp b/Runtime/World/CGameLight.cpp index e03019125..84e090164 100644 --- a/Runtime/World/CGameLight.cpp +++ b/Runtime/World/CGameLight.cpp @@ -2,6 +2,9 @@ #include "Runtime/CStateManager.hpp" #include "Runtime/World/CActorParameters.hpp" +#include "Runtime/GameGlobalObjects.hpp" +#include "Runtime/CSimplePool.hpp" +#include "Graphics/CBooRenderer.hpp" #include "TCastTo.hpp" // Generated file, do not modify include path @@ -53,4 +56,30 @@ CLight CGameLight::GetLight() const { return ret; } + +void CGameLight::DebugDraw() { + if (!m_debugRes) { + const auto* tok = (xec_light.GetType() == ELightType::Spot || xec_light.GetType() == ELightType::Directional) + ? g_ResFactory->GetResourceIdByName("CMDL_DebugLightCone") + : g_ResFactory->GetResourceIdByName("CMDL_DebugSphere"); + if (tok != nullptr && tok->type == FOURCC('CMDL')) { + m_debugRes = CStaticRes(tok->id, zeus::skOne3f); + } + } + + if (m_debugRes && !m_debugModel) { + m_debugModel = std::make_unique(*m_debugRes); + } + + if (m_debugModel) { + g_Renderer->SetGXRegister1Color(xec_light.GetColor()); + CModelFlags modelFlags; + modelFlags.x0_blendMode = 5; + modelFlags.x4_color = zeus::skWhite; + modelFlags.x4_color.a() = 0.5f; + m_debugModel->Render(CModelData::EWhichModel::Normal, zeus::CTransform::Translate(xec_light.GetPosition()), nullptr, + modelFlags); + m_debugModel->Render(CModelData::EWhichModel::Normal, x34_transform, nullptr, modelFlags); + } +} } // namespace urde diff --git a/Runtime/World/CGameLight.hpp b/Runtime/World/CGameLight.hpp index d840a8bc9..ac6b6e312 100644 --- a/Runtime/World/CGameLight.hpp +++ b/Runtime/World/CGameLight.hpp @@ -14,6 +14,9 @@ class CGameLight : public CActor { u32 x140_priority; float x144_lifeTime; + + std::optional m_debugRes; + std::unique_ptr m_debugModel; public: CGameLight(TUniqueId uid, TAreaId aid, bool active, std::string_view name, const zeus::CTransform& xf, TUniqueId parentId, const CLight& light, u32 sourceId, u32 priority, float lifeTime); @@ -24,5 +27,7 @@ public: void SetLight(const CLight& light); CLight GetLight() const; TUniqueId GetParentId() const { return xe8_parentId; } + + void DebugDraw(); }; } // namespace urde