metaforce/Runtime/Graphics/CPVSVisSet.cpp

92 lines
2.4 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 += 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