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