您当前的位置: 首页 >  Jave.Lin ar

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

Jave.Lin 发布时间:2021-11-04 15:57:52 ,浏览量:4

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

另外参考 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
			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
关注
打赏
1688896170
查看更多评论

Jave.Lin

暂无认证

  • 4浏览

    0关注

    546博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.1169s