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

Maya Python API:OpenMaya.MItMeshPolygon.center()调用及多组件定位问题

问题:OpenMaya API获取选中组件中心的问题

初始问题描述

刚接触Python版OpenMaya API,已完成基础教程任务,现在想实现用Maya命令做过的「获取多边形组件中心」功能。确认可以用OpenMaya.MItMeshPolygon.center()方法,但调用时出错:

尝试直接调用类方法:

import maya.api.OpenMaya as om

coordValue = om.MItMeshPolygon.center(om.MSpace.kWorld)
print(coordValue)      # 期望获取选中面的中心
# Error: TypeError: descriptor 'center' for 'OpenMaya.MItMeshPolygon' objects doesn't apply to a 'int' object

因为kWorld实际是整数(输出为4),尝试直接传整数仍报错:

import maya.api.OpenMaya as om

print(om.MSpace.kWorld)                        # 输出4
coordValue = om.MItMeshPolygon.center(4)       # 期望获取选中面的中心
print(coordValue)

使用Maya 2026,查阅Devkit示例未找到解决方法。

已尝试的进展(编辑1)

经摸索写出部分可行代码,但仅在选中面时符合预期;选中边或顶点时,仍会创建面中心的定位器:

import maya.api.OpenMaya as om
import maya.cmds as cmds
def get_selected_center():
    selection = om.MGlobal.getActiveSelectionList()
    if selection.length() == 0:
        raise RuntimeError("Nothing selected")
    dag_path, component = selection.getComponent(0)
    if not dag_path.node().apiType() == om.MFn.kMesh:
        raise RuntimeError("Selected object is not a mesh")
    poly_iter = om.MItMeshPolygon(dag_path, component)
    
    center = poly_iter.center(om.MSpace.kWorld)
    return center

center = get_selected_center()     # 返回一个三维坐标值
cmds.spaceLocator(p=(center.x, center.y, center.z))

需求:选中多边形面、边或顶点时,分别在对应中心(顶点则为自身位置)创建定位器。


解决方案

1. 初始错误原因

MItMeshPolygon.center()是实例方法,不是类方法——必须先创建MItMeshPolygon的实例(绑定到具体的网格和组件),才能调用该方法。直接用om.MItMeshPolygon.center()调用类的方法,会因为缺少实例上下文而报错。

2. 支持多组件类型的完整实现

需要根据选中的组件类型(顶点/边/面),使用对应的迭代器,并计算对应中心:

  • 顶点:用MItMeshVertex获取顶点位置
  • 边:用MItMeshEdge.center()获取边中心
  • 面:用MItMeshPolygon.center()获取面中心

同时支持单个或多个选中组件(每个组件都创建对应定位器):

import maya.api.OpenMaya as om
import maya.cmds as cmds

def create_center_locators():
    selection = om.MGlobal.getActiveSelectionList()
    if selection.length() == 0:
        raise RuntimeError("Nothing selected")
    
    # 遍历选中的每个对象-组件对
    for i in range(selection.length()):
        dag_path, component = selection.getComponent(i)
        
        # 检查是否为网格对象
        if dag_path.node().apiType() != om.MFn.kMesh:
            print(f"Skipping non-mesh object: {dag_path.partialPathName()}")
            continue
        
        # 判断组件类型,选择对应的迭代器
        comp_fn = om.MFnSingleIndexedComponent(component)
        comp_type = comp_fn.componentType
        
        if comp_type == om.MFn.kMeshVertComponent:
            iter = om.MItMeshVertex(dag_path, component)
            while not iter.isDone():
                pos = iter.position(om.MSpace.kWorld)
                cmds.spaceLocator(p=(pos.x, pos.y, pos.z))
                iter.next()
        elif comp_type == om.MFn.kMeshEdgeComponent:
            iter = om.MItMeshEdge(dag_path, component)
            while not iter.isDone():
                center = iter.center(om.MSpace.kWorld)
                cmds.spaceLocator(p=(center.x, center.y, center.z))
                iter.next()
        elif comp_type == om.MFn.kMeshPolygonComponent:
            iter = om.MItMeshPolygon(dag_path, component)
            while not iter.isDone():
                center = iter.center(om.MSpace.kWorld)
                cmds.spaceLocator(p=(center.x, center.y, center.z))
                iter.next()
        else:
            print(f"Unsupported component type: {comp_type}")

# 执行函数
create_center_locators()

代码说明

  • 使用MFnSingleIndexedComponent获取组件类型,判断是顶点、边还是面
  • 针对不同组件类型初始化对应的迭代器,遍历每个选中的组件
  • 每个组件都创建对应的定位器:顶点直接取位置,边和面取中心
  • 加入了非网格对象的跳过逻辑,以及不支持组件类型的提示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 03:33:18