johnsoncodehk 发表于 2022-11-2 10:54

用 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 .

Mecanim 发表于 2022-11-2 10:57

很有趣的分享
页: [1]
查看完整版本: 用 Unity 来探索 rotation