mirror of https://github.com/AxioDL/metaforce.git
87 lines
3.4 KiB
C++
87 lines
3.4 KiB
C++
#include "Runtime/World/CMarkerGrid.hpp"
|
|
|
|
namespace metaforce {
|
|
CMarkerGrid::CMarkerGrid(const zeus::CAABox& bounds) : x0_bounds(bounds) {
|
|
x18_gridUnits = zeus::CVector3f((bounds.max - bounds.min) * 0.0625f);
|
|
x24_gridState.resize(0x400);
|
|
}
|
|
|
|
void CMarkerGrid::MarkCells(const zeus::CSphere& area, u32 val) {
|
|
int width_units = static_cast<int>((area.radius - x18_gridUnits.x()) / x18_gridUnits.x());
|
|
int length_units = static_cast<int>((area.radius - x18_gridUnits.y()) / x18_gridUnits.y());
|
|
int height_units = static_cast<int>((area.radius - x18_gridUnits.z()) / x18_gridUnits.z());
|
|
u32 x_coord, y_coord, z_coord;
|
|
if (!GetCoords(area.position, x_coord, y_coord, z_coord)) {
|
|
return;
|
|
}
|
|
for (int i = width_units - z_coord; i < (z_coord + width_units); i++) {
|
|
for (int j = length_units - y_coord; j < (y_coord + length_units); j++) {
|
|
for (int k = height_units - x_coord; k < (z_coord + height_units); k++) {
|
|
u32 new_cell_val = val | GetValue(x_coord, y_coord, z_coord);
|
|
SetValue(k, j, i, new_cell_val);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CMarkerGrid::GetCoords(zeus::CVector3f const& vec, u32& x, u32& y, u32& z) const {
|
|
if (x0_bounds.pointInside(vec)) {
|
|
x = static_cast<u32>((vec.x() - x0_bounds.min.x()) / x18_gridUnits.x());
|
|
y = static_cast<u32>((vec.y() - x0_bounds.min.y()) / x18_gridUnits.y());
|
|
z = static_cast<u32>((vec.z() - x0_bounds.min.z()) / x18_gridUnits.z());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
u32 CMarkerGrid::GetValue(u32 x, u32 y, u32 z) const {
|
|
const u32 bit_offset = (x & 3) << 1;
|
|
u8 marker_byte = x24_gridState[(z << 6) + (y << 2) + (x >> 2)];
|
|
return static_cast<u32>((marker_byte & (3 << bit_offset)) >> bit_offset);
|
|
}
|
|
|
|
void CMarkerGrid::SetValue(u32 x, u32 y, u32 z, u32 val) {
|
|
const u32 bit_offset = (x & 3) << 1;
|
|
const u32 grid_offset = (z << 6) + (y << 2) + (x >> 2);
|
|
u8 marker_byte = x24_gridState[grid_offset];
|
|
marker_byte |= (marker_byte & ~(3 << bit_offset)) | (val << bit_offset);
|
|
x24_gridState[grid_offset] = marker_byte;
|
|
}
|
|
|
|
bool CMarkerGrid::AABoxTouchesData(const zeus::CAABox& box, u32 val) const {
|
|
if (!x0_bounds.intersects(box)) {
|
|
return false;
|
|
}
|
|
zeus::CAABox in_box = box;
|
|
if (!box.inside(x0_bounds)) {
|
|
zeus::CVector3f max_of_min(x0_bounds.min.x() > box.min.x() ? x0_bounds.min.x() : box.min.x(),
|
|
x0_bounds.min.y() > box.min.y() ? x0_bounds.min.y() : box.min.y(),
|
|
x0_bounds.min.z() > box.min.z() ? x0_bounds.min.z() : box.min.z());
|
|
zeus::CVector3f min_of_max(x0_bounds.max.x() < box.max.x() ? x0_bounds.max.x() : box.max.x(),
|
|
x0_bounds.max.y() < box.max.y() ? x0_bounds.max.y() : box.max.y(),
|
|
x0_bounds.max.z() < box.max.z() ? x0_bounds.max.z() : box.max.z());
|
|
in_box = zeus::CAABox(max_of_min, min_of_max);
|
|
}
|
|
u32 c1x, c1y, c1z, c2x, c2y, c2z;
|
|
GetCoords(in_box.min, c1x, c1y, c1z);
|
|
GetCoords(in_box.max, c2x, c2y, c2z);
|
|
|
|
for (int i = c1z; i < c2z; i++) {
|
|
for (int j = c1y; j < c2y; j++) {
|
|
for (int k = c1x; k < c2x; k++) {
|
|
if ((GetValue(k, j, i) & val) != 0u) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
zeus::CVector3f CMarkerGrid::GetWorldPositionForCell(u32 x, u32 y, u32 z) const {
|
|
// returns the center of a given cell
|
|
return zeus::CVector3f(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)) * x18_gridUnits +
|
|
x0_bounds.min + (x18_gridUnits / 2.f);
|
|
}
|
|
} // namespace urde
|