凸包到体素网格

Convex Hull to Voxel Grid

我有一个给定的 3D 网格,它是通过获取一组随机点并找到这些点的凸包来构建的。然后我使用 open3d 和 trimesh 将 conex 船体转换为网格。我想知道如何将此网格或凸包本身转换为填充的布尔体素网格。

我可以使用 trimesh 获得某种体素网格,但内部似乎是空心的。我想要一个布尔体素网格,它为凸包内的体积给出 true,否则为 false。

简单地栅格化你的凸多边形体积...

  1. 计算任意内点c

    对于凸包,它足以计算平均点,所以将所有 n 点加在一起除以 n

  2. 计算每面法线

    每个三角形面有 3 个点 p0,p1,p2 所以

    nor = cross( p1-p0 , p2-p0 );
    

    并选择方向,使其指向凸包外,因此:

    if ( dot( p0-c , nor ) < 0) nor = -nor;
    
  3. 遍历所有体素

    所以 3 个嵌套 for 循环通过您的网格。让我们调用实际迭代点 q

  4. 凸包内部测试

    如果 q-face_pointface_normal 之间的所有点积都是负数或零,q 就在你的凸包内......所以遍历所有 triangles/faces 并测试...之后要么填充体素要么不填充...

如果你想要更快的东西(以防你有太多三角形),有如下方法:

  • 栅格化三角形并填充
  • 四面体化体积并分别光栅化每个四面体
  • 从外描立方体和填充的 6 个面渲染深度图

所以我想出了一个可以使用 trimmesh 实现的简单解决方案。这个想法是生成大量坐标并查询网格以确定坐标是否在 mesh/convex 船体内。如果坐标在网格内,则在网格中指示为 1,否则为 0。 res 是一个数组,用于确定沿 x、y、z 轴的分辨率。更高的分辨率提供更好的网格表示。

x, y, z = np.indices((res[0], res[1], res[2]))
total_voxels = np.product(res)
coords = np.concatenate((np.reshape(x/res[0], [total_voxels, 1]),       
         np.reshape(y/res[1], [total_voxels, 1]),
         np.reshape(z/res[2], [total_voxels, 1])), axis=1)
out = mesh.contains(coords)
voxel = np.reshape(out, res)