diff --git a/Runtime/Graphics/CBooRenderer.cpp b/Runtime/Graphics/CBooRenderer.cpp index 4301da320..c671c4d89 100644 --- a/Runtime/Graphics/CBooRenderer.cpp +++ b/Runtime/Graphics/CBooRenderer.cpp @@ -7,6 +7,7 @@ #include "CModel.hpp" #include "Particle/CParticleGen.hpp" #include "CMetroidModelInstance.hpp" +#include "World/CAreaOctTree.hpp" #define MIRROR_RAMP_RES 32 #define FOGVOL_RAMP_RES 256 @@ -141,12 +142,60 @@ void Buckets::Init() CBooRenderer::CAreaListItem::CAreaListItem (const std::vector* geom, const CAreaOctTree* octTree, - std::vector&& models, int unk) -: x0_geometry(geom), x4_octTree(octTree), x10_models(std::move(models)), x18_unk(unk) {} + std::vector&& models, int areaIdx) +: x0_geometry(geom), x4_octTree(octTree), x10_models(std::move(models)), x18_areaIdx(areaIdx) {} CBooRenderer::CAreaListItem::~CAreaListItem() {} -void CBooRenderer::RenderBucketItems(const std::vector& lights) +void CBooRenderer::ActivateLightsForModel(CAreaListItem* item, CBooModel& model) +{ + std::vector thisLights; + thisLights.reserve(4); + + if (x304_lights.size()) + { + /* + void* unk3 = nullptr; + int x14 = 0; + if (item && item->x18_areaIdx != -1) + { + unk3 = item->x28_unk3; + x14 = item->x4_octTree->x14_; + } + void* unk3Cur = unk3; + */ + + float lightRads[] = {-1.f, -1.f, -1.f, -1.f}; + for (int i=0 ; i<4 ; ++i) + { + for (CLight& light : x304_lights) + { + /* + if (unk3) + { + } + */ + if (light.x40_loadedIdx == i) + continue; + float rad = light.GetRadius(); + if (model.x20_aabb.intersects(zeus::CSphere{light.x0_pos, rad})) + { + if (rad > lightRads[i]) + { + lightRads[i] = rad; + light.x40_loadedIdx = i; + thisLights.push_back(light); + break; + } + } + } + } + } + + model.ActivateLights(thisLights); +} + +void CBooRenderer::RenderBucketItems(CAreaListItem* item) { for (u16 idx : Buckets::sBucketIndex) { @@ -166,16 +215,16 @@ void CBooRenderer::RenderBucketItems(const std::vector& lights) CBooModel* model = surf->m_parent; if (model) { - model->ActivateLights(lights); + ActivateLightsForModel(item, *model); model->DrawSurface(*surf, CModelFlags{}); } break; } default: { - if (xa8_renderCallback) + if (xa8_drawableCallback) { - xa8_renderCallback(drawable->GetData(), xac_callbackContext, + xa8_drawableCallback(drawable->GetData(), xac_callbackContext, int(drawable->GetType()) - 2); } break; @@ -185,6 +234,17 @@ void CBooRenderer::RenderBucketItems(const std::vector& lights) } } +void CBooRenderer::HandleUnsortedModel(CAreaListItem* item, CBooModel& model) +{ + ActivateLightsForModel(item, model); + CBooSurface* surf = model.x38_firstUnsortedSurface; + while (surf) + { + model.DrawSurface(*surf, CModelFlags{}); + surf = surf->m_next; + } +} + void CBooRenderer::GenerateMirrorRampTex(boo::IGraphicsDataFactory::Context& ctx) { u8 data[MIRROR_RAMP_RES][MIRROR_RAMP_RES][4] = {}; @@ -271,8 +331,8 @@ void CBooRenderer::AddWorldSurfaces(CBooModel& model) { const CBooModel::MaterialSet::Material& mat = model.GetMaterialByIndex(surf->selfIdx); zeus::CAABox aabb = surf->GetBounds(); - zeus::CVector3f pt = aabb.closestPointAlongVector(xb0_.vec); - Buckets::Insert(pt, aabb, EDrawableType::Surface, surf, xb0_, + zeus::CVector3f pt = aabb.closestPointAlongVector(xb0_viewPlane.vec); + Buckets::Insert(pt, aabb, EDrawableType::Surface, surf, xb0_viewPlane, mat.heclIr.m_blendDst != boo::BlendFactor::Zero); surf = surf->m_next; } @@ -286,7 +346,7 @@ CBooRenderer::FindStaticGeometry(const std::vector* geome } void CBooRenderer::AddStaticGeometry(const std::vector* geometry, - const CAreaOctTree* octTree, int unk) + const CAreaOctTree* octTree, int areaIdx) { auto search = FindStaticGeometry(geometry); if (search == x1c_areaListItems.end()) @@ -298,7 +358,7 @@ void CBooRenderer::AddStaticGeometry(const std::vector* g for (const CMetroidModelInstance& inst : *geometry) models.push_back(inst.m_instance.get()); } - x1c_areaListItems.emplace_back(geometry, octTree, std::move(models), unk); + x1c_areaListItems.emplace_back(geometry, octTree, std::move(models), areaIdx); } } @@ -320,7 +380,7 @@ void CBooRenderer::RemoveStaticGeometry(const std::vector x1c_areaListItems.erase(search); } -void CBooRenderer::DrawUnsortedGeometry(const std::vector&, int mask, int targetMask) +void CBooRenderer::DrawUnsortedGeometry(int areaIdx, int mask, int targetMask) { //SetupRendererStates(true); @@ -328,7 +388,7 @@ void CBooRenderer::DrawUnsortedGeometry(const std::vector&, int mask, in for (CAreaListItem& item : x1c_areaListItems) { - if (item.x18_unk != 0xff) + if (areaIdx != -1 && item.x18_areaIdx != areaIdx) continue; if (item.x4_octTree) @@ -356,6 +416,7 @@ void CBooRenderer::DrawUnsortedGeometry(const std::vector&, int mask, in model->x40_25_modelVisible = false; continue; } + break; } case EPVSMode::PVSAndMask: { @@ -389,7 +450,7 @@ void CBooRenderer::DrawUnsortedGeometry(const std::vector&, int mask, in } model->x40_25_modelVisible = true; - //HandleUnsortedModel(); + HandleUnsortedModel(lastOctreeItem, *model); } } @@ -397,14 +458,40 @@ void CBooRenderer::DrawUnsortedGeometry(const std::vector&, int mask, in //SetupCGraphicsStates(); } -void CBooRenderer::DrawSortedGeometry(const std::vector&, int mask, int targetMask) +void CBooRenderer::DrawSortedGeometry(int areaIdx, int mask, int targetMask) { //SetupRendererStates(true); + + CAreaListItem* lastOctreeItem = nullptr; + + for (CAreaListItem& item : x1c_areaListItems) + { + if (areaIdx != -1 && item.x18_areaIdx != areaIdx) + continue; + + if (item.x4_octTree) + lastOctreeItem = &item; + + for (auto it = item.x10_models.begin() ; it != item.x10_models.end() ; ++it) + { + CBooModel* model = *it; + if (model->x40_25_modelVisible) + AddWorldSurfaces(*model); + } + } + + Buckets::Sort(); + RenderBucketItems(lastOctreeItem); + + //SetupCGraphicsStates(); + //DrawRenderBucketsDebug(); + Buckets::Clear(); } -void CBooRenderer::DrawStaticGeometry(const std::vector& lights, int mask, int targetMask) +void CBooRenderer::DrawStaticGeometry(int modelCount, int mask, int targetMask) { - DrawUnsortedGeometry(lights, mask, targetMask); + DrawUnsortedGeometry(modelCount, mask, targetMask); + DrawSortedGeometry(modelCount, mask, targetMask); } void CBooRenderer::PostRenderFogs() @@ -416,8 +503,8 @@ void CBooRenderer::AddParticleGen(const CParticleGen& gen) std::pair bounds = gen.GetBounds(); if (bounds.second) { - zeus::CVector3f pt = bounds.first.closestPointAlongVector(xb0_.vec); - Buckets::Insert(pt, bounds.first, EDrawableType::Particle, &gen, xb0_, 0); + zeus::CVector3f pt = bounds.first.closestPointAlongVector(xb0_viewPlane.vec); + Buckets::Insert(pt, bounds.first, EDrawableType::Particle, &gen, xb0_viewPlane, 0); } } @@ -429,31 +516,36 @@ void CBooRenderer::AddPlaneObject(const void*, const zeus::CAABox&, const zeus:: void CBooRenderer::AddDrawable(const void* obj, const zeus::CVector3f& pos, const zeus::CAABox& aabb, int mode, EDrawableSorting sorting) { if (sorting == EDrawableSorting::UnsortedCallback) - xa8_renderCallback(obj, xac_callbackContext, mode); + xa8_drawableCallback(obj, xac_callbackContext, mode); else - Buckets::Insert(pos, aabb, EDrawableType(mode + 2), obj, xb0_, 0); + Buckets::Insert(pos, aabb, EDrawableType(mode + 2), obj, xb0_viewPlane, 0); } void CBooRenderer::SetDrawableCallback(TDrawableCallback&& cb, const void* ctx) { - xa8_renderCallback = std::move(cb); + xa8_drawableCallback = std::move(cb); xac_callbackContext = ctx; } -void CBooRenderer::SetWorldViewpoint(const zeus::CTransform&) +void CBooRenderer::SetWorldViewpoint(const zeus::CTransform& xf) { + CGraphics::SetViewPointMatrix(xf); + xb0_viewPlane.vec = xf.basis[1]; + xb0_viewPlane.d = xf.basis[1].dot(xf.origin); } void CBooRenderer::SetPerspectiveFovScalar(float) { } -void CBooRenderer::SetPerspective(float, float, float, float, float) +void CBooRenderer::SetPerspective(float fovy, float width, float height, float znear, float zfar) { + CGraphics::SetPerspective(fovy, width / height, znear, zfar); } -void CBooRenderer::SetPerspective(float, float, float, float) +void CBooRenderer::SetPerspective(float fovy, float aspect, float znear, float zfar) { + CGraphics::SetPerspective(fovy, aspect, znear, zfar); } void CBooRenderer::SetViewportOrtho(bool, float, float) @@ -630,7 +722,7 @@ void CBooRenderer::DoThermalBlendCold() zeus::CColor b{bFac, bFac, bFac, bAlpha}; m_thermColdFilter.setColorB(b); zeus::CColor c = zeus::CColor::lerp(zeus::CColor::skBlack, zeus::CColor::skWhite, - (x2f8_thermColdScale - 0.25f) * 4.f / 3.f); + zeus::clamp(0.f, (x2f8_thermColdScale - 0.25f) * 4.f / 3.f, 1.f)); m_thermColdFilter.setColorC(c); m_thermColdFilter.setScale(x2f8_thermColdScale); diff --git a/Runtime/Graphics/CBooRenderer.hpp b/Runtime/Graphics/CBooRenderer.hpp index 094cac799..10ce85430 100644 --- a/Runtime/Graphics/CBooRenderer.hpp +++ b/Runtime/Graphics/CBooRenderer.hpp @@ -49,13 +49,13 @@ class CBooRenderer : public IRenderer const CAreaOctTree* x4_octTree; //std::vector> x8_textures; std::vector x10_models; - int x18_unk; + int x18_areaIdx; int x20_unk1 = 0; int x24_unk2 = 0; - int x28_unk3 = 0; + void* x28_unk3 = nullptr; CAreaListItem(const std::vector* geom, const CAreaOctTree* octTree, - std::vector&& models, int unk); + std::vector&& models, int areaIdx); ~CAreaListItem(); }; @@ -67,10 +67,10 @@ class CBooRenderer : public IRenderer std::list x1c_areaListItems; zeus::CFrustum x44_frustumPlanes; - TDrawableCallback xa8_renderCallback; + TDrawableCallback xa8_drawableCallback; const void* xac_callbackContext; - zeus::CPlane xb0_ = {0.f, 1.f, 0.f, 0.f}; + zeus::CPlane xb0_viewPlane = {0.f, 1.f, 0.f, 0.f}; enum class EPVSMode { @@ -101,6 +101,8 @@ class CBooRenderer : public IRenderer float x2f8_thermColdScale = 0.f; CThermalColdFilter m_thermColdFilter; + std::vector x304_lights; + union { struct @@ -122,7 +124,9 @@ class CBooRenderer : public IRenderer void GenerateSphereRampTex(boo::IGraphicsDataFactory::Context& ctx); void LoadThermoPalette(); - void RenderBucketItems(const std::vector& lights); + void ActivateLightsForModel(CAreaListItem* item, CBooModel& model); + void RenderBucketItems(CAreaListItem* item); + void HandleUnsortedModel(CAreaListItem* item, CBooModel& model); public: CBooRenderer(IObjectStore& store, IFactory& resFac); @@ -130,13 +134,13 @@ public: void AddWorldSurfaces(CBooModel& model); std::list::iterator FindStaticGeometry(const std::vector*); - void AddStaticGeometry(const std::vector*, const CAreaOctTree*, int); + void AddStaticGeometry(const std::vector*, const CAreaOctTree*, int areaIdx); void EnablePVS(const CPVSVisSet*, u32); void DisablePVS(); void RemoveStaticGeometry(const std::vector*); - void DrawUnsortedGeometry(const std::vector&, int mask, int targetMask); - void DrawSortedGeometry(const std::vector&, int mask, int targetMask); - void DrawStaticGeometry(const std::vector&, int mask, int targetMask); + void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask); + void DrawSortedGeometry(int areaIdx, int mask, int targetMask); + void DrawStaticGeometry(int areaIdx, int mask, int targetMask); void PostRenderFogs(); void AddParticleGen(const CParticleGen&); void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int); diff --git a/Runtime/Graphics/CLight.hpp b/Runtime/Graphics/CLight.hpp index 815f75cf0..3bb036d42 100644 --- a/Runtime/Graphics/CLight.hpp +++ b/Runtime/Graphics/CLight.hpp @@ -27,6 +27,7 @@ class CLight { friend class CGuiLight; friend class CBooModel; + friend class CBooRenderer; zeus::CVector3f x0_pos; zeus::CVector3f xc_dir; diff --git a/Runtime/Graphics/IRenderer.hpp b/Runtime/Graphics/IRenderer.hpp index 8dcad859c..d8a9dad9f 100644 --- a/Runtime/Graphics/IRenderer.hpp +++ b/Runtime/Graphics/IRenderer.hpp @@ -45,9 +45,9 @@ public: virtual void EnablePVS(const CPVSVisSet*, u32)=0; virtual void DisablePVS()=0; virtual void RemoveStaticGeometry(const std::vector*)=0; - virtual void DrawUnsortedGeometry(const std::vector&, int, int)=0; - virtual void DrawSortedGeometry(const std::vector&, int, int)=0; - virtual void DrawStaticGeometry(const std::vector&, int, int)=0; + virtual void DrawUnsortedGeometry(int, int, int)=0; + virtual void DrawSortedGeometry(int, int, int)=0; + virtual void DrawStaticGeometry(int, int, int)=0; virtual void PostRenderFogs()=0; virtual void AddParticleGen(const CParticleGen&)=0; virtual void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int)=0; diff --git a/Runtime/World/CAreaOctTree.hpp b/Runtime/World/CAreaOctTree.hpp index 01e90194a..14ad2975a 100644 --- a/Runtime/World/CAreaOctTree.hpp +++ b/Runtime/World/CAreaOctTree.hpp @@ -10,6 +10,7 @@ class CCollisionEdge; class CMaterialFilter; class CAreaOctTree { + friend class CBooRenderer; public: struct SRayResult { @@ -35,6 +36,7 @@ public: }; private: + public: Node(const void*, const zeus::CAABox&, const CAreaOctTree& owner, ETreeType); #if 0 @@ -52,6 +54,8 @@ public: ETreeType GetTreeType(s32) const; }; + int x14_; + public: CAreaOctTree(const zeus::CAABox& box, Node::ETreeType treeType, u8*, void*, u32, u32*, u8*, u8*, u8*, u32, CCollisionEdge*, u32, u16*, u32, zeus::CVector3f*); diff --git a/Runtime/World/CGameArea.cpp b/Runtime/World/CGameArea.cpp index 4d4ad2104..886c52b3c 100644 --- a/Runtime/World/CGameArea.cpp +++ b/Runtime/World/CGameArea.cpp @@ -1,4 +1,6 @@ #include "CGameArea.hpp" +#include "GameGlobalObjects.hpp" +#include "Graphics/CBooRenderer.hpp" namespace urde { @@ -243,10 +245,26 @@ void CGameArea::SetOcclusionState(EOcclusionState state) void CGameArea::RemoveStaticGeometry() { + if (!xf0_24_postConstructed || !x12c_postConstructed || !x12c_postConstructed->x10dc_) + return; + x12c_postConstructed->x10e0_ = 0; + x12c_postConstructed->x10dc_ = 0; + g_Renderer->RemoveStaticGeometry(&x12c_postConstructed->x4c_insts); } void CGameArea::AddStaticGeometry() { + if (x12c_postConstructed->x10dc_ != 1) + { + x12c_postConstructed->x10e0_ = 0; + x12c_postConstructed->x10dc_ = 1; + if (!x12c_postConstructed->x1108_25_) + FillInStaticGeometry(); + g_Renderer->AddStaticGeometry(&x12c_postConstructed->x4c_insts, + x12c_postConstructed->xc_octTree ? + &*x12c_postConstructed->xc_octTree : nullptr, + x4_selfIdx); + } } void CGameArea::SetChain(CGameArea* other, int) diff --git a/Runtime/World/CGameArea.hpp b/Runtime/World/CGameArea.hpp index ecc60dac1..3528af156 100644 --- a/Runtime/World/CGameArea.hpp +++ b/Runtime/World/CGameArea.hpp @@ -7,6 +7,7 @@ #include "CToken.hpp" #include "RetroTypes.hpp" #include "IGameArea.hpp" +#include "CAreaOctTree.hpp" #include "hecl/ClientProcess.hpp" #include "Graphics/CMetroidModelInstance.hpp" @@ -85,9 +86,8 @@ public: { std::unique_ptr x0_; u32 x8_ = 0; - std::unique_ptr xc_; - bool x48_owns = false; - std::vector x4c_; + std::experimental::optional xc_octTree; + std::vector x4c_insts; std::unique_ptr x5c_; //std::vector x60_; //std::vector x70_;