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

Maya脚本:Shape Node转OBJ的顶点/三角面提取及四边面转三角面问题

Maya Shape Node 批量转 OBJ(自动三角化四边面)

一、正确获取三角面顶点索引的方法

你之前用OpenMaya.MFnMesh.getTriangles()没成功,大概率是没正确初始化MFnMesh对象。以下是靠谱的实现方式:

import maya.OpenMaya as om

def get_triangle_indices(shape_name):
    # 获取shape node的MObject
    sel_list = om.MSelectionList()
    sel_list.add(shape_name)
    mesh_obj = om.MObject()
    sel_list.getDependNode(0, mesh_obj)
    
    # 初始化MFnMesh
    mesh_fn = om.MFnMesh(mesh_obj)
    
    # 获取三角面数据:tri_counts是每个面的三角数量,tri_verts是所有三角的顶点索引
    tri_counts = om.MIntArray()
    tri_verts = om.MIntArray()
    mesh_fn.getTriangles(tri_counts, tri_verts)
    
    # 把tri_verts拆成三元组(每个三角的三个顶点索引)
    triangle_indices = []
    idx = 0
    for count in tri_counts:
        for _ in range(count):
            triangle = (tri_verts[idx], tri_verts[idx+1], tri_verts[idx+2])
            triangle_indices.append(triangle)
            idx += 3
    return triangle_indices

注意:如果原模型有四边面,getTriangles()会自动把四边面拆成两个三角面返回索引,不需要手动处理。

二、完整的Shape Node转OBJ脚本(含四边面三角化)

如果不想自己写OBJ文件的写入逻辑,可以结合Maya内置命令先三角化模型,再批量导出每个shape:

import maya.cmds as cmds
import os

def export_shapes_to_obj(export_dir):
    # 创建导出目录
    if not os.path.exists(export_dir):
        os.makedirs(export_dir)
    
    # 获取所有可见的mesh shape node(排除中间节点)
    shape_nodes = cmds.ls(type='mesh', visible=True, long=True)
    # 过滤掉不是直接关联transform的shape(比如历史节点)
    shape_nodes = [s for s in shape_nodes if cmds.listRelatives(s, parent=True, type='transform')]
    
    for shape in shape_nodes:
        # 获取父transform的名称,作为导出文件名
        transform = cmds.listRelatives(shape, parent=True)[0]
        obj_path = os.path.join(export_dir, f"{transform}.obj")
        
        # 临时三角化当前shape(创建新的三角化shape,保留原模型)
        tri_shape = cmds.polyTriangulate(shape, ch=False, keepOriginal=True)[0]
        
        # 单独导出这个三角化后的shape
        cmds.select(tri_shape)
        cmds.exportSelected(obj_path, type="OBJexport", 
                            options="groups=0;ptgroups=0;materials=0;smoothing=0;normals=1",
                            force=True)
        
        # 删除临时三角化的shape
        cmds.delete(tri_shape)

# 使用示例:替换成你的导出路径
export_shapes_to_obj("D:/Maya_Exports/OBJ_Files")

脚本说明:

  • polyTriangulate(shape, ch=False, keepOriginal=True):对原shape进行三角化,生成新的三角面shape,不修改原模型
  • 导出选项options:关闭组、材质、平滑组,保留法线,符合标准OBJ格式
  • 自动遍历所有可见的mesh shape,每个单独导出为OBJ,文件名用父transform的名称

三、手动写入OBJ文件的方式(适合自定义格式)

如果你需要完全手动控制OBJ内容,可以结合顶点坐标和三角索引来生成:

import maya.OpenMaya as om
import os

def write_shape_to_obj(shape_name, obj_path):
    # 获取shape的MObject
    sel_list = om.MSelectionList()
    sel_list.add(shape_name)
    mesh_obj = om.MObject()
    sel_list.getDependNode(0, mesh_obj)
    mesh_fn = om.MFnMesh(mesh_obj)
    
    # 获取顶点坐标
    points = om.MPointArray()
    mesh_fn.getPoints(points, om.MSpace.kWorld)  # 换成kObject可获取局部坐标
    
    # 获取三角面索引
    tri_counts = om.MIntArray()
    tri_verts = om.MIntArray()
    mesh_fn.getTriangles(tri_counts, tri_verts)
    
    # 写入OBJ文件
    with open(obj_path, 'w') as f:
        # 写入顶点
        for i in range(points.length()):
            p = points[i]
            f.write(f"v {p.x} {p.y} {p.z}\n")
        
        # 写入三角面(OBJ索引从1开始,所以要+1)
        idx = 0
        for count in tri_counts:
            for _ in range(count):
                v1 = tri_verts[idx] + 1
                v2 = tri_verts[idx+1] + 1
                v3 = tri_verts[idx+2] + 1
                f.write(f"f {v1} {v2} {v3}\n")
                idx += 3

# 使用示例
write_shape_to_obj("pSphereShape1", "D:/test.obj")

内容的提问来源于stack exchange,提问作者user8469759

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 02:55:34