万向节死锁_万向节死锁产生的原因
萬向節(jié)死鎖產(chǎn)生的根本原因是,旋轉(zhuǎn)矩陣是依次進(jìn)行的,假設(shè)先圍繞x軸旋轉(zhuǎn),再圍繞y軸旋轉(zhuǎn),最后圍繞z軸旋轉(zhuǎn),這就導(dǎo)致物體其實(shí)是圍繞自己的X軸旋轉(zhuǎn),而不是世界坐標(biāo)的X軸旋轉(zhuǎn)。
表現(xiàn)就是,在一個(gè)歐拉角(x,y,z)下,改變x的值,物體會(huì)圍繞物體自己的x軸進(jìn)行旋轉(zhuǎn),而不是世界坐標(biāo)系的x軸進(jìn)行旋轉(zhuǎn)。
下圖所示,改變x值,都是在繞自己的紅色的軸(x軸)轉(zhuǎn)。RGB三個(gè)顏色分別對應(yīng)XYZ正半軸:
首先,旋轉(zhuǎn)3D模型時(shí),實(shí)際是對原始模型的頂點(diǎn)進(jìn)行旋轉(zhuǎn)。比如旋轉(zhuǎn)(x1,y1,z1),就是把原始模型旋轉(zhuǎn)到這個(gè)角度,然后渲染顯示。當(dāng)旋轉(zhuǎn)變成(x2,y2,z2),會(huì)把原始模型旋轉(zhuǎn)到這個(gè)角度,然后渲染顯示。
然后,進(jìn)行一次旋轉(zhuǎn)時(shí),物體是先圍繞x軸進(jìn)行旋轉(zhuǎn),這時(shí)候物體的局部坐標(biāo)系和世界坐標(biāo)系是重合的,雖然是圍繞世界坐標(biāo)的x軸旋轉(zhuǎn),但也是圍繞自己的x軸進(jìn)行旋轉(zhuǎn)。最后得到的旋轉(zhuǎn)結(jié)果,也變成了物體是繞自己的x軸轉(zhuǎn)的結(jié)果了。
最后,當(dāng)把物體的x軸旋轉(zhuǎn)到與世界的z軸重合時(shí),歐垃角的x和z旋轉(zhuǎn)結(jié)果就都一樣了,也就丟失了一個(gè)維度。另一方面,比如在(30, 30, 30)的歐垃角下,把y從30調(diào)到60會(huì)發(fā)現(xiàn)并不是繞自己的y軸在轉(zhuǎn),也不是繞世界坐標(biāo)的y旋轉(zhuǎn)。
可以自己通過歐拉角計(jì)算出頂點(diǎn)旋轉(zhuǎn)后的坐標(biāo)來驗(yàn)證這個(gè)。
參考資料:
附上自己的Unity測試代碼:
using UnityEngine;
[ExecuteInEditMode]
public class TestEuler : MonoBehaviour
{
public Vector3 Euler;
public Vector3 OrgPosOfA;
public Vector3 OrgPosOfB;
public Vector3 OrgPosOfC;
public Transform TransA;
public Transform TransB;
public Transform TransC;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update ()
{
TransA.position = Rotate(OrgPosOfA, Euler) + transform.position;
TransB.position = Rotate(OrgPosOfB, Euler) + transform.position;
TransC.position = Rotate(OrgPosOfC, Euler) + transform.position;
}
Vector3 Rotate(Vector3 pos, Vector3 euler)
{
pos = RotateX(pos, euler.x * Mathf.Deg2Rad);
pos = RotateY(pos, euler.y * Mathf.Deg2Rad);
pos = RotateZ(pos, euler.z * Mathf.Deg2Rad);
return pos;
}
Vector3 RotateX(Vector3 pos, float r)
{
Vector3 newPos = pos;
float cos = Mathf.Cos(r);
float sin = Mathf.Sin(r);
newPos.y = pos.y * cos + pos.z * sin;
newPos.z = -pos.y * sin + pos.z * cos;
return newPos;
}
Vector3 RotateY(Vector3 pos, float r)
{
Vector3 newPos = pos;
float cos = Mathf.Cos(r);
float sin = Mathf.Sin(r);
newPos.x = pos.x * cos - pos.z * sin;
newPos.z = pos.x * sin + pos.z * cos;
return newPos;
}
Vector3 RotateZ(Vector3 pos, float r)
{
Vector3 newPos = pos;
float cos = Mathf.Cos(r);
float sin = Mathf.Sin(r);
newPos.x = pos.x * cos + pos.y * sin;
newPos.y = -pos.x * sin + pos.y * cos;
return newPos;
}
void OnDrawGizmos()
{
//坐標(biāo)軸
Gizmos.color = Color.red;
Gizmos.DrawLine(transform.position, transform.position + Vector3.right);
Gizmos.color = Color.green;
Gizmos.DrawLine(transform.position, transform.position + Vector3.up);
Gizmos.color = Color.blue;
Gizmos.DrawLine(transform.position, transform.position + Vector3.forward);
//旋轉(zhuǎn)后的點(diǎn)
Gizmos.color = Color.red;
Gizmos.DrawLine(transform.position, TransA.position);
Gizmos.color = Color.green;
Gizmos.DrawLine(transform.position, TransB.position);
Gizmos.color = Color.blue;
Gizmos.DrawLine(transform.position, TransC.position);
}
}
下圖所示,改變x值,都是在繞紅色的軸(x軸)轉(zhuǎn)。RGB三個(gè)顏色分別對應(yīng)XYZ正半軸:
總結(jié)
以上是生活随笔為你收集整理的万向节死锁_万向节死锁产生的原因的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多目标跟踪MOT入门
- 下一篇: iPhone手机使用:iPhone XR