1. 背景:
最近因为项目需要,需要阅读 Blender 中关于 mesh boolean 的源码;因此,对 blender 中的 mesh boolean 源码进行解读;
Github 上源码下载很慢,一般使用 Gitee: gitee Blender 源码
2. Mesh Boolean 核心源码位置:
Blender 的 mesh boolean 的源码,主要在工程:blenlib 这个工程中 的 BLI_mesh_boolean.h 文件中;
BoolOpType 主要包含:Intersect: 交;Union: 并; Difference: 差三种模式;
/**
* Enum values after BOOLEAN_NONE need to match BMESH_ISECT_BOOLEAN_... values in
* `editmesh_intersect.cc`.
*/
enum class BoolOpType {
None = -1,
/* Aligned with #BooleanModifierOp. */
Intersect = 0,
Union = 1,
Difference = 2,
};
3. 核心函数
核心函数:boolean_mesh 以及 boolean_trimesh 这两个函数;boolean_trimesh 调用的是 boolean_mesh 实现,输入参数 IMesh 需要是三角面片;
IMesh boolean_mesh(IMesh &imesh,
BoolOpType op,
int nshapes,
FunctionRef<int(int)> shape_fn,
bool use_self,
bool hole_tolerant,
IMesh *imesh_triangulated,
IMeshArena *arena);
boolean_mesh 的文件注释如:
对网格 pm_in 执行布尔运算运算。
布尔运算具有 \a nshapes 输入形状。每个网格都是输入网格的不相交子集。shape_fn 参数在应用于输入面参数时,表示它位于哪个形状中(应该是从 -1 到 : 如果为 -1,则它不是任何形状的一部分)。
use_self 参数表示函数是否应该假设相同形状的
面相交 - 如果参数为 true,则会找到此类自交集。
有时调用者已经进行了三角剖分;
如果是这样,则 *pm_triangulated 包含一个三角剖分:如果非 null,则它包含一个三角形网格
,每个三角形的 orig_field 表示该三角形属于 pm 中的哪个面。
pm 参数不是因为我们可以填充它的顶点(用于调试)。pm_triangulated 参数也是如此。
输出 #IMesh 将具有其原始字段映射回输入网格中的
面和边的面
4. 核心函数实现分析:
boolean_mesh 的具体实现步骤:
step 1: 如果输入参数 imesh_triangulated 为 null, 则对 imesh 进行三角面片化
our_triangulation = triangulate_polymesh(imesh, arena);
IMesh *tm_in = imesh_triangulated;
IMesh our_triangulation;
if (tm_in == nullptr) {
our_triangulation = triangulate_polymesh(imesh, arena);
tm_in = &our_triangulation;
}
step2: 执行 boolean_trimesh 函数
IMesh tm_out = boolean_trimesh(*tm_in, op, nshapes, shape_fn, use_self, hole_tolerant, arena);
step3: 对三角面片进行后处理
布尔函数对三角形 #IMesh 进行操作,并生成一个
IMesh 作为输出Triangle;这个函数通过删除任何可能的三角剖分边(可以识别,是因为它们将具有 NO_INDEX 的原始边。并非所有三角剖分边都可以删除:如果它们最终真实的输入边,那么我们需要保留它。此外,有些是使输出满足所必需的“valid #BMesh(有效)”属性:我们无法生成它们,或者具有多个不相连的边界(例如,带有孔的面)。
IMesh ans = polymesh_from_trimesh_with_dissolve(tm_out, imesh, arena);
6. boolean_trimesh 原理分析:
IMesh boolean_trimesh(IMesh &tm_in,
BoolOpType op,
int nshapes,
FunctionRef<int(int)> shape_fn,
bool use_self,
bool hole_tolerant,
IMeshArena *arena);
} // namespace blender::meshintersect