跳到主要内容

Architecture

📄️ 封闭线选择三角面并分割网格

在通过封闭曲线分割网格时,一般先将用户绘制的二维闭合线投影到三维网格表面上,得到对应的三维边路径(EdgePath)。具体实现通常是对每个 2D 线段沿视线投射到网格上,求交点并连接形成网格上的闭合路径。接下来使用 MeshTopology 中的区域提取工具:例如 MR::fillContourLeft(topology, contourEdges) 可以计算出位于边路径左侧(或右侧)的所有三角面。这样就得到被闭合线包围的面集合。最后需要根据该边界将网格拆分:一种做法是在边路径处对原三角形进行分割插入新边,然后把路径一侧的面与另一侧的面区分开来。例如,可以调用 mesh.topology.deleteFaces(outsideFaces) 删除路径外的三角面,使网格只保留选中的部分,或反之;任意拓扑修改后同样要调用 mesh.invalidateCaches() 以更新缓存。总之,利用投影得到的 EdgePath 结合 fillContourLeft(和后续的删除/复制操作),即可实现基于用户封闭线的网格分割。

📄️ 孔洞填充实现细节

在 MeshTopology 中,孔洞由只有一个邻接面的边(裸边)定义。函数 MeshTopology::fillHole(mesh, edge, params),该函数根据边界顶点自动生成一组三角形来填充孔洞。其内部流程大致是:首先从给定边出发沿孔洞边界形成多边形链,接着根据填充策略将该多边形三角化。填充策略由参数 FillHoleParams 控制,例如 maxPolygonSubdivisions(默认20)限制多边形细分的最大深度,而 FillHoleMetric 可用来评价三角形质量。最终,新生成的三角形被加入到 MeshTopology 中,消除原有的孔洞开口。简单示例代码:

📄️ 顶点/边/面 ID 的连续分配与重映射

网格元素(顶点 VertId、边 EdgeId、面 FaceId)都是以连续整数索引分配的。构造网格时(如使用 MeshTopology::deleteFaces(faceSet))会从拓扑中移除对应面,系统自动更新有效面的集合;如果直接修改了拓扑(如删面或拆分边),则需调用 mesh.invalidateCaches() 来重建缓存的法线、邻接等信息。通过这些机制,保证所有 ID 始终指向有效元素,必要时进行压缩或重建,以保持索引与底层结构一致。