其实,单纯要说四元数float型的精度完全够用,并不需要写成double型。不过前面的都写了,总要进行计算啊!不写不行啊。
Quaternion写起来有些难度,查找了一些资料后仍有一个FromToRotation方法未实现,求大神前来帮助~
Quaterniond:
/// Quaterniond.cs
///
/// The double type version of the Unity struct Quaternion.
/// It can solve the problem that the float type may not be accurate enough.
/// Function LookAt is unimplmented.
///
/// Unity Quaternion结构体的double版实现,以解决float型精度可能不够的问题。其中FromToRotation方法暂未实现。
///
/// Created by D子宇 on 2018.3.17
///
/// Email: darkziyu@126.com
using System;
using UnityEngine.Internal;
namespace Mathd
{
public struct Quaterniond
{
#region public members
public double x;
public double y;
public double z;
public double w;
#endregion
#region constructor
public Quaterniond(double p_x, double p_y, double p_z, double p_w)
{
x = p_x;
y = p_y;
z = p_z;
w = p_w;
}
#endregion
#region public properties
public double this[int index]
{
get
{
switch (index)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
case 3:
return w;
default:
throw new IndexOutOfRangeException("Invalid Quaterniond index!");
}
}
set
{
switch (index)
{
case 0:
x = value;
break;
case 1:
y = value;
break;
case 2:
z = value;
break;
case 3:
w = value;
break;
default:
throw new IndexOutOfRangeException("Invalid Quaterniond index!");
}
}
}
public static Quaterniond identity
{
get
{
return new Quaterniond(0, 0, 0, 1);
}
}
public Vector3d eulerAngles
{
get
{
Matrix4x4d m = QuaternionToMatrix(this);
return (MatrixToEuler(m) * 180 / Math.PI);
}
set
{
this = Euler(value);
}
}
#endregion
#region public functions
/// <summary>
/// 夹角大小
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static double Angle(Quaterniond a, Quaterniond b)
{
double single = Dot(a, b);
return Math.Acos(Math.Min(Math.Abs(single), 1f)) * 2f * (180 / Math.PI);
}
/// <summary>
/// 轴向旋转
/// </summary>
/// <param name="angle"></param>
/// <param name="axis"></param>
/// <returns></returns>
public static Quaterniond AngleAxis(double angle, Vector3d axis)
{
axis = axis.normalized;
angle = angle / 180D * Math.PI;
Quaterniond q = new Quaterniond();
double halfAngle = angle * 0.5D;
double s = Math.Sin(halfAngle);
q.w = Math.Cos(halfAngle);
q.x = s * axis.x;
q.y = s * axis.y;
q.z = s * axis.z;
return q;
}
/// <summary>
/// 点乘
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static double Dot(Quaterniond a, Quaterniond b)
{
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}
/// <summary>
/// 欧拉角转四元数
/// </