参考:
https://www.cnblogs.com/tgycoder/p/5103966.html
https://www.cnblogs.com/tgycoder/p/5106463.html
重新学习一下Quaternion
using UnityEngine;
public class QF : MonoBehaviour
{
[ContextMenu("GG")]
void MM()
{
}
void RotateAxisY90()
{
// 绕Y轴旋转90度的Quaternion, 顺时针旋转
Quaternion Q1 = Quaternion.identity;
Q1.eulerAngles = new Vector3(0, 90, 0);
Quaternion Q2 = Quaternion.AngleAxis(90, Vector3.up);
Quaternion Q3 = Quaternion.Euler(new Vector3(0, 90, 0));
Quaternion Q4 = Quaternion.Euler(0, 90, 0);
Vector3 v1 = Vector3.forward;
Vector3 v2 = Vector3.right;
Quaternion Q5 = Quaternion.FromToRotation(v1, v2);
}
Quaternion identity()
{
Quaternion identity = Quaternion.identity;
Debug.Log(identity); // (0.0, 0.0, 0.0, 1.0)
return Quaternion.identity;
}
Vector3 eulerAngles()
{
// 使用欧拉角表示的旋转, 绕Z轴旋转eulerAngles.z度, 绕X轴旋转eulerAngles.x度, 绕Y轴旋转eulerAngles.y度(按顺序)
Quaternion identity = Quaternion.identity;
Vector3 eulerAngles = identity.eulerAngles;
Debug.Log(eulerAngles); // (0.0, 0.0, 0.0)
return Vector3.zero;
}
float Angle()
{
// 两个旋转状态a达到b时需要旋转的最小夹角。[0, 180]
Quaternion Q1 = Quaternion.identity;
Quaternion Q2 = Quaternion.identity;
Q1.eulerAngles = new Vector3(0, 0, 0);
Q2.eulerAngles = new Vector3(0, 0, 181);
Debug.Log(Quaternion.Angle(Q1, Q2)); // 179
return 0;
}
Quaternion AngleAxis()
{
// Quaternion AngleAxis(float angle, Vector3 axis);
// 创建一个旋转, 这个旋转是绕axis轴旋转angle度
// 按左手定则
// 写法一和写法二的效果是一样的
// 写法一
// transform.rotation = Quaternion.AngleAxis(90, Vector3.up);
// 写法二
// Quaternion Q1 = Quaternion.identity;
// Q1.eulerAngles = new Vector3(0, 90, 0);
// transform.rotation = Q1;
return Quaternion.identity;
}
float Dot()
{
// float Dot(Quaternion a, Quaternion b)
// 根据点乘的结果,判断a和b对应欧拉角的关系。
// float f = Dot(Q1, Q2);
// f = x1 * x2 + y1 * y2 + z1 * z2 + w1 * w2
// f = [-1, 1]
// f == 1 => Q1.eulerAngles == Q2.eulerAngles
// f == -1 => 其中一个比另一个多转了360度, Dot(Q1,Q2)顺序无关
Quaternion Q1 = Quaternion.identity;
Quaternion Q2 = Quaternion.identity;
Q1.eulerAngles = new Vector3(0, 40, 0);
Q2.eulerAngles = new Vector3(0, 40, 0);
Debug.LogFormat("Q1四元数{0}, Q1欧拉角{1}", Q1, Q1.eulerAngles);
Debug.LogFormat("Q1四元数{0}, Q1欧拉角{1}", Q1, Q1.eulerAngles);
Debug.LogFormat("Dot(Q1, Q2) = {0}", Quaternion.Dot(Q1, Q2)); // 1
Q1.eulerAngles = new Vector3(0, 40, 0);
Q2.eulerAngles = new Vector3(0, 400, 0);
Debug.LogFormat("Q1四元数{0}, Q1欧拉角{1}", Q1, Q1.eulerAngles);
Debug.LogFormat("Q1四元数{0}, Q1欧拉角{1}", Q1, Q1.eulerAngles);
Debug.LogFormat("Dot(Q1, Q2) = {0}", Quaternion.Dot(Q2, Q1)); // -1
Debug.Log("--------------------------------");
// Q1和Q2越接近, 点乘结果越小, 可用于Lerp插值即将完成时的判断
for (int i = 40; i > 0; i--)
{
Q1.eulerAngles = new Vector3(0, 40, 0);
Q2.eulerAngles = new Vector3(0, 40 - i, 0);
Debug.LogFormat("Dot(Q1, Q2) = {0}", Quaternion.Dot(Q1, Q2));
}
return 0;
}
Quaternion Euler()
{
// Quaternion Euler(Vector3 euler)
// Quaternion Euler(float x, float y, float z)
// 返回一个旋转, 这个旋转是先绕Z轴旋转euler.z/z, 绕X轴旋转euler.y/y, 绕Y轴旋转euler.x/x
transform.rotation = Quaternion.Euler(new Vector3(0, 0, 45));
transform.rotation = Quaternion.Euler(0, 90, 0);
return Quaternion.identity;
}
Quaternion FromToRotation()
{
Vector3 v1 = Vector3.forward;
Vector3 v2 = Vector3.right;
transform.rotation = Quaternion.FromToRotation(v1, v2);
return Quaternion.identity;
}
Quaternion Inverse()
{
// Quaternion Inverse(Quaternion rotation)
// 逆取
// q1 = {x, y, z, w}
// q1_Inverse = {-x, -y, -z, w}
Quaternion Q1 = new Quaternion(1, 2, 3, 4);
Quaternion Q2 = Quaternion.Inverse(Q1);
Debug.LogFormat("Q1四元数{0}, 欧拉角{1}", Q1, Q1.eulerAngles);// Q1四元数(1.0, 2.0, 3.0, 4.0), 欧拉角(352.3, 47.7, 70.3)
Debug.LogFormat("Q2四元数{0}, 欧拉角{1}", Q2, Q2.eulerAngles);// Q2四元数(-1.0, -2.0, -3.0, 4.0), 欧拉角(318.2, 333.4, 296.6)
return Quaternion.identity;
}
Quaternion Lerp()
{
// 线性插值
// a + (b - a) * t, t被限制在[0, 1]
Quaternion Q1 = Quaternion.Euler(0, 0, 0);
Quaternion Q2 = Quaternion.Euler(0, -90, 0);
for (int i = -10; i <= 10; i++)
{
Quaternion Q = Quaternion.Lerp(Q1, Q2, i / 10.0f);
Debug.DrawLine(Vector3.zero, Q * Vector3.right, Color.red, 10);
}
return Quaternion.identity;
}
Quaternion LerpUnclamped()
{
// 线性插值
// a + (b - a) * t, t没有限制
Quaternion Q1 = Quaternion.Euler(0, 0, 0);
Quaternion Q2 = Quaternion.Euler(0, -90, 0);
for (int i = -10; i <= 20; i++)
{
Quaternion Q = Quaternion.LerpUnclamped(Q1, Q2, i / 10.0f);
Debug.DrawLine(Vector3.zero + Vector3.right * 2, Q * Vector3.right + Vector3.right * 2, Color.yellow, 10);
}
return Quaternion.identity;
}
Quaternion LookRotation()
{
// Quaternion LookRotation(Vector3 forward)
// Quaternion LookRotation(Vector3 forward, [DefaultValue("Vector3.up")] Vector3 upwards)
// 使 transform.up = upwards; transform.forward = forward
transform.rotation = Quaternion.LookRotation(Vector3.right);
return Quaternion.identity;
}
// NO
Quaternion RotateTowards()
{
// Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta)
// 插值方法,即从返回参数from到to的插值,且返回值的最大角度不超过maxDegreesDelta。
// maxDegreesDelta是角度值,不是插值系数,当maxDegreesDelta < 0时,将进行逆向插值即从to到from的方向进行插值计算。
Quaternion Q1 = Quaternion.Euler(0, 0, 0);
Quaternion Q2 = Quaternion.Euler(0, -90, 0);
Quaternion Q = Q1;
for (int i = 0; i <= 10; i++)
{
Q = Quaternion.RotateTowards(Q, Q2, 10);
Debug.DrawLine(Vector3.zero, Q * Vector3.right, Color.yellow, 10);
}
return Quaternion.identity;
}
Quaternion Slerp()
{
return Quaternion.identity;
}
Quaternion SlerpUnclamped()
{
return Quaternion.identity;
}
int GetHashCode()
{
Quaternion Q1 = new Quaternion(1, 2, 3, 4);
Quaternion Q2 = new Quaternion(1, 2, 3, 4);
Debug.Log(Q1.GetHashCode()); // 265289728
Debug.Log(Q2.GetHashCode()); // 265289728
return 0;
}
void Set()
{
Quaternion Q = new Quaternion(1, 2, 3, 4);
Q.Set(4, 3, 2, 1);
Debug.Log(Q);
}
void SetFromToRotation()
{
// SetFromToRotation(Vector3 fromDirection, Vector3 toDirection)
// 同 Quaternion FromToRotation()
// 成员方法,静态方法
}
void SetLookRotation()
{
// void SetLookRotation(Vector3 view)
// void SetLookRotation(Vector3 view, [DefaultValue("Vector3.up")] Vector3 up)
// 同 Quaternion LookRotation()
// 成员方法,静态方法
}
void ToAngleAxis()
{
// ToAngleAxis(out float angle, out Vector3 axis)
// 得到一个旋转是绕哪个轴旋转了多少度
Quaternion Q1 = Quaternion.Euler(45, 90, 60);
float angle;
Vector3 axis;
Q1.ToAngleAxis(out angle, out axis);
Debug.LogFormat("绕{0} 旋转{1}度", axis, angle); // 绕(0.8, 0.6, 0.1) 旋转90.9762度
Quaternion Q2 = Quaternion.identity;
Q2 = Quaternion.AngleAxis(angle, axis);
Debug.LogFormat("Q1 四元数{0}, 欧拉角{1}", Q1, Q1.eulerAngles); // Q1 四元数(0.6, 0.4, 0.1, 0.7), 欧拉角(45.0, 90.0, 60.0)
Debug.LogFormat("Q2 四元数{0}, 欧拉角{1}", Q2, Q2.eulerAngles); // Q2 四元数(0.6, 0.4, 0.1, 0.7), 欧拉角(45.0, 90.0, 60.0)
}
Quaternion OperatorQQ()
{
// Quaternion operator *(Quaternion lhs, Quaternion rhs)
// 先按lhs旋转, 再按rhs旋转, 顺序反了效果也会不一样
transform.rotation = Quaternion.Euler(0, 45, 0) * Quaternion.Euler(0, 45, 0);
return Quaternion.identity;
}
Vector3 OperatorQV()
{
// Vector3 operator *(Quaternion rotation, Vector3 point)
// 将point旋转rotation
Debug.Log(Quaternion.Euler(0, 90, 0) * Vector3.forward); // (1, 0, 0)
return Vector3.zero;
}
}