проецирование точек на параллельную сетку на глубине от камеры (майя) - PullRequest
0 голосов
/ 03 мая 2018

Я пытаюсь создать сетку локаторов, которые служат проецируемыми точками на параллельную конечную плоскость из камеры в Майе на заданной глубине. Сетка должна соответствовать указанному разрешению, чтобы соответствовать отображаемому результату.

В данный момент мои вычисления выключены, и я ищу некоторую помощь, чтобы выяснить, насколько неверна моя формула для определения проецируемых точек.

У меня есть автономный скрипт на Python и изображение, показывающее текущую позицию локаторов, которые создаются в качестве примера.

изображение, показывающее, что текущие порожденные локаторы отключены по осям y и z

import maya.cmds as mc
import maya.OpenMaya as om

res = [mc.getAttr('defaultResolution.width'), 
        mc.getAttr('defaultResolution.height')]

print res
grid = [5, 5]    


def projectedGridPoint(camera, coord, depth, res):


    selList = om.MSelectionList()
    selList.add(camera)
    dagPath = om.MDagPath()
    selList.getDagPath(0,dagPath)
    dagPath.extendToShape()
    camMtx = dagPath.inclusiveMatrix()

    fnCam = om.MFnCamera(dagPath)
    mFloatMtx = fnCam.projectionMatrix()
    projMtx = om.MMatrix(mFloatMtx.matrix)

    #center of camera
    eyePt = fnCam.eyePoint()

    #offset position
    z = eyePt.z - depth

    #calculated xy positions
    x = (2 * z * coord[0] / res[0]) - z
    y = (2 * z * coord[1] / res[1]) - z

    return om.MPoint(x,y,depth) * camMtx * projMtx.inverse()

for y in range(grid[1] + 1):
    for x in range(grid[0] + 1):
        coord = ( x / float(grid[0]) * res[0], y / float(grid[1]) * res[1] )
        pt = projectedGridPoint('camera1', coord, 10, res)

        mc.spaceLocator(a=1, p=[pt.x, pt.y, pt.z])

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Как только я откорректировал ответ Theodox, чтобы учесть все возможные деления сетки, чтобы ndc_x и ndc_y всегда находились в диапазоне от -1 до 1. Я смог получить рабочее решение.

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


def projectedGridPoint(camera, coord, depth):
    selList = om.MGlobal.getSelectionListByName(camera)
    dagPath = selList.getDagPath(0)
    dagPath.extendToShape()
    view = dagPath.inclusiveMatrix()

    fnCam = om.MFnCamera(dagPath)
    projection = om.MMatrix(fnCam.projectionMatrix())

    viewProj =  projection * view 


    r =    om.MPoint(coord[0],coord[1], -1 * depth)  * projection.inverse()
    return r.homogenize() * view


xx, yy = (6, 6) 

for y in range(yy + 1):
    for x in range(xx + 1):
        ndc_x = -1
        ndc_y = -1

        if x > 0:
            ndc_x = (x / float(xx) * 2) - 1
        if y > 0:    
            ndc_y = (y / float(yy) * 2) - 1

        coord = ( ndc_x, ndc_y)
        print coord
        pt = projectedGridPoint('camera1', coord, 0)

        c,_ = cmds.polyCube(w = 0.1, d = 0.1, h = 0.1)
        cmds.xform(c, t = (pt[0], pt[1], pt[2]))
0 голосов
/ 04 мая 2018

Я думаю, что вы хотите что-то более похожее на это (обратите внимание, я преобразовал его в API 2, чтобы сократить шаблон)

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


    def projectedGridPoint(camera, coord, depth):
        selList = om.MGlobal.getSelectionListByName(camera)
        dagPath = selList.getDagPath(0)
        dagPath.extendToShape()
        view = dagPath.inclusiveMatrix()

        fnCam = om.MFnCamera(dagPath)
        projection = om.MMatrix(fnCam.projectionMatrix())

        viewProj =  projection * view 


        r =    om.MPoint(coord[0],coord[1], -1 * depth)  * projection.inverse()
        return r.homogenize() * view


    xx, yy = (2, 2) 

    for y in range(yy):
        for x in range(xx):

            ndc_x =  2.0 * x  / float(xx - 1) - 1
            ndc_y =  2.0 * y  / float(yy - 1) - 1
            coord = ( ndc_x, ndc_y)
            pt = projectedGridPoint('camera1', coord,0)

            c,_ = cmds.polyCube(w = 0.1, d = 0.1, h = 0.1)
            cmds.xform(c, t = (pt[0], pt[1], pt[2]))

Координаты предоставляются в виде нормализованных координат устройства (от -1, -1 до 1, 1 по углам вида), а глубина идет от ближних к дальним плоскостям отсечения - глубина 1 находится прямо на около плоскости, а глубина 0 находится в дальней плоскости. Я думаю, что на практике я бы зафиксировал глубину на 0 и использовал настройку плоскости отсечения на камере, чтобы установить глубину

edit Я рационализировал оригинальный, изящный метод преобразования значений индекса в координаты NDC

...