mirror of https://github.com/AxioDL/metaforce.git
92 lines
2.5 KiB
C++
92 lines
2.5 KiB
C++
#include "Runtime/Graphics/CPVSVisSet.hpp"
|
|
|
|
#include "Runtime/Graphics/CPVSVisOctree.hpp"
|
|
|
|
namespace metaforce {
|
|
|
|
void CPVSVisSet::Reset(EPVSVisSetState state) {
|
|
x0_state = state;
|
|
x4_numBits = 0;
|
|
x8_numLights = 0;
|
|
// xc_ = false;
|
|
x10_ptr = nullptr;
|
|
}
|
|
|
|
EPVSVisSetState CPVSVisSet::GetVisible(u32 idx) const {
|
|
if (x0_state != EPVSVisSetState::NodeFound)
|
|
return x0_state;
|
|
|
|
u32 numFeatures = x4_numBits - x8_numLights;
|
|
if (idx < numFeatures) {
|
|
/* This is a feature lookup */
|
|
if (!(x10_ptr[idx / 8] & (1 << (idx & 0x7))))
|
|
return EPVSVisSetState::EndOfTree;
|
|
return EPVSVisSetState::OutOfBounds;
|
|
}
|
|
|
|
/* This is a light lookup */
|
|
u32 lightTest = idx - numFeatures + idx;
|
|
const u8* ptr = &x10_ptr[lightTest / 8];
|
|
lightTest &= 0x7;
|
|
if (lightTest != 0x7)
|
|
return EPVSVisSetState((ptr[0] & (0x3 << lightTest)) >> lightTest);
|
|
return EPVSVisSetState((ptr[0] >> 7) | ((ptr[1] & 0x1) << 1));
|
|
}
|
|
|
|
void CPVSVisSet::SetFromMemory(u32 numBits, u32 numLights, const u8* leafPtr) {
|
|
x0_state = EPVSVisSetState::NodeFound;
|
|
x4_numBits = numBits;
|
|
x8_numLights = numLights;
|
|
x10_ptr = leafPtr;
|
|
}
|
|
|
|
void CPVSVisSet::SetTestPoint(const CPVSVisOctree& octree, const zeus::CVector3f& point) {
|
|
if (!octree.GetBounds().pointInside(point)) {
|
|
Reset(EPVSVisSetState::OutOfBounds);
|
|
return;
|
|
}
|
|
|
|
const u8* octCur = octree.GetOctreeData();
|
|
octree.ResetSearch();
|
|
s32 nextNodeRel;
|
|
u8 curNode;
|
|
while ((nextNodeRel = octree.IterateSearch((curNode = *octCur++), point)) != -1) {
|
|
if (nextNodeRel) {
|
|
/* Skip node data */
|
|
if (!(curNode & 0x60)) {
|
|
octCur += hecl::SBig(reinterpret_cast<const u16*>(octCur)[nextNodeRel - 1]);
|
|
} else if (curNode & 0x20) {
|
|
octCur += *(octCur + nextNodeRel - 1);
|
|
} else {
|
|
const u8* tmp = octCur + (nextNodeRel - 1) * 3;
|
|
octCur += (tmp[0] << 16) + (tmp[1] << 8) + tmp[2];
|
|
}
|
|
}
|
|
|
|
/* Skip children data */
|
|
if (!(curNode & 0x60)) {
|
|
octCur += (octree.GetNumChildren(curNode) - 1) * 2;
|
|
} else if (curNode & 0x20) {
|
|
octCur += octree.GetNumChildren(curNode) - 1;
|
|
} else {
|
|
octCur += (octree.GetNumChildren(curNode) - 1) * 3;
|
|
}
|
|
}
|
|
|
|
/* Handle leaf type */
|
|
switch (curNode & 0x18) {
|
|
case 0x18:
|
|
SetFromMemory(octree.GetNumObjects(), octree.GetNumLights(), octCur);
|
|
break;
|
|
case 0x10:
|
|
Reset(EPVSVisSetState::EndOfTree);
|
|
break;
|
|
case 0x08:
|
|
default:
|
|
Reset(EPVSVisSetState::OutOfBounds);
|
|
break;
|
|
}
|
|
}
|
|
|
|
} // namespace metaforce
|