Unity - 搬砖日志 - 获取 child 相对 parent 下的 rotation


今天有位小伙伴问我如何获取 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


另外参考 ToLua 作者中的代码 Quaternion.lua 中的其中一个方法 :Quaternion.lua

--from http://www.geometrictools.com/Documentation/EulerAngles.pdf
--Order of rotations: YXZ
function Quaternion:ToEulerAngles()
	local x = self.x
	local y = self.y
	local z = self.z
	local w = self.w
		
	local check = 2 * (y * z - w * x)
	
	if check < 0.999 then
		if check > -0.999 then
			local v = Vector3.New( -asin(check), 
						atan2(2 * (x * z + w * y), 1 - 2 * (x * x + y * y)), 
						atan2(2 * (x * y + w * z), 1 - 2 * (x * x + z * z)))
			SanitizeEuler(v)
			v:Mul(rad2Deg)
			return v
		else
			local v = Vector3.New(half_pi, atan2(2 * (x * y - w * z), 1 - 2 * (y * y + z * z)), 0)
			SanitizeEuler(v)
			v:Mul(rad2Deg)
			return v
		end
	else
		local v = Vector3.New(-half_pi, atan2(-2 * (x * y - w * z), 1 - 2 * (y * y + z * z)), 0)
		SanitizeEuler(v)
		v:Mul(rad2Deg)
		return v		
	end
end
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值