void generateInteriorExteriorVoxelGrid()

in src/esp/geo/VoxelUtils.cpp [9:88]


void generateInteriorExteriorVoxelGrid(
    std::shared_ptr<esp::geo::VoxelWrapper>& voxelWrapper) {
  // create 6 bool grids
  auto v_grid = voxelWrapper->getVoxelGrid();
  auto boundaryGrid = v_grid->getGrid<bool>("Boundary");

  auto m_voxelGridDimensions = v_grid->getVoxelGridDimensions();
  // Create a temporary grid (unregistered) to hold 6 booleans for each cell -
  // each for a specified direction of raycasts
  std::size_t dims[3]{static_cast<std::size_t>(m_voxelGridDimensions[0]),
                      static_cast<std::size_t>(m_voxelGridDimensions[1]),
                      static_cast<std::size_t>(m_voxelGridDimensions[2])};
  Corrade::Containers::Array<char> cr_grid{
      Corrade::ValueInit, v_grid->gridSize() * sizeof(Mn::Math::BoolVector<6>)};
  auto shadowGrid_ =
      Cr::Containers::StridedArrayView<3, Mn::Math::BoolVector<6>>{
          Cr::Containers::arrayCast<Mn::Math::BoolVector<6>>(cr_grid), dims};

  // fill each grid with ray cast
  bool hit = false;
  int ind = 0;
  int increment = 0;
  Mn::Vector3i indices;
  for (int castAxis = 0; castAxis < 3; ++castAxis) {
    int a1 = castAxis != 0 ? 0 : 1;
    int a2 = castAxis == 2 ? 1 : 2;
    for (int j = 0; j < m_voxelGridDimensions[a1]; j++) {
      for (int k = 0; k < m_voxelGridDimensions[a2]; k++) {
        indices[a1] = j;
        indices[a2] = k;
        // fill from front and back of each 1D slice
        for (int direction = -1; direction < 2; direction += 2) {  //-1 and 1
          hit = false;
          ind = (direction > 0 ? 0 : m_voxelGridDimensions[castAxis] - 1);
          while (ind >= 0 && ind < m_voxelGridDimensions[castAxis]) {
            indices[castAxis] = ind;
            hit = (hit || boundaryGrid[indices[0]][indices[1]][indices[2]]);
            if (hit)
              shadowGrid_[indices[0]][indices[1]][indices[2]].set(
                  castAxis * 2 + (direction < 0 ? 0 : 1), true);
            ind += direction;
          }
        }
      }
    }
  }

  // create int grid
  std::string gridName = "InteriorExterior";
  v_grid->addGrid<int>(gridName);
  auto intExtGrid = v_grid->getGrid<int>(gridName);
  bool nX = false, pX = false, nY = false, pY = false, nZ = false, pZ = false;
  // fill in int grid with voting approach
  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++) {
        Mn::Vector3i index = Mn::Vector3i(i, j, k);
        if (boundaryGrid[i][j][k]) {
          intExtGrid[i][j][k] = 0;
          continue;
        }
        nX = !shadowGrid_[i][j][k][0];
        pX = !shadowGrid_[i][j][k][1];
        nY = !shadowGrid_[i][j][k][2];
        pY = !shadowGrid_[i][j][k][3];
        nZ = !shadowGrid_[i][j][k][4];
        pZ = !shadowGrid_[i][j][k][5];
        // || ((nX || pX) && (nY || pY) && (nZ || pZ))
        if (((nX && pX) || (nY && pY) || (nZ && pZ)) ||
            ((nX || pX) && (nY || pY) && (nZ || pZ))) {
          // Exterior (+inf)
          intExtGrid[i][j][k] = INT_MAX;
        } else {
          // Interior (-inf)
          intExtGrid[i][j][k] = INT_MIN;
        }
      }
    }
  }
}