阅读 225

S03E10:利用矩阵操纵“傀儡”物体相对运动

说明

一个帮助理解矩阵几何含义的简单问题:假设有两个参照的物体,box1, box2 ,当我(即手机或相机)靠近 box1 时,傀儡物体也靠近 box2;当我走到 box1 后面时,傀儡物体也走到 box2 的后面。

几何

听起来有点复杂,先用简单的二维图像来表示一下我们要做的事情: 这就是一个简单的示意,我相对于 box1 的运动,会 1:1 反映在 Puppet 和 box2 上。但这个图像是二维的,而且只是控制了点的二维平移,没有缩放、旋转和三维的平移。

如果需要在 3D 或 AR 中完成类似操作,包含缩放、旋转和平移,应该怎么做呢?答案是用矩阵运算。先分析一下它们之间的关系:站在 box1 角度看 Me,和站在 box2 角度看 Puppet,姿态矩阵是一样的。用公式表示就是:

//inverse代表矩阵的逆运算
box1.inverse * Me = box2.inverse * Puppet
//两边同时左乘 box2,化简得到
box2 * box1.inverse * Me = Puppet
复制代码

这里我们认为四者都在同一层级,那么box1.inverse * Me就是站在 box1 看 Me 的姿态,再左乘 box2 就得到了 Puppet 的真实姿态。AR 中效果如图:

可以看到,当我手机靠近灰色方块 box1 时,飞船也会靠近红色方块 box2;当我抬起手机时,飞船也会抬头。。。。

当然,在实际 3D/AR 开发中,如果可以更改层级关系,可以将 Me 放在 box1 层级下,将 Puppet 放在 box2 层级下面,也可以实现同样效果。如果不方便更改层级关系,也可以用系统框架的 convert 方法来转换状态矩阵,不用考虑层级关系,也不用手动计算矩阵的逆。这些是框架为了便于理解而提供的抽象封装,实际数学计算过程仍然是利用矩阵的逆来计算的。

代码

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    if let phoneT = sceneView.pointOfView?.simdTransform, let box1 = box1, let box2 = box2 {
        ship?.simdTransform = box2.simdTransform * box1.simdTransform.inverse * phoneT
    }
}
复制代码
文章分类
iOS
文章标签