diff --git a/Runtime/CObjectList.hpp b/Runtime/CObjectList.hpp index 9ee5783d5..aaebff5b3 100644 --- a/Runtime/CObjectList.hpp +++ b/Runtime/CObjectList.hpp @@ -9,6 +9,7 @@ namespace urde enum class EGameObjectList { + Invalid = -1, All, Actor, PhysicsActor, @@ -21,6 +22,8 @@ enum class EGameObjectList class CObjectList { + friend class CGameArea; + struct SObjectListEntry { CEntity* entity = nullptr; @@ -31,6 +34,7 @@ class CObjectList EGameObjectList m_listEnum; TUniqueId m_lastId = -1; u16 m_count = 0; + int m_areaIdx = 0; public: CObjectList(EGameObjectList listEnum); diff --git a/Runtime/CStateManager.hpp b/Runtime/CStateManager.hpp index 8abcff324..dbf19126c 100644 --- a/Runtime/CStateManager.hpp +++ b/Runtime/CStateManager.hpp @@ -253,6 +253,8 @@ public: CCameraManager* GetCameraManager() { return x870_cameraManager.get(); } std::shared_ptr MapWorldInfo() { return x8c0_mapWorldInfo; } + + bool IsLayerActive(TAreaId area, int layerIdx) { return false; } }; } diff --git a/Runtime/Collision/CAreaOctTree.hpp b/Runtime/Collision/CAreaOctTree.hpp index e8cef7c7c..cde3a28e9 100644 --- a/Runtime/Collision/CAreaOctTree.hpp +++ b/Runtime/Collision/CAreaOctTree.hpp @@ -130,20 +130,6 @@ public: const u16* GetTriangleEdgeIndices(u16 idx) const; static std::unique_ptr MakeFromMemory(void* buf, unsigned int size); - - void RecursiveMatchXray(std::vector& out, const zeus::CAABox& inner, const zeus::CAABox& outer) - { - if (outer.intersects(inner)) - { - if (inner.inside(outer)) - { - } - } - } - - void MatchXray(std::vector& out, const zeus::CAABox&) - { - } }; } diff --git a/Runtime/Graphics/CBooRenderer.cpp b/Runtime/Graphics/CBooRenderer.cpp index 99cd891d8..cffb95bc8 100644 --- a/Runtime/Graphics/CBooRenderer.cpp +++ b/Runtime/Graphics/CBooRenderer.cpp @@ -140,7 +140,7 @@ void Buckets::Init() } CBooRenderer::CAreaListItem::CAreaListItem -(const std::vector* geom, const CAreaOctTree* octTree, +(const std::vector* geom, const CAreaRenderOctTree* octTree, std::vector&& models, int areaIdx) : x0_geometry(geom), x4_octTree(octTree), x10_models(std::move(models)), x18_areaIdx(areaIdx) {} @@ -331,7 +331,7 @@ CBooRenderer::FindStaticGeometry(const std::vector* geome } void CBooRenderer::AddStaticGeometry(const std::vector* geometry, - const CAreaOctTree* octTree, int areaIdx) + const CAreaRenderOctTree* octTree, int areaIdx) { auto search = FindStaticGeometry(geometry); if (search == x1c_areaListItems.end()) @@ -598,12 +598,36 @@ void CBooRenderer::DrawThermalModel(const CModel& model, const zeus::CColor& mul model.Draw(flags); } -void CBooRenderer::DrawXRayOutline(const zeus::CAABox&, const float*, const float*) +void CBooRenderer::DrawXRayOutline(const zeus::CAABox& aabb) { + CModelFlags flags; + flags.m_extendedShaderIdx = 3; + for (CAreaListItem& item : x1c_areaListItems) { if (item.x4_octTree) { + std::vector bitmap; + item.x4_octTree->FindOverlappingModels(bitmap, aabb); + + for (u32 c=0 ; cx14_bitmapWordCount ; ++c) + { + for (u32 b=0 ; b<32 ; ++b) + { + if (bitmap[c] & (1 << b)) + { + CBooModel* model = item.x10_models[c * 32 + b]; + model->UpdateUniformData(flags); + const CBooSurface* surf = model->x38_firstUnsortedSurface; + while (surf) + { + if (surf->GetBounds().intersects(aabb)) + model->DrawSurface(*surf, flags); + surf = surf->m_next; + } + } + } + } } } } diff --git a/Runtime/Graphics/CBooRenderer.hpp b/Runtime/Graphics/CBooRenderer.hpp index 553ef8a33..115bd483f 100644 --- a/Runtime/Graphics/CBooRenderer.hpp +++ b/Runtime/Graphics/CBooRenderer.hpp @@ -11,6 +11,7 @@ #include "CRandom16.hpp" #include "CPVSVisSet.hpp" #include "zeus/CRectangle.hpp" +#include "World/CGameArea.hpp" namespace urde { @@ -51,13 +52,13 @@ class CBooRenderer : public IRenderer struct CAreaListItem { const std::vector* x0_geometry; - const CAreaOctTree* x4_octTree; + const CAreaRenderOctTree* x4_octTree; //std::vector> x8_textures; std::vector x10_models; int x18_areaIdx; std::vector x20_; - CAreaListItem(const std::vector* geom, const CAreaOctTree* octTree, + CAreaListItem(const std::vector* geom, const CAreaRenderOctTree* octTree, std::vector&& models, int areaIdx); ~CAreaListItem(); }; @@ -140,7 +141,7 @@ public: void AddWorldSurfaces(CBooModel& model); std::list::iterator FindStaticGeometry(const std::vector*); - void AddStaticGeometry(const std::vector*, const CAreaOctTree*, int areaIdx); + void AddStaticGeometry(const std::vector*, const CAreaRenderOctTree*, int areaIdx); void EnablePVS(const CPVSVisSet*, u32); void DisablePVS(); void RemoveStaticGeometry(const std::vector*); @@ -187,7 +188,7 @@ public: //void CacheReflection(TReflectionCallback, void*, bool); void DrawSpaceWarp(const zeus::CVector3f&, float); void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol); - void DrawXRayOutline(const zeus::CAABox&, const float*, const float*); + void DrawXRayOutline(const zeus::CAABox&); void SetWireframeFlags(int); void SetWorldFog(ERglFogMode, float, float, const zeus::CColor&); void RenderFogVolume(const zeus::CColor&, const zeus::CAABox&, const TLockedToken*, const CSkinnedModel*); diff --git a/Runtime/Graphics/CPVSAreaSet.cpp b/Runtime/Graphics/CPVSAreaSet.cpp index aa9b86046..44609e4a3 100644 --- a/Runtime/Graphics/CPVSAreaSet.cpp +++ b/Runtime/Graphics/CPVSAreaSet.cpp @@ -3,6 +3,10 @@ namespace urde { +CPVSAreaSet::CPVSAreaHolder::CPVSAreaHolder(CInputStream& in) +{ +} + CPVSAreaSet::CPVSAreaSet(CInputStream& in) { } diff --git a/Runtime/Graphics/CPVSAreaSet.hpp b/Runtime/Graphics/CPVSAreaSet.hpp index 6fb8dc042..b1a890303 100644 --- a/Runtime/Graphics/CPVSAreaSet.hpp +++ b/Runtime/Graphics/CPVSAreaSet.hpp @@ -8,10 +8,12 @@ namespace urde class CPVSAreaSet { +public: struct CPVSAreaHolder { CPVSAreaHolder(CInputStream& in); }; +private: std::vector xunk; public: CPVSAreaSet(CInputStream& in); diff --git a/Runtime/Graphics/IRenderer.hpp b/Runtime/Graphics/IRenderer.hpp index e231c3da5..32231f55c 100644 --- a/Runtime/Graphics/IRenderer.hpp +++ b/Runtime/Graphics/IRenderer.hpp @@ -18,6 +18,7 @@ class CParticleGen; class CModel; class CSkinnedModel; class CPVSVisSet; +class CAreaRenderOctTree; class IRenderer { @@ -41,7 +42,7 @@ public: }; virtual ~IRenderer() = default; - virtual void AddStaticGeometry(const std::vector*, const CAreaOctTree*, int)=0; + virtual void AddStaticGeometry(const std::vector*, const CAreaRenderOctTree*, int)=0; virtual void EnablePVS(const CPVSVisSet*, u32)=0; virtual void DisablePVS()=0; virtual void RemoveStaticGeometry(const std::vector*)=0; @@ -88,7 +89,7 @@ public: //virtual void CacheReflection(TReflectionCallback, void*, bool)=0; virtual void DrawSpaceWarp(const zeus::CVector3f&, float)=0; virtual void DrawThermalModel(const CModel&, const zeus::CColor&, const zeus::CColor&)=0; - virtual void DrawXRayOutline(const zeus::CAABox&, const float*, const float*)=0; + virtual void DrawXRayOutline(const zeus::CAABox&)=0; virtual void SetWireframeFlags(int)=0; virtual void SetWorldFog(ERglFogMode, float, float, const zeus::CColor&)=0; virtual void RenderFogVolume(const zeus::CColor&, const zeus::CAABox&, const TLockedToken*, const CSkinnedModel*)=0; diff --git a/Runtime/World/CGameArea.cpp b/Runtime/World/CGameArea.cpp index 595f129d0..6b6cf19e6 100644 --- a/Runtime/World/CGameArea.cpp +++ b/Runtime/World/CGameArea.cpp @@ -4,10 +4,177 @@ #include "CGameArea.hpp" #include "GameGlobalObjects.hpp" #include "Graphics/CBooRenderer.hpp" +#include "CSimplePool.hpp" +#include "CStateManager.hpp" namespace urde { +CAreaRenderOctTree::CAreaRenderOctTree(std::unique_ptr&& buf) +: x0_buf(std::move(buf)) +{ + athena::io::MemoryReader r(x0_buf.get() + 8, INT32_MAX); + x8_bitmapCount = r.readUint32Big(); + xc_meshCount = r.readUint32Big(); + x10_nodeCount = r.readUint32Big(); + x14_bitmapWordCount = (xc_meshCount + 31) / 32; + x18_aabb.readBoundingBoxBig(r); + + x30_bitmaps = reinterpret_cast(x0_buf.get() + 64); + u32 wc = x14_bitmapWordCount * x8_bitmapCount; + for (int i=0 ; i(x34_indirectionTable) + x10_nodeCount; + for (int i=0 ; i(x38_entries + x34_indirectionTable[i]); + n->x0_bitmapIdx = hecl::SBig(n->x0_bitmapIdx); + n->x2_flags = hecl::SBig(n->x2_flags); + if (n->x2_flags) + { + u32 childCount = n->GetChildCount(); + for (u32 c=0 ; cx4_children[c] = hecl::SBig(n->x4_children[c]); + } + } +} + +static const u32 ChildCounts[] = { 0, 2, 2, 4, 2, 4, 4, 8 }; +u32 CAreaRenderOctTree::Node::GetChildCount() const +{ + return ChildCounts[x2_flags]; +} + +zeus::CAABox CAreaRenderOctTree::Node::GetNodeBounds(const zeus::CAABox& curAABB, int idx) const +{ + zeus::CVector3f center = curAABB.center(); + switch (x2_flags) + { + case 0: + default: + return curAABB; + case 1: + if (idx == 0) + return {curAABB.min.x, curAABB.min.y, curAABB.min.z, center.x, curAABB.max.y, curAABB.max.z}; + else + return {center.x, curAABB.min.y, curAABB.min.z, curAABB.max.x, curAABB.max.y, curAABB.max.z}; + case 2: + if (idx == 0) + return {curAABB.min.x, curAABB.min.y, curAABB.min.z, curAABB.max.x, center.y, curAABB.max.z}; + else + return {curAABB.min.x, center.y, curAABB.min.z, curAABB.max.x, curAABB.max.y, curAABB.max.z}; + case 3: + { + switch (idx) + { + case 0: + default: + return {curAABB.min.x, curAABB.min.y, curAABB.min.z, center.x, center.y, curAABB.max.z}; + case 1: + return {center.x, curAABB.min.y, curAABB.min.z, curAABB.max.x, center.y, curAABB.max.z}; + case 2: + return {curAABB.min.x, center.y, curAABB.min.z, center.x, curAABB.max.y, curAABB.max.z}; + case 3: + return {center.x, center.y, curAABB.min.z, curAABB.max.x, curAABB.max.y, curAABB.max.z}; + } + } + case 4: + if (idx == 0) + return {curAABB.min.x, curAABB.min.y, curAABB.min.z, curAABB.max.x, curAABB.max.y, center.z}; + else + return {curAABB.min.x, curAABB.min.y, center.z, curAABB.max.x, curAABB.max.y, curAABB.max.z}; + case 5: + { + switch (idx) + { + case 0: + default: + return {curAABB.min.x, curAABB.min.y, curAABB.min.z, center.x, curAABB.max.y, center.z}; + case 1: + return {center.x, curAABB.min.y, curAABB.min.z, curAABB.max.x, curAABB.max.y, center.z}; + case 2: + return {curAABB.min.x, curAABB.min.y, center.z, center.x, curAABB.max.y, curAABB.max.z}; + case 3: + return {center.x, curAABB.min.y, center.z, curAABB.max.x, curAABB.max.y, curAABB.max.z}; + } + } + case 6: + { + switch (idx) + { + case 0: + default: + return {curAABB.min.x, curAABB.min.y, curAABB.min.z, curAABB.max.x, center.y, center.z}; + case 1: + return {curAABB.min.x, center.y, curAABB.min.z, curAABB.max.x, curAABB.max.y, center.z}; + case 2: + return {curAABB.min.x, curAABB.min.y, center.z, curAABB.max.x, center.y, curAABB.max.z}; + case 3: + return {curAABB.min.x, center.y, center.z, curAABB.max.x, curAABB.max.y, curAABB.max.z}; + } + } + case 7: + { + switch (idx) + { + case 0: + default: + return {curAABB.min.x, curAABB.min.y, curAABB.min.z, center.x, center.y, center.z}; + case 1: + return {center.x, curAABB.min.y, curAABB.min.z, curAABB.max.x, center.y, center.z}; + case 2: + return {curAABB.min.x, center.y, curAABB.min.z, center.x, curAABB.max.y, center.z}; + case 3: + return {center.x, center.y, curAABB.min.z, curAABB.max.x, curAABB.max.y, center.z}; + case 4: + return {curAABB.min.x, curAABB.min.y, center.z, center.x, center.y, curAABB.max.z}; + case 5: + return {center.x, curAABB.min.y, center.z, curAABB.max.x, center.y, curAABB.max.z}; + case 6: + return {curAABB.min.x, center.y, center.z, center.x, curAABB.max.y, curAABB.max.z}; + case 7: + return {center.x, center.y, center.z, curAABB.max.x, curAABB.max.y, curAABB.max.z}; + } + } + } +} + +void CAreaRenderOctTree::Node::RecursiveBuildOverlaps(u32* bmpOut, + const CAreaRenderOctTree& parent, + const zeus::CAABox& curAABB, + const zeus::CAABox& testAABB) const +{ + if (testAABB.intersects(curAABB)) + { + if (curAABB.inside(testAABB)) + { + const u32* bmp = &parent.x30_bitmaps[x0_bitmapIdx * parent.x14_bitmapWordCount]; + for (u32 c=0 ; c(parent.x38_entries[parent.x34_indirectionTable[x4_children[c]]])-> + RecursiveBuildOverlaps(bmpOut, parent, childAABB, testAABB); + } + } + } +} + +void CAreaRenderOctTree::FindOverlappingModels(std::vector& out, const zeus::CAABox& testAABB) const +{ + out.resize(x14_bitmapWordCount); + reinterpret_cast(x38_entries[x34_indirectionTable[0]])-> + RecursiveBuildOverlaps(out.data(), *this, x18_aabb, testAABB); +} + void CGameArea::CAreaFog::SetCurrent() const { } @@ -39,6 +206,19 @@ void CGameArea::CAreaFog::DisableFog() { } +static std::vector ReadDependencyList(CInputStream& in) +{ + std::vector ret; + u32 count = in.readUint32Big(); + ret.reserve(count); + for (u32 i=0 ; i 13) + { + u32 depCount = in.readUint32Big(); + for (u32 i=0 ; i ReadDependencyList(CInputStream& in) -{ - std::vector ret; - u32 count = in.readUint32Big(); - ret.reserve(count); - for (u32 i=0 ; i 13) + { + u32 depCount = in.readUint32Big(); + xbc_layerDepOffsets.reserve(depCount); + for (u32 i=0 ; iResourceSize(*tok.GetObjectTag()); + + xec_totalResourcesSize += g_ResFactory->ResourceSize(SObjectTag{FOURCC('MREA'), x84_mrea}); } bool CGameArea::IGetScriptingMemoryAlways() const @@ -306,18 +501,172 @@ bool CGameArea::Validate(CStateManager& mgr) void CGameArea::PostConstructArea() { + MREAHeader header = VerifyHeader(); + + auto secIt = x110_mreaSecBufs.begin() + 2; + + /* Models */ + if (header.modelCount) + { + for (int i=0 ; i((secIt+6)->first.get())); + secIt += 7 + surfCount; + } + } + + /* Render octree */ + if (header.version == 15 && header.arotSecIdx != -1) + { + x12c_postConstructed->xc_octTree.emplace(std::move(secIt->first)); + ++secIt; + } + + /* Scriptable layer section */ + x12c_postConstructed->x10c8_sclyBuf = std::move(secIt->first); + x12c_postConstructed->x10d0_sclySize = secIt->second; + ++secIt; + + /* Collision section */ + std::unique_ptr collision = CAreaOctTree::MakeFromMemory(secIt->first.get(), secIt->second); + if (collision) + { + x12c_postConstructed->x0_collision = std::move(collision); + x12c_postConstructed->x8_collisionSize = secIt->second; + } + ++secIt; + + /* Unknown section */ + ++secIt; + + /* Lights section */ + if (header.version > 6) + { + athena::io::MemoryReader r(secIt->first.get(), secIt->second); + u32 magic = r.readUint32Big(); + if (magic == 0xBABEDEAD) + { + u32 aCount = r.readUint32Big(); + x12c_postConstructed->x60_lightsA.reserve(aCount); + x12c_postConstructed->x70_gfxLightsA.reserve(aCount); + for (u32 i=0 ; ix60_lightsA.emplace_back(r); + x12c_postConstructed->x70_gfxLightsA.push_back( + x12c_postConstructed->x60_lightsA.back().GetAsCGraphicsLight()); + } + + u32 bCount = r.readUint32Big(); + x12c_postConstructed->x80_lightsB.reserve(bCount); + x12c_postConstructed->x90_gfxLightsB.reserve(bCount); + for (u32 i=0 ; ix80_lightsB.emplace_back(r); + x12c_postConstructed->x90_gfxLightsB.push_back( + x12c_postConstructed->x80_lightsB.back().GetAsCGraphicsLight()); + } + } + + ++secIt; + } + + /* PVS section */ + if (header.version > 7) + { + athena::io::MemoryReader r(secIt->first.get(), secIt->second); + u32 magic = r.readUint32Big(); + if (magic == 'VISI') + { + x12c_postConstructed->x10a8_pvsVersion = r.readUint32Big(); + if (x12c_postConstructed->x10a8_pvsVersion == 2) + { + x12c_postConstructed->x1108_29_ = r.readBool(); + x12c_postConstructed->x1108_30_ = r.readBool(); + x12c_postConstructed->xa0_pvs.reset(new CPVSAreaSet::CPVSAreaHolder(r)); + } + } + + ++secIt; + } + + /* Pathfinding section */ + if (header.version > 9) + { + athena::io::MemoryReader r(secIt->first.get(), secIt->second); + ResId pathId = r.readUint32Big(); + x12c_postConstructed->x10ac_path = g_SimplePool->GetObj(SObjectTag{FOURCC('PATH'), pathId}); + ++secIt; + } + + x12c_postConstructed->x10c0_areaObjs.reset(new CObjectList(EGameObjectList::Invalid)); + x12c_postConstructed->x10c0_areaObjs->m_areaIdx = x4_selfIdx; + + x12c_postConstructed->x10c4_areaFog.reset(new CAreaFog()); + + xf0_24_postConstructed = true; + + /* Resolve layer pointers */ + if (x12c_postConstructed->x10c8_sclyBuf) + { + athena::io::MemoryReader r(x12c_postConstructed->x10c8_sclyBuf.get(), x12c_postConstructed->x10d0_sclySize); + u32 magic = r.readUint32Big(); + if (magic == 'SCLY') + { + r.readUint32Big(); + u32 layerCount = r.readUint32Big(); + x12c_postConstructed->x110c_layerPtrs.resize(layerCount); + for (u32 l=0 ; lx110c_layerPtrs[l].second = r.readUint32Big(); + u8* ptr = x12c_postConstructed->x10c8_sclyBuf.get() + r.position(); + for (u32 l=0 ; lx110c_layerPtrs[l].first = ptr; + ptr += x12c_postConstructed->x110c_layerPtrs[l].second; + } + } + } } void CGameArea::FillInStaticGeometry() { } -void CGameArea::VerifyTokenList() +void CGameArea::VerifyTokenList(CStateManager& stateMgr) { + if (xdc_tokens.empty()) + return; + ClearTokenList(); + + if (xac_deps2.empty()) + return; + + u32 lastOff = 0; + int lidx = 0; + for (u32 off : xbc_layerDepOffsets) + { + if (stateMgr.IsLayerActive(x4_selfIdx, lidx)) + { + auto it = xac_deps2.begin() + lastOff; + auto end = xac_deps2.begin() + off; + for (; it != end ; ++it) + { + xdc_tokens.push_back(g_SimplePool->GetObj(*it)); + xdc_tokens.back().Lock(); + } + } + lastOff = off; + ++lidx; + } } void CGameArea::ClearTokenList() { + if (xdc_tokens.empty()) + xdc_tokens.reserve(xac_deps2.size()); + else + xdc_tokens.clear(); + + xf0_26_tokensReady = 0; } u32 CGameArea::GetPreConstructedSize() const @@ -325,9 +674,37 @@ u32 CGameArea::GetPreConstructedSize() const return 0; } -bool CGameArea::VerifyHeader() const +CGameArea::MREAHeader CGameArea::VerifyHeader() const { - return false; + if (x110_mreaSecBufs.empty()) + return {}; + if (*reinterpret_cast(x110_mreaSecBufs[0].first.get()) != SBIG(0xDEADBEEF)) + return {}; + + MREAHeader header; + athena::io::MemoryReader r(x110_mreaSecBufs[0].first.get() + 4, INT32_MAX); + u32 version = r.readUint32Big(); + header.version = (version >= 12 && version <= 15) ? version : 0; + if (!header.version) + return {}; + + header.xf.read34RowMajor(r); + header.modelCount = r.readUint32Big(); + header.secCount = r.readUint32Big(); + header.geomSecIdx = r.readUint32Big(); + header.sclySecIdx = r.readUint32Big(); + header.collisionSecIdx = r.readUint32Big(); + header.unkSecIdx = r.readUint32Big(); + header.lightSecIdx = r.readUint32Big(); + header.visiSecIdx = r.readUint32Big(); + header.pathSecIdx = r.readUint32Big(); + header.arotSecIdx = r.readUint32Big(); + + header.secSizes.reserve(header.secCount); + for (int i=0 ; i x0_buf; + u32 x8_bitmapCount; + u32 xc_meshCount; + u32 x10_nodeCount; + u32 x14_bitmapWordCount; + zeus::CAABox x18_aabb; + u32* x30_bitmaps; + u32* x34_indirectionTable; + u8* x38_entries; + + CAreaRenderOctTree(std::unique_ptr&& buf); + + void FindOverlappingModels(std::vector& out, const zeus::CAABox& testAABB) const; +}; + class CGameArea : public IGameArea { friend class CWorld; @@ -60,7 +94,7 @@ class CGameArea : public IGameArea std::vector x9c_deps1; std::vector xac_deps2; - std::vector xbc_; + std::vector xbc_layerDepOffsets; std::vector xcc_docks; std::vector xdc_tokens; @@ -72,7 +106,7 @@ class CGameArea : public IGameArea { bool xf0_24_postConstructed : 1; bool xf0_25_active : 1; - bool xf0_26_ : 1; + bool xf0_26_tokensReady : 1; bool xf0_27_ : 1; bool xf0_28_ : 1; }; @@ -82,32 +116,51 @@ class CGameArea : public IGameArea std::list> xf8_loadTransactions; public: + class CAreaFog + { + zeus::CVector2f x4_ = {0.f, 1024.f}; + zeus::CVector2f xc_ = {0.f, 1024.f}; + zeus::CVector2f x14_; + zeus::CVector3f x1c_ = {0.5f}; + zeus::CVector3f x28_ = {0.5f}; + float x34_ = 0.f; + public: + void SetCurrent() const; + void Update(float dt); + void RollFogOut(float, float, const zeus::CColor& color); + void FadeFog(ERglFogMode, const zeus::CColor& color, const zeus::CVector2f& vec1, + float, const zeus::CVector2f& vec2); + void SetFogExplicit(ERglFogMode, const zeus::CColor& color, const zeus::CVector2f& vec); + bool IsFogDisabled() const; + void DisableFog(); + }; + struct CPostConstructed { - std::unique_ptr x0_; - u32 x8_ = 0; - std::experimental::optional xc_octTree; + std::unique_ptr x0_collision; + u32 x8_collisionSize = 0; + std::experimental::optional xc_octTree; std::vector x4c_insts; - std::unique_ptr x5c_; - //std::vector x60_; - //std::vector x70_; - //std::vector x80_; - //std::vector x90_; - std::unique_ptr xa0_; + //std::unique_ptr x5c_; + std::vector x60_lightsA; + std::vector x70_gfxLightsA; + std::vector x80_lightsB; + std::vector x90_gfxLightsB; + std::unique_ptr xa0_pvs; u32 xa4_elemCount = 1024; struct MapEntry { s16 x0_id = -1; TUniqueId x4_uid = kInvalidUniqueId; } xa8_map[1024]; - u32 x10a8_ = 0; - CToken x10ac_; + u32 x10a8_pvsVersion = 0; + TLockedToken x10ac_path; // bool x10b8_ = 0; optional flag for CToken u32 x10bc_ = 0; - std::unique_ptr x10c0_; - std::unique_ptr x10c4_; - std::unique_ptr x10c8_; - u32 x10d0_ = 0; + std::unique_ptr x10c0_areaObjs; + std::unique_ptr x10c4_areaFog; + std::unique_ptr x10c8_sclyBuf; + u32 x10d0_sclySize = 0; u32 x10d4_ = 0; u32 x10d8_ = 0; u32 x10dc_ = 0; @@ -131,7 +184,7 @@ public: }; u8 _dummy = 0; }; - // std::vector x110c_; + std::vector> x110c_layerPtrs; float x111c_thermalCurrent = 0.f; float x1120_thermalSpeed = 0.f; float x1124_thermalTarget = 0.f; @@ -143,11 +196,29 @@ public: u32 x113c_ = 0; }; private: + std::vector, int>> x110_mreaSecBufs; std::unique_ptr x12c_postConstructed; void UpdateFog(float dt); void UpdateThermalVisor(float dt); + struct MREAHeader + { + u32 version = 0; + zeus::CTransform xf; + u32 modelCount; + u32 secCount; + u32 geomSecIdx; + u32 sclySecIdx; + u32 collisionSecIdx; + u32 unkSecIdx; + u32 lightSecIdx; + u32 visiSecIdx; + u32 pathSecIdx; + u32 arotSecIdx; + std::vector secSizes; + }; + public: struct CAreaObjectList : public IAreaObjectList @@ -159,25 +230,6 @@ public: { }; - class CAreaFog - { - zeus::CVector2f x4_ = {0.f, 1024.f}; - zeus::CVector2f xc_ = {0.f, 1024.f}; - zeus::CVector2f x14_; - zeus::CVector3f x1c_ = {0.5f}; - zeus::CVector3f x28_ = {0.5f}; - float x34_ = 0.f; - public: - void SetCurrent() const; - void Update(float dt); - void RollFogOut(float, float, const zeus::CColor& color); - void FadeFog(ERglFogMode, const zeus::CColor& color, const zeus::CVector2f& vec1, - float, const zeus::CVector2f& vec2); - void SetFogExplicit(ERglFogMode, const zeus::CColor& color, const zeus::CVector2f& vec); - bool IsFogDisabled() const; - void DisableFog(); - }; - CGameArea(CInputStream& in, int idx, int mlvlVersion); bool IsFinishedOccluding() const; @@ -215,10 +267,10 @@ public: bool Validate(CStateManager& mgr); void PostConstructArea(); void FillInStaticGeometry(); - void VerifyTokenList(); + void VerifyTokenList(CStateManager& stateMgr); void ClearTokenList(); u32 GetPreConstructedSize() const; - bool VerifyHeader() const; + MREAHeader VerifyHeader() const; const zeus::CTransform& GetTransform() const {return xc_transform;} const zeus::CTransform& GetInverseTransform() const {return x3c_invTransform;}