【问题标题】:projecting points onto a parallel grid at a depth from camera (maya)将点投影到相机深度的平行网格上(maya)
【发布时间】:2018-05-03 01:15:26
【问题描述】:

我正在尝试创建一个定位器网格,这些定位器用作从 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])

【问题讨论】:

  • 那么这些点应该投影在相机截锥体中吗?即,深度为 0 是否应该位于剪辑平面上?
  • 是的,网格点应该在指定深度细分/对齐渲染图像的查看区域(在本例中为 10 个单位,作为 arg 传递给 projectionGridPoint 函数)

标签: python math coordinates maya maya-api


【解决方案1】:

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

【讨论】:

  • 我修复了坐标计算,第一个版本恰好适用于我的测试编号但不正确
【解决方案2】:

我认为您想要一些更像这样的东西(注意,我将其转换为 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 正好在near 平面,并且深度为 0 在远平面上。我认为在实践中我会将深度锁定在 0 并使用相机上的剪辑平面设置来设置深度

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

【讨论】:

  • 这似乎工作得很好,直到网格调整被细分。例如将其更改为 (6, 6) 并且相机偏离中心。我也想知道坐标计算中的 4.0 值是什么。
猜你喜欢
  • 1970-01-01
  • 2021-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
  • 2021-06-25
相关资源
最近更新 更多