用 Unity 来探索 rotation
transform.rotation如果直接对物体使用 transform.rotation,在这个物体没有 parent 的前提下,是直接对着自己的中心 rotation, 有 parent 好像也ok,区别是 parent 的 transform 会影响到 children 的 transform:
targetDevice.TryGetFeatureValue(CommonUsages.deviceRotation, out Quaternion controllerCurrentRotation);
cube.transform.rotation = controllerCurrentRotation;
正因为是随着中心 rotation,所以对于球来说,这个 rotation 设置起来好像是没有效果的。测试如下,同样设置球的 rotation 和 cube 一样:
使用 Rotation Matrix
那么要怎么做到,如果我想球也有 rotation,那就当然是我要球绕世界某处旋转(而不是它自身的中心)。所以这里我可以改变一下:
void Start()
{
...
cor = ( sphere0.transform.position + sphere1.transform.position + sphere2.transform.position + sphere3.transform.position ) / 4.0f;
}
void Update()
{
...
targetDevice.TryGetFeatureValue(CommonUsages.deviceRotation, out Quaternion controllerCurrentRotation);
Quaternion rotationOffset = controllerCurrentRotation * Quaternion.Inverse(controllerLastRotation);
cube.transform.rotation = controllerCurrentRotation;
Matrix4x4 m = Matrix4x4.TRS(Vector3.zero, rotationOffset, Vector3.one);
sphere0.transform.position = m.MultiplyPoint3x4(sphere0.transform.position - cor) + cor;
sphere1.transform.position = m.MultiplyPoint3x4(sphere1.transform.position - cor) + cor;
sphere2.transform.position = m.MultiplyPoint3x4(sphere2.transform.position - cor) + cor;
sphere3.transform.position = m.MultiplyPoint3x4(sphere3.transform.position - cor) + cor;
controllerLastRotation = controllerCurrentRotation;
}
上面的代码实现让球绕着他们共同的中心 mass center 旋转,所以这样就可以做到:
上面绕某点旋转的代码是:
R (p - cor) + cor
实际上可以展开:
R p + ( cor - R cor )
其实也可以看作:
[*]首先旋转 Rp
[*]旋转完的结果移动到 cor - R cor
如果认为 T 是 translation 矩阵,那么写出来是:
TranslationMatrix[ cor - R cor ] R p
实际上绕某点(非原点)旋转也可以认为是先把坐标系移到这一点,然后绕着这一点旋转,然后再把坐标系移回去。所以很多地方的绕某点移动一般是写的TRT这种形式,实际上我们看到它也可以写成 T'R ,也就是上面这种形式。
移动 + 旋转
假设我想做另一件事,球不仅跟着手旋转,并且要加上跟着手移动,如果纯考虑跟着 controller 位置和旋转动,推导一下:
[*]上一帧 controller 的位置和旋转 : T_0, R_0
[*]这一帧 controller 的位置和旋转 : T_1, R_1
[*]之间的差异: ( T_1 R_1 ) ( T_0 R_0 )^{-1}
\begin{align*} & ( T_1 R_1 ) ( T_0 R_0 )^{-1}\\ = & T_1 R_1 R_0^{-1} T_0^{-1} \end{align*}
用来改变点的位置(t 对应 T 的 translation):
\begin{align*} & T_1 R_1 R_0^{-1} T_0^{-1}p\\ =& t_1 + R_1R_0^{-1}(p - t_0)\\ =& (t_1 -R_1R_0^{-1} t_0) + R_1R_0^{-1} p \\ =& (T_1 -R_1R_0^{-1} T_0) R_1R_0^{-1} p\end{align*}
Quaternion rotation = controllerCurrentRotation * Quaternion.Inverse(controllerLastRotation);
Matrix4x4 m = Matrix4x4.TRS(controllerCurrentPosition - rotation * controllerLastPosition, rotation, Vector3.one);
如果考虑:
TranslationMatrix[ T_1 - T_0 ] R p
Quaternion rotation = controllerCurrentRotation * Quaternion.Inverse(controllerLastRotation);
Matrix4x4 m = Matrix4x4.TRS(controllerCurrentPosition -controllerLastPosition, rotation, Vector3.one);
下一种情况好像是旋转的中心不同。
再测试了一种 rotate + translation:
\begin{align*} & R(p - cor) + cor + t_1 - t_0\\ =& Rp + cor - R cor + t_1 - t_0\\ =& Translation R p\end{align*}
这个看起来也 ok,但是发现某些时候看起来不太流畅,会有突然的位置改变,发现最符合直接的还是 TranslationMatrix[ T_1 - R T_0 ] R p . 很有趣的分享
页:
[1]