CATransform3D的m34的含义

Xia*_*ang 16 perspective catransform3d

结构CATransform3D的m34的含义是什么,我只知道它可以改变视角,但当值为-0.001和0.001时,意义是什么?

Mih*_*mar 18

您可以在此处找到完整的详细信息.请注意,Apple使用反向乘法顺序进行投影(相对于给定链接),因此所有矩阵乘法都会反转,并且所有矩阵都会被转置.

简短描述的含义:

  • m34 =投影平面的1/z距离(参考链接中的1/e z项)
  • + z轴朝向观察者,在使用时产生"照镜子"的感觉 -
  • 投影中心是(0,0,0)加上您设置的任何翻译


mib*_*ibu 5

以下是我认为读者在回答问题之前应该了解的一些有关该主题的背景知识:

  1. iOS 坐标系:想象一下,您垂直握住手机,屏幕面向您。对于每个视图,其坐标系的原点位于其中心。x 轴从左到右,y 轴从上到下,z 轴从手机背面到您的脸部。

  2. 齐次坐标:在使用 iOS 进行 3D 变换时,您使用的是齐次坐标或投影坐标,而不是传统的笛卡尔坐标。简而言之,新坐标系w比旧坐标系多了一维。该系统的优点在于它允许通过向量矩阵乘法进行旋转/平移/缩放。

  • 要将齐次坐标中的向量转换为 Catersian 坐标,请将 x、y、z 除以 w。

现在,让我们来寻找答案。考虑如下示例:

    var transform = CATransform3DIdentity
    transform.m34 = -1 / 500
    transform = CATransform3DRotate(transform, Double.pi/4, 0, 1, 0)
    transform = CATransform3DTranslate(transform, 0, 0, 200)
    imageLayer.transform = transform
Run Code Online (Sandbox Code Playgroud)

要了解上面的代码的作用,您必须以相反的顺序阅读它。首先,图像沿 z 轴方向移动 200px(正号表示其方向是从屏幕朝向您的脸部)。其次,图像相对于 y 轴旋转 45 度(向右倾斜)。如果您停在这里,您将看到一个宽度较小并移至右侧的图像。但一些操作是在步骤 3 中完成的,并且“神奇地”给出了图像透视图。元素的奥秘就在这里m34

以下是以矩阵乘法表示的运算序列:

 [x' y' z' w'] = ([x y z w] * translation_matrix * rotation_matrix) * perspective_matrix
Run Code Online (Sandbox Code Playgroud)

透视矩阵变换

现在,重点关注操作perspective_matrix

转换为 Catersian 坐标:

带比例因子的变换

要在 2D 屏幕上模拟 3D 透视,您希望靠近眼睛的物体看起来比远处的物体更大。为此,您需要将对象从 3D 空间投影到屏幕上,即从您的眼睛中绘制穿过对象并与屏幕相交的假想线。让我们计算该投影的比例因子:

z = the object's z-coordinate which is its distance to the screen
eye2screen #distance from your eyes to the screens
scaleFactor = eye2screen / (eye2Screen - z) #Thales's intercept theorem
Run Code Online (Sandbox Code Playgroud)

快速计算可以证实我们的直觉。随着 z 变小(即物体离眼睛更远),scaleFactor变得更小。

将我们scaleFactorperspective_matrix上面的乘法调和,我们有:

scaleFactor = 1 / (1 + m34 * z)
1 / (1 - z / eye2screen) = 1 / (1 + m34 * z)
-1 / eye2screen = m34
m34 = -1 / eye2screen
Run Code Online (Sandbox Code Playgroud)

选择眼睛和屏幕之间的合理距离(例如 500),您可以计算 m34 并且您自己得到了一个新的perspective_matrix.

结论:

  1. 透视矩阵是一种根据物体到眼睛的距离来缩放物体的数学技巧。
  2. 计算m34 = -1 / eye2screen给你一个perspective_matrix
  3. perspective_matrix操作只能在转换管道末尾应用一次。