in src/esp/geo/VoxelUtils.cpp [90:185]
void generateManhattanDistanceSDF(
std::shared_ptr<esp::geo::VoxelWrapper>& voxelWrapper,
const std::string& gridName) {
// check to see if Interior/Exterior grid exists, if not, generate it
auto v_grid = voxelWrapper->getVoxelGrid();
auto m_voxelGridDimensions = v_grid->getVoxelGridDimensions();
if (!v_grid->gridExists("InteriorExterior")) {
generateInteriorExteriorVoxelGrid(voxelWrapper);
}
// create new intGrid and copy data from interior/exterior grid
v_grid->addGrid<int>(gridName);
auto intExtGrid = v_grid->getGrid<int>("InteriorExterior");
auto sdfGrid = v_grid->getGrid<int>(gridName);
Cr::Utility::copy(intExtGrid, sdfGrid);
// 1st sweep
for (int i = 0; i < m_voxelGridDimensions[0]; i++) {
for (int j = 0; j < m_voxelGridDimensions[1]; j++) {
for (int k = 0; k < m_voxelGridDimensions[2]; k++) {
int i_behind = INT_MAX, j_behind = INT_MAX, k_behind = INT_MAX;
if (v_grid->isValidIndex(Mn::Vector3i(i - 1, j, k))) {
i_behind = abs(std::max(sdfGrid[i - 1][j][k], -INT_MAX));
}
if (v_grid->isValidIndex(Mn::Vector3i(i, j - 1, k))) {
j_behind = abs(std::max(sdfGrid[i][j - 1][k], -INT_MAX));
}
if (v_grid->isValidIndex(Mn::Vector3i(i, j, k - 1))) {
k_behind = abs(std::max(sdfGrid[i][j][k - 1], -INT_MAX));
}
int curVal = sdfGrid[i][j][k];
int closest = 0;
if (i_behind <= j_behind && i_behind <= k_behind) {
// i_behind is closest to nearest obstacle.
closest = i_behind;
} else if (j_behind <= i_behind && j_behind <= k_behind) {
// j_behind is closest to nearest obstacle.
closest = j_behind;
} else {
// k_behind is closest or tied for closest to nearest obstacle.
closest = k_behind;
}
// Get the minimum of the cell that's closest to an obstacle and the
// current distance to an obstacle, and multiply by the true sign of
// curVal
if (closest == INT_MAX)
closest--;
curVal = (static_cast<int>(curVal > 0) - static_cast<int>(curVal < 0)) *
std::min(abs(std::max(curVal, -INT_MAX)), closest + 1);
sdfGrid[i][j][k] = curVal;
}
}
}
// second sweep
for (int i = m_voxelGridDimensions[0] - 1; i >= 0; i--) {
for (int j = m_voxelGridDimensions[1] - 1; j >= 0; j--) {
for (int k = m_voxelGridDimensions[2] - 1; k >= 0; k--) {
int curVal = sdfGrid[i][j][k];
if (curVal == 0)
continue;
int i_ahead = INT_MAX, j_ahead = INT_MAX, k_ahead = INT_MAX;
if (v_grid->isValidIndex(Mn::Vector3i(i + 1, j, k))) {
i_ahead = abs(std::max(sdfGrid[i + 1][j][k], -INT_MAX));
}
if (v_grid->isValidIndex(Mn::Vector3i(i, j + 1, k))) {
j_ahead = abs(std::max(sdfGrid[i][j + 1][k], -INT_MAX));
}
if (v_grid->isValidIndex(Mn::Vector3i(i, j, k + 1))) {
k_ahead = abs(std::max(sdfGrid[i][j][k + 1], -INT_MAX));
}
int closest = INT_MAX - 1;
if (i_ahead <= j_ahead && i_ahead <= k_ahead) {
// i_ahead is closest to nearest obstacle.
closest = i_ahead;
} else if (j_ahead <= i_ahead && j_ahead <= k_ahead) {
// j_ahead is closest to nearest obstacle.
closest = j_ahead;
} else {
// k_ahead is closest or tied for closest to nearest obstacle.
closest = k_ahead;
}
// Get the minimum of the cell that's closest to an obstacle and the
// current distance to an obstacle, and multiply by the true sign of
// curVal
if (closest == INT_MAX)
closest--;
curVal = (static_cast<int>(curVal > 0) - static_cast<int>(curVal < 0)) *
std::min(abs(std::max(curVal, -INT_MAX)), closest + 1);
sdfGrid[i][j][k] = curVal;
}
}
}
}