Maya 正交投影矩阵

Maya Orthographic Projection Matrix

我正在尝试计算 Maya 的正交投影矩阵。有人熟悉如何计算吗?我对透视不感兴趣,只对正交相机视图感兴趣。

import math
import maya.cmds as cmds
import maya.OpenMaya as OpenMaya
import maya.OpenMayaUI as OpenMayaUI

# Get view matrix.
view = OpenMayaUI.M3dView.active3dView()
mayaProjMatrix = OpenMaya.MMatrix()
view.projectionMatrix(mayaProjMatrix)

print("\nMaya Projection:")
for x in xrange(0, 4):
    print(round(mayaProjMatrix(x, 0), 3),
          round(mayaProjMatrix(x, 1), 3),
          round(mayaProjMatrix(x, 2), 3),
          round(mayaProjMatrix(x, 3), 3))

Maya Projection:
(0.067, 0.0, 0.0, 0.0)
(0.0, 0.132, 0.0, 0.0)
(0.0, 0.0, -0.0, 0.0)
(0.0, 0.0, -1.0, 1.0)

我一直在研究很多网站,但我不太确定如何在 Maya 中翻译相同的想法 (http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho)。

在计算机图形学中,投影矩阵只是定义将某个体积仿射或投影变换为定义的标准体积,通常是立方体。

我不知道这里的 maya 约定,所以我使用的是 GL。无论如何,原则都是一样的。

在 GL 中,观看体积由 标准化设备 space 中所有 3 个维度的单位立方体 [-1,1] 表示。而projection的matrix的工作就是将data转换成clip space。 clip space 和 normalized device space 的区别在于后者是在透视划分之后。但是,由于您不需要透视而只需要一个正交矩阵,而除数将始终为 1 - 因此在这种情况下,我们可以将归一化设备 space 和剪辑 space 视为相同。

现在使用你的矩阵(评论中更精确的版本,你粘贴在问题中的那个实际上不可能重建 z)并乘以一个点导致:

(0.066666667  0.0          0.0          0.0    )  (x)
(0.0          0.131734838  0.0          0.0    )  (y)
(0.0          0.0         -0.000200002 -1.00002)  (z) 
(0.0          0.0          0.0          1.0    )  (1)

x' =  0.066666667 * x
y' =  0.131734838 * y
z' = -0.000200002 * z -1.00002

所以这个矩阵非常好,因为它可以通过分别反转每个方程来简单地反转。您需要找出剪辑 space 中查看体积边缘的 x yz,因此 x'=-1x'=1, y'=-1 等等。

这导致 x 方向的观看体积 [-15,15],y 方向的 [-7.591,7.591](与您在评论中提到的 1401/709 的纵横比相匹配)和 [-0.1,- 5000] 在 z。在典型的 GL 术语中,该矩阵是以下结果:

ortho(-15, 15, -15/aspect, 15/aspect, 0.1, 5000)

(clip near 和 clip far 的 z 值按照约定取反,因为相机应该沿着 -z 看,而 clip 值是距离)。

所有这些实际上都在您提供的 link 中进行了解释。我会在这里添加完全相同的 link,如果它还没有出现在问题中...

我想我会 post 我正在使用的 Maya 代码。显然,maya 中有正字法属性可以帮助根据 derhass 的回答计算这个称为 "Orthographic Width" 的属性。

# Get view matrix.
view = OpenMayaUI.M3dView.active3dView()
mayaProjMatrix = OpenMaya.MMatrix()
view.projectionMatrix(mayaProjMatrix)

# Get camera MFnDagPath.
dagCam = OpenMaya.MDagPath()
view.getCamera(dagCam)

width = float(view.portWidth())
height = float(view.portHeight())
aspect = width/height

n = cmds.getAttr("%s.nearClipPlane" % dagCam.fullPathName())
f = cmds.getAttr("%s.farClipPlane" % dagCam.fullPathName())

w = 2.0/cmds.getAttr("%s.orthographicWidth" % dagCam.fullPathName())
h = w * aspect
z = -2.0/(f-n)
v = -1.0 * ((f + n) / (f-n))

mat = [0.0] * 16
mat[0] = w
mat[1] = 0.0
mat[2] = 0.0
mat[3] = 0.0

mat[4] = 0.0
mat[5] = h
mat[6] = 0.0
mat[7] = 0.0

mat[8] = 0.0
mat[9] = 0.0
mat[10] = z
mat[11] = 0.0

mat[12] = 0.0
mat[13] = 0.0
mat[14] = v
mat[15] = 1.0

projMatrix = OpenMaya.MMatrix()
OpenMaya.MScriptUtil().createMatrixFromList(mat, projMatrix)

print("\nMaya Projection:")
for x in xrange(0, 4):
    print(round(mayaProjMatrix(x, 0), 9),
          round(mayaProjMatrix(x, 1), 9),
          round(mayaProjMatrix(x, 2), 9),
          round(mayaProjMatrix(x, 3), 9))

print("\nMy Projection:")
for x in xrange(0, 4):
    print(round(projMatrix(x, 0), 9),
          round(projMatrix(x, 1), 9),
          round(projMatrix(x, 2), 9),
          round(projMatrix(x, 3), 9))

Maya Projection:
(0.04116922, 0.0, 0.0, 0.0)
(0.0, 0.061226019, 0.0, 0.0)
(0.0, 0.0, -0.000200002, 0.0)
(0.0, 0.0, -1.00002, 1.0)

My Projection:
(0.04116922, 0.0, 0.0, 0.0)
(0.0, 0.061226019, 0.0, 0.0)
(0.0, 0.0, -0.000200002, 0.0)
(0.0, 0.0, -1.00002, 1.0)