四面体网格数据存储方式
四面体网格数据是这样存储的:
分为两部分:
第一部分:
所有顶点的三维坐标数据。
第二部分
每个四面体的顶点编号。
四面体顶点编号顺序满足外法线约定
假如我们随便指定4个顶点编号的顺序,那么四面体顶点编号,则有24种排列方式。
为什么是24种呢?首先4个顶点里任选3个组成一个面,那么有4种选法,这就代表了四个面。四个面中,每个面的三个顶点有6种排列方式,因此共有4x6=24种排列方式。
然而四面体的四个顶点顺序不是随便指定的,而是约定:
法线约定:所有面的法线方向朝外(或朝内)
(我们这里只取朝外)
这里法向的判断就是右手定则
即
(wxl)
这里我们先要进行分类讨论:
当3处于012面法向那一侧的时候(即3在底面的正面侧):
0和1和2这三个顶点,必须得是021的顺序,这样才符合外法线的约定。
而0和1和3这三个顶点,必须的是013的顺序
以此类推
0和2和3这三个顶点,必须的是032的顺序
1和2和3这三个顶点,必须的是123的顺序
即图中的a组
同理:
当3处于底面的背面侧的时候
即图中的b组
无论是a还是b,只要任意给出3个顶点,它们的顺序一定是确定了的。
因此实际上顶点的编号顺序只有2种组合(即a和b)。
提取四面体所有面
上面讲过
随意给定三个点,一定在a或b两种情况之一。
那么,对于每个四面体,我们就拥有了两组面(a或者b)。
然后再去掉a或者b其中的一种。这就需要去比较外法线和3号点是不是再同一侧了。
用01和12边叉乘,再与03点乘,假如结果为正数,就是情况a,结果为负数,就是情况b。
如何找到并剔除内部面(或提取网格的表面)
只要看有没有被共享的面即可
4个点中随意取出3点(3个点本身的顺序无关紧要,但是要保证唯一性,即012和021、120等是完全一样的,只是标识这个面)
然后看其他四面体内是否出现了这三个点即可。
具体操作:
为了保证3点的唯一性,可以使用哈希表或者C++中的unordered_set,或者人为规定一个顺序(比如升序)
然后遍历所有的四面体,取出所有的面。
最后剔除所有重复出现的面。
还可以这么干:
在遍历的同时就剔除掉重复的面,可以使用unordered_set保证唯一性(因为这个数据结构只要重复值就会自动剔除掉,是自动保证唯一性的)。