今天有位小伙伴问我如何获取 child 相对 parent 下的 rotation
也就是 child 相对 parent 下的 世界坐标下的四元数
但是啊,四元数,我一直还没去啃这块老骨头
后面都是搜索得到结果,到时推导过程很简单
推导过程:
已知 Unity 中 Transform parent, Transform child
想要获取:child
相对 parent
下的 Quaternion
应用变换,如下:
Transform parent, Transform child;
child.SetParent(parent);
var localQ = child.localRotation;
可以写成:
var localQ = Quaternion.Inverse(parent.rotation) * child.rotation;
推导过程如下:
-
已知等式:
parent.rotation * child.localRotation = child.rotation
-
两边乘以
Quaternion.Inverse(parent.rotation)
等式变换:Quaternion.Inverse(parent.rotation) * parent.rotation * child.localRotation = Quaternion.Inverse(parent.rotation) * child.rotation
-
左边因为
Quaternion.Inverse(parent.rotation) * parent.rotation = Quaternion.identity
,所以可以不写,那么等式再次变换:child.localRotation = Quaternion.Inverse(parent.rotation) * child.rotation
// jave.lin : 写成代码方式
Quaternion.identity = Quaternion.Inverse(parent.rotation) * parent.rotation; // (1) Q * Q^-1 = I
var childWorldRotation = child.rotation; // (2) child 世界坐标下的 rotation
var childWorldLocalRotation = child.localRotation; // (3) child 世界坐标下的 rotation
var parentWorldRotation = parent.rotation; // (4) parent 世界坐标下的 rotation
var invParentWorldRotation = Quaternion.Invser(parent.rotation); // (5) parent 世界坐标下的 逆 rotation
已知:
Quaternion.identity = I
var childWorldRotation = C_W
var childWorldLocalRotation = C_L
var parentWorldRotation = P_W
var invParentWorldRotation = P_IW
parentWorldRotation * childWorldLocalRotation = childWorldRotation
代数化:
P_W * C_L = C_W
两边乘以 P_IW :
P_IW * P_W * C_L = P_IW * C_W
因为:P_W * P_IW = I
I * C_L = P_IW * C_W
I 可省略,得最终式子:
C_L = P_IW * C_W
还原代数,得:
var childWorldLocalRotation = invParentWorldRotation * childWorldRotation
引用大佬的简化推导
cam_rotation * q = obj_rotation
inverse(cam_rotation) * cam_rotation * q = inverse(cam_rotation) * obj_rotation
q = inverse(cam_rotation) * obj_rotation
References
- Unity calculate quaternion relative to main camera
- Problem finding relative rotation from one quaternion to another