#include "CAreaOctTree.hpp" namespace urde { CAreaOctTree::Node CAreaOctTree::Node::GetChild(int idx) const { u16 flags = *reinterpret_cast(m_ptr); const u32* offsets = reinterpret_cast(m_ptr + 4); ETreeType type = ETreeType((flags >> (2 * idx)) & 0x3); if (type == ETreeType::Branch) { zeus::CAABox pos, neg, res; m_aabb.splitZ(pos, neg); if (idx & 4) { pos.splitY(pos, neg); if (idx & 2) { pos.splitX(pos, neg); if (idx & 1) res = pos; else res = neg; } else { neg.splitX(pos, neg); if (idx & 1) res = pos; else res = neg; } } else { neg.splitY(pos, neg); if (idx & 2) { pos.splitX(pos, neg); if (idx & 1) res = pos; else res = neg; } else { neg.splitX(pos, neg); if (idx & 1) res = pos; else res = neg; } } return Node(m_ptr + offsets[idx] + 36, res, m_owner, ETreeType::Branch); } else if (type == ETreeType::Leaf) { const float* aabb = reinterpret_cast(m_ptr + offsets[idx] + 36); zeus::CAABox aabbObj(aabb[0], aabb[1], aabb[2], aabb[3], aabb[4], aabb[5]); return Node(aabb, aabbObj, m_owner, ETreeType::Leaf); } else { return Node(nullptr, zeus::CAABox::skNullBox, m_owner, ETreeType::Invalid); } } void CAreaOctTree::SwapTreeNode(u8* ptr, Node::ETreeType type) { if (type == Node::ETreeType::Branch) { u16* typeBits = reinterpret_cast(ptr); *typeBits = hecl::SBig(*typeBits); u32* offsets = reinterpret_cast(ptr + 4); for (int i=0 ; i<8 ; ++i) { Node::ETreeType ctype = Node::ETreeType((*typeBits >> (2 * i)) & 0x3); offsets[i] = hecl::SBig(offsets[i]); SwapTreeNode(ptr + offsets[i] + 36, ctype); } } else if (type == Node::ETreeType::Leaf) { float* aabb = reinterpret_cast(ptr); aabb[0] = hecl::SBig(aabb[0]); aabb[1] = hecl::SBig(aabb[1]); aabb[2] = hecl::SBig(aabb[2]); aabb[3] = hecl::SBig(aabb[3]); aabb[4] = hecl::SBig(aabb[4]); aabb[5] = hecl::SBig(aabb[5]); u16* countIdxs = reinterpret_cast(ptr + 24); *countIdxs = hecl::SBig(*countIdxs); for (u16 i=0 ; i<*countIdxs ; ++i) countIdxs[i+1] = hecl::SBig(countIdxs[i+1]); } } CAreaOctTree::CAreaOctTree(const zeus::CAABox& aabb, Node::ETreeType treeType, const u8* buf, const u8* treeBuf, u32 matCount, const u32* materials, const u8* vertMats, const u8* edgeMats, const u8* polyMats, u32 edgeCount, const CCollisionEdge* edges, u32 polyCount, const u16* polyEdges, u32 vertCount, const float* verts) : x0_aabb(aabb), x18_treeType(treeType), x1c_buf(buf), x20_treeBuf(treeBuf), x24_matCount(matCount), x28_materials(materials), x2c_vertMats(vertMats), x30_edgeMats(edgeMats), x34_polyMats(polyMats), x38_edgeCount(edgeCount), x3c_edges(edges), x40_polyCount(polyCount), x44_polyEdges(polyEdges), x48_vertCount(vertCount), x4c_verts(verts) { SwapTreeNode(const_cast(x20_treeBuf), treeType); for (u32 i=0 ; i(x28_materials)[i] = hecl::SBig(x28_materials[i]); for (u32 i=0 ; i(x3c_edges)[i].swapBig(); for (u32 i=0 ; i(x44_polyEdges)[i] = hecl::SBig(x44_polyEdges[i]); for (u32 i=0 ; i(x4c_verts)[i] = hecl::SBig(x4c_verts[i]); } std::unique_ptr CAreaOctTree::MakeFromMemory(const u8* buf, unsigned int size) { athena::io::MemoryReader r(buf + 8, size - 8); r.readUint32Big(); r.readUint32Big(); zeus::CAABox aabb; aabb.readBoundingBoxBig(r); Node::ETreeType nodeType = Node::ETreeType(r.readUint32Big()); u32 treeSize = r.readUint32Big(); const u8* cur = reinterpret_cast(buf) + 8 + r.position(); const u8* treeBuf = cur; cur += treeSize; u32 matCount = hecl::SBig(*reinterpret_cast(cur)); cur += 4; const u32* matBuf = reinterpret_cast(cur); cur += 4 * matCount; u32 vertMatsCount = hecl::SBig(*reinterpret_cast(cur)); cur += 4; const u8* vertMatsBuf = cur; cur += vertMatsCount; u32 edgeMatsCount = hecl::SBig(*reinterpret_cast(cur)); cur += 4; const u8* edgeMatsBuf = cur; cur += edgeMatsCount; u32 polyMatsCount = hecl::SBig(*reinterpret_cast(cur)); cur += 4; const u8* polyMatsBuf = cur; cur += polyMatsCount; u32 edgeCount = hecl::SBig(*reinterpret_cast(cur)); cur += 4; const CCollisionEdge* edgeBuf = reinterpret_cast(cur); cur += edgeCount * sizeof(edgeCount); u32 polyCount = hecl::SBig(*reinterpret_cast(cur)); cur += 4; const u16* polyBuf = reinterpret_cast(cur); cur += polyCount * 2; u32 vertCount = hecl::SBig(*reinterpret_cast(cur)); cur += 4; const float* vertBuf = reinterpret_cast(cur); return std::make_unique(aabb, nodeType, reinterpret_cast(buf + 8), treeBuf, matCount, matBuf, vertMatsBuf, edgeMatsBuf, polyMatsBuf, edgeCount, edgeBuf, polyCount, polyBuf, vertCount, vertBuf); } }