C++ 如何从四面体网格中提取曲面三角形?

C++ 如何从四面体网格中提取曲面三角形?,c++,unity3d,3d,rendering,game-physics,C++,Unity3d,3d,Rendering,Game Physics,我想用一些3D软件渲染一个四面体网格。但是,我无法在我选择的软件(例如Blender)中直接加载四面体网格,因为不支持我用于四面体网格的文件格式。所以我应该自己用相应的顶点索引来提取这些面 对于立方体,我的四面体文件包含每个四面体的顶点ID,其中包括4个面,如下所示: v 0.41 0.41 0.41 v 0.41 0.41 -0.41 v 0.41 -0.41 0.41 v 0.41 -0.41 -0.41 v -0.41 0.41 0.41 v -0.41 0.41 -0.41 v -0.4

我想用一些3D软件渲染一个四面体网格。但是,我无法在我选择的软件(例如Blender)中直接加载四面体网格,因为不支持我用于四面体网格的文件格式。所以我应该自己用相应的顶点索引来提取这些面

对于立方体,我的四面体文件包含每个四面体的顶点ID,其中包括4个面,如下所示:

v 0.41 0.41 0.41
v 0.41 0.41 -0.41
v 0.41 -0.41 0.41
v 0.41 -0.41 -0.41
v -0.41 0.41 0.41
v -0.41 0.41 -0.41
v -0.41 -0.41 0.41
v -0.41 -0.41 -0.41
t 0 1 2 4
t 5 1 4 7
t 1 2 4 7
t 3 1 7 2
t 6 4 2 7

但是,我不确定如何在给定这些数据的情况下提取曲面网格。有人知道我怎么做吗?或者算法是什么?

这里有一个简单的暴力方法。例如,对于每个四面体,请查看第三个四面体,
t:1 2 4 7
,通过删除每个顶点,生成四个四面体顶点中三个顶点的所有四个组合,即

face[t][0]: 1 2 4,  face[t][1]: 1 2 7,  face[t][2]: 1 4 7, face[t][3]: 2 4 7
并按升序对每个三角形的整数标签进行排序(以获得唯一性) 通过这种方式,可以从四面体网格生成所有四面体的所有面的列表(或某种数组)

现在,在刚刚生成的所有三角形面列表上运行一个循环,查找重复的面。每当一个三角形在所有三角形面列表中包含两次时,都会将其删除,因为它是一个内部三角形,即两个相邻四面体共享此三角形面,因此它是内部面而不是边界面

此过程后剩下的只是四面体网格的边界(即曲面)三角形面

下面是一个用python编写的算法示例

将numpy导入为np
def列表_面(t):
t、 排序(轴=1)
n_t,m_t=t形
f=np.empty((4*n_t,3),dtype=int)
i=0
对于范围(4)内的j:
f[i:i+n_t,0:j]=t[:,0:j]
f[i:i+n_t,j:3]=t[:,j+1:4]
i=i+n\t
返回f
def提取唯一三角形(t):
_,indxs,count=np.unique(t,axis=0,return\u index=True,return\u counts=True)
返回t[indxs[count==1]]
def提取表面(t):
f=列表面(t)
f=提取唯一的三角形(f)
返回f
V=np.数组([
[ 0.41,  0.41,  0.41],
[ 0.41,  0.41, -0.41],
[ 0.41, -0.41,  0.41],
[ 0.41, -0.41, -0.41],
[-0.41,  0.41,  0.41],
[-0.41,  0.41, -0.41],
[-0.41, -0.41,  0.41],
[-0.41, -0.41, -0.41]])
T=np.array([
[0, 1, 2, 4],
[5, 1, 4, 7],
[1, 2, 4, 7],
[3, 1, 7, 2],
[6, 4, 2, 7]])
F_all=列表_面(T)
打印(全部)
打印(F_all.shape)
F\u surf=提取曲面(T)
打印(F_surf)
打印(F_曲面形状)

<代码> > p>一种非常有效的方法是使用python中的哈希集(AK<代码> SET/CODE >,<代码> STD::uncordEdSub < /C> C++中,<代码> HasSET/<代码>生锈)< /P> 从四面体体积中检索封套的原理与检索三角形曲面的轮廓相同()

这在python中提供了以下代码,可以使用哈希集轻松地在任何语言中进行翻译(为了简单起见,在这里使用python):

envelope=set()
对于四面体中的tet:
对于面in((tet[0],tet[1],tet[2]),
(tet[0],tet[2],tet[3]),
(tet[0],tet[3],tet[2]),
(tet[1],tet[3],tet[2]):
#如果已经遇到面,则它不在信封上
#哈希集的魔力使该检查为O(1)(如极快)
如果面在信封中:信封。删除(面)
#如果尚未遇到,请将其添加为翻转
其他:信封。添加((面[2],面[1],面[0]))
#现在只会遇到一次面(对于自相矛盾的网格,会遇到奇数次)
回信信封

每条v线都是某个顶点的x y z坐标。每条t线是三角形或四边形顶点的第一个、第二个、第三个或第四个索引。当你知道顶点位置和顶点如何连接成三角形时,这是一个很好的创建统一网格的教程。@Ruzihm我知道每条
v
线的意思,但我不知道如何从每条
t
线中获得4个面为什么不共享生成文件的代码或应用程序?@Ruzihm我没有访问权限。我只有这些四面体网格文件,我不明白的是为什么你说这有4个面,但我看到5。。还有,为什么这些面显然都是由4个顶点而不是3个顶点组成的。。。如果它是一个四面体,它不应该只有4个顶点和4个面吗?