找回密码
 立即注册
查看: 195|回复: 1

用 Unity 来探索 rotation

[复制链接]
发表于 2022-11-2 10:54 | 显示全部楼层 |阅读模式
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[cor - R cor + t_1 - t_0] R p  \end{align*}  
这个看起来也 ok,但是发现某些时候看起来不太流畅,会有突然的位置改变,发现最符合直接的还是 TranslationMatrix[ T_1 - R T_0 ] R p .

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2022-11-2 10:57 | 显示全部楼层
很有趣的分享
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-21 20:38 , Processed in 0.126016 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表