Как исправить 'TypeError: в методе' MFnMesh_anyIntersection ', аргумент 4 типа' MIntArray const * ', ошибка в Python в Maya - PullRequest
0 голосов
/ 15 октября 2019

Я хотел бы попробовать лучевое вещание с Python в Maya, используя OpenMaya.MFnMesh.anyIntersection () .

Я просто хочу навести луч от объекта вниз и ударить по плоскостиЯ не могу идти дальше, поэтому я получаю только один raycasthit и получаю значения перевода от raycasthit.

Я получил код из видео и сделал его немного более понятным для понимания.

ДляДля правильной работы в Maya вам нужен объект, который находится выше по оси Y, чем другой, предпочтительно polyPlane (например: наличие polySphere в позиции [0, 3, 0] и polyPlane в позиции [0,0, 0], выберите polySphere и запустите код)

import maya.OpenMaya as OpenMaya
import maya.cmds as cmds

def RayReposition(*args):
    direction = (0.0, -1, 0)
    sel = cmds.ls(sl = True)

    fromPositionRay = cmds.xform(sel[0], query = True, translation = True)
    selShape = cmds.listRelatives(shapes = True)
    meshes = cmds.ls(geometry = True)

    cmds.select(clear = True)

    for x in meshes:
        if x == selShape[0]:
            continue
        else:
            OpenMaya.MGlobal.selectByName(x)
            sList = OpenMaya.MSelectionList()

            OpenMaya.MGlobal.getActiveSelectionList(sList)
            item = OpenMaya.MDagPath()
            sList.getDagPath(0, item)
            item.extendToShape()

            fnMesh = OpenMaya.MFnMesh(item)

            raySource = OpenMaya.MFloatPoint(fromPositionRay[0], fromPositionRay[1], fromPositionRay[2], 1.0)
            rayDir = OpenMaya.MFloatVector(direction[0], direction[1], direction[2])
            faceIds = None
            triIds = None
            idsSorted = False
            testBothDirections = False
            worldSpace = OpenMaya.MSpace.kWorld
            maxParam = 999999
            accelParams = None
            sortHits = True
            hitPoints = OpenMaya.MFloatPointArray()

            hitRayParams = OpenMaya.MFloatArray()
            hitFaces = OpenMaya.MIntArray()
            hitTris = None
            hitBarys1 = None
            hitBarys2 = None
            tolerance = 0.0001

            hit = fnMesh.anyIntersection(raySource, rayDir, worldSpace, maxParam, testBothDirections, faceIds, triIds, idsSorted, accelParams, tolerance, hitPoints, hitRayParams, hitFaces, hitTris, hitBarys1, hitBarys2)

            OpenMaya.MGlobal.clearSelectionList()
            firstHit = (hitPoints[0].x, hitPoints[0].y, hitPoints[0].z)
            print firstHit

RayReposition()

Я ожидал получить значения перевода из raycasthit, но я получаю следующую ошибку:

TypeError: in method 'MFnMesh_anyIntersection', argument 4 of type 'MIntArray const *'

Использование OpenMaya.MFnMesh.allIntersections () * Функция 1016 * взамен прекрасно работает, но я получаю каждый удар из raycast, но мне нужен только первый удар.

Ссылки наOpenMayaAPI .MFnMesh: ссылка: https://help.autodesk.com/view/MAYAUL/2016/ENU/?guid=__py_ref_class_open_maya_1_1_m_fn_mesh_html

1 Ответ

2 голосов
/ 15 октября 2019

Главное, что anyIntersection ищет одиночное пересечение, которое оно встречает первым, а не несколько. Таким образом, ваши out-параметры имеют неправильные типы, потому что они являются массивами.

Я бы также не стал очищать или делать новые выборки в цикле, поскольку это просто замедляло бы производительность из-за необходимости каждый раз перерисовывать области просмотра.

Вот рабочий пример, который создаст локатор для первого меша, к которому он попадет:

import maya.OpenMaya as OpenMaya
import maya.cmds as cmds


def RayReposition(*args):
    direction = (0.0, -1, 0)
    sel = cmds.ls(sl=True)

    fromPositionRay = cmds.xform(sel[0], query=True, translation=True)
    selShape = cmds.listRelatives(shapes=True)
    meshes = cmds.ls(geometry=True)

    for x in meshes:
        if x == selShape[0]:
            continue
        else:
            sList = OpenMaya.MSelectionList()
            sList.add(x)
            item = OpenMaya.MDagPath()
            sList.getDagPath(0, item)
            item.extendToShape()

            fnMesh = OpenMaya.MFnMesh(item)

            raySource = OpenMaya.MFloatPoint(fromPositionRay[0], fromPositionRay[1], fromPositionRay[2], 1.0)
            rayDir = OpenMaya.MFloatVector(direction[0], direction[1], direction[2])
            worldSpace = OpenMaya.MSpace.kWorld
            maxParam = 999999
            testBothDirections = False
            faceIds = None
            triIds = None
            idsSorted = False
            accelParams = None
            sortHits = True

            hitPoints = OpenMaya.MFloatPoint()
            hitRayParams = None
            hitFaces = None
            hitTris = None
            hitBarys1 = None
            hitBarys2 = None
            tolerance = 0.0001

            hit = fnMesh.anyIntersection(
                raySource, rayDir, faceIds, triIds, idsSorted, worldSpace, maxParam, testBothDirections, accelParams, 
                hitPoints, hitRayParams, hitFaces, hitTris, hitBarys1, hitBarys2, tolerance)

            if hit:
                firstHit = (hitPoints.x, hitPoints.y, hitPoints.z)
                loc = cmds.spaceLocator()[0]
                cmds.xform(loc, ws=True, t=firstHit)
                print "Hit on {} at {}".format(x, firstHit)
                break


RayReposition()

Я нахожу документацию c ++ немного более ясной, чем метод ожидаетдля параметров.

...