// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2025 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "unique_sparse_voxel_corners.h" #include "matlab_format.h" #include "unique.h" #include #include namespace { // Match the yxz binary counting order in marching_cubes/sparse_voxel_grid const int marching_cubes_reoder[] = {1,0,2,3,5,4,6,7}; } template < typename Derivedijk, typename Derivedunique_ijk, typename DerivedJ > IGL_INLINE void igl::unique_sparse_voxel_corners( const int depth, const Eigen::MatrixBase & ijk, Eigen::PlainObjectBase & unique_ijk, Eigen::PlainObjectBase & J) { using MatrixiX3R = Eigen::Matrix; // slow, precise hashing. Not sure why I didn't just use unique_rows on #ijk*8 // by 3... const Eigen::Matrix coeffs( 1, //static_cast(std::pow(2,depth) + 1), (1 << depth) + 1, //static_cast(std::pow(2,depth) + 1) * (std::pow(2,depth) + 1)); ((1 << depth) +1)*((1 << depth) +1)); const auto ijk2code = [&coeffs](const int i, const int j, const int k)->std::int64_t { // code = i*(2.^depth + 1)^0 + j*(2.^depth + 1)^1 + k*(2.^depth + 1)^2; // Probably can just use 2.^(depth+1) instead of (2.^depth + 1) and use bit // shifting? const std::int64_t code = static_cast(i) * coeffs[0] + static_cast(j) * coeffs[1] + static_cast(k) * coeffs[2]; return code; }; const auto code2ijk = [&coeffs](const std::int64_t code, int & i, int & j, int & k) { k = static_cast(code / coeffs[2]); j = static_cast((code - k * coeffs[2]) / coeffs[1]); i = static_cast(code - j * coeffs[1] - k * coeffs[2]); }; // Should use parallel_for Eigen::Matrix codes(ijk.rows(),8); for(int c = 0;c _; Eigen::Matrix Jvec; // igl::unique has a lot of internal copies :-( igl::unique(codes,_,I,Jvec); // reshape Jvec into ijk.rows() by 8 J = Jvec.reshaped(ijk.rows(),8); } // Map of codes as vector const auto codes_vec = codes.reshaped(); unique_ijk.resize(I.size(),3); for(int c = 0;c(); } } template< typename Derivedorigin, typename Derivedijk, typename Derivedunique_ijk, typename DerivedJ, typename Derivedunique_corners > IGL_INLINE void igl::unique_sparse_voxel_corners( const Eigen::MatrixBase & origin, const typename Derivedorigin::Scalar h0, const int depth, const Eigen::MatrixBase & ijk, Eigen::PlainObjectBase & unique_ijk, Eigen::PlainObjectBase & J, Eigen::PlainObjectBase & unique_corners) { unique_sparse_voxel_corners(depth,ijk,unique_ijk,J); using Scalar = typename Derivedunique_corners::Scalar; const Scalar h = h0 / (1 << depth); unique_corners.resize(unique_ijk.rows(),3); for(int c = 0;c, Eigen::Matrix, Eigen::Matrix>(int, Eigen::MatrixBase> const&, Eigen::PlainObjectBase>&, Eigen::PlainObjectBase>&); template void igl::unique_sparse_voxel_corners, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(Eigen::MatrixBase> const&, Eigen::Matrix::Scalar, int, Eigen::MatrixBase> const&, Eigen::PlainObjectBase>&, Eigen::PlainObjectBase>&, Eigen::PlainObjectBase>&); #endif