将点投射到相机深处的平行网格上(maya)

时间:2018-05-03 01:15:27

标签: python math coordinates maya maya-api

我正在尝试创建一个定位器网格,这些定位器用作指定深度的maya中相机的平行有限平面上的投影点。网格应与指定的分辨率对齐,以匹配渲染的输出。

目前我的计算已经结束,我正在寻找一些帮助,以确定我的确定预测点的公式是如何不正确的。

我有一个自包含的python脚本和图像,显示了作为示例生成的定位器的当前位置。

image showing current spawned locators are off on y and z axis

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 :(得分:0)

我认为你想要更像这样的东西(注意,我将它转换为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]))

coords作为标准化设备坐标(从视图的角落处的-1,-1到1,1)提供,深度从近到远的剪裁平面 - 深度为1就在靠近平面,深度为0位于远平面上。我认为在实践中我将深度锁定为0并使用相机上的剪裁平面设置来设置深度

编辑我合理化了将索引值转换为NDC坐标的原始,不稳定的方法

答案 1 :(得分:0)

一旦我调整了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]))