You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mxs技术问询:按边界拆分收集网格开放边至多维数组

解决MaxScript中网格开放边按边界环分组的问题

没问题,这需求很明确——要把网格里的开放边按独立的边界环(比如孔洞的边缘)拆分成对应的子数组对吧?我写了个MaxScript脚本,完美实现这个功能,还加了详细注释,你可以直接用:

fn getBoundaryEdgeLoops targetMesh =
(
    -- 存储最终的边界环数组,每个子数组对应一个边界的边索引
    local boundaryLoops = #()
    
    -- 提前获取网格的边总数,方便后续操作
    local edgeCount = targetMesh.numEdges
    
    -- 第一步:收集所有开放边的索引
    local openEdges = #()
    for e in 1 to edgeCount do
    (
        if targetMesh.openEdge[e] do append openEdges e
    )
    
    -- 如果没有开放边,直接返回空数组
    if openEdges.count == 0 do return boundaryLoops
    
    -- 创建一个数组标记边是否已被处理,避免重复遍历
    local visitedEdges = #(false) * (edgeCount + 1) -- 边索引从1开始,所以多开一个位置
    
    -- 第二步:遍历所有开放边,分组连通的边形成边界环
    for startEdge in openEdges do
    (
        -- 如果这条边已经被处理过,跳过
        if visitedEdges[startEdge] do continue
        
        -- 初始化当前边界环的数组
        local currentLoop = #()
        -- 当前处理的边,从起始边开始
        local currentEdge = startEdge
        
        -- 记录起始边的第一个顶点,用于判断环是否闭合
        local startVert = targetMesh.getEdgeVert currentEdge 1
        
        while true do
        (
            -- 将当前边加入环数组,并标记为已访问
            append currentLoop currentEdge
            visitedEdges[currentEdge] = true
            
            -- 获取当前边的两个顶点
            local vert1 = targetMesh.getEdgeVert currentEdge 1
            local vert2 = targetMesh.getEdgeVert currentEdge 2
            
            -- 找下一条连通的开放边:从vert2出发,找未被访问的开放边
            local nextEdge = undefined
            for e in openEdges do
            (
                if not visitedEdges[e] do
                (
                    local eVert1 = targetMesh.getEdgeVert e 1
                    local eVert2 = targetMesh.getEdgeVert e 2
                    -- 判断这条边是否和当前边的vert2相连
                    if (eVert1 == vert2) or (eVert2 == vert2) do
                    (
                        nextEdge = e
                        exit -- 找到就跳出循环
                    )
                )
            )
            
            -- 如果找不到下一条边,检查是否回到起始顶点(闭合环)
            if nextEdge == undefined do
            (
                -- 最后一条边的第二个顶点应该和起始顶点一致,确保环闭合
                if vert2 == startVert do break
                -- 特殊情况:如果是不闭合的边界?不过Max里的开放边环应该都是闭合的(比如孔洞)
                -- 如果遇到不闭合的,也直接结束当前环
                break
            )
            
            -- 更新当前边为找到的下一条边
            currentEdge = nextEdge
        )
        
        -- 将当前边界环加入结果数组
        append boundaryLoops currentLoop
    )
    
    -- 返回分组后的边界环数组
    return boundaryLoops
)

-- 示例用法:选中一个网格对象后运行
if selection.count == 1 and classof selection[1] == Editable_Mesh do
(
    local meshObj = selection[1]
    local loops = getBoundaryEdgeLoops meshObj
    
    print "找到的边界环数量:" + loops.count as string
    for i in 1 to loops.count do
    (
        print ("边界环 " + i as string + " 的边索引:" + loops[i] as string)
    )
)
else
(
    print "请选中一个Editable Mesh对象!"
)

脚本说明:

  • 核心逻辑:先筛选出所有开放边,然后通过遍历连通的开放边,把属于同一个边界环的边归到同一个子数组里,用visitedEdges数组避免重复处理。
  • 适配性:不管网格有几个孔洞(边界环),都会自动分成对应的子数组,比如2个孔洞就返回包含2个子数组的数组。
  • 使用方式:选中一个Editable Mesh对象,运行脚本即可,控制台会输出每个边界环的边索引。

如果你的网格是Poly对象,只需要先转换成Editable Mesh(或者修改脚本里的判断和边的获取方式,不过上面的脚本用Editable Mesh更稳定)。

内容的提问来源于stack exchange,提问作者Maarten -Monica for president

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:16:53