Allow the conversion to be implicit…
using UnityEngine;
public struct AxisAngle
{
private Vector3 _axis;
private float _angle;
public AxisAngle(Vector3 axis, float a)
{
_axis = axis.normalized;
_angle = a % 360f;
if(_angle < 0f) _angle += 360f;
}
public AxisAngle(Quaternion q)
{
Quaternion.ToAngleAxis(out _angle, out _axis);
}
public Vector3 Axis
{
get { return _axis; }
set { _axis = value.normalized; }
}
public float Angle
{
get { return _angle; }
set {
_angle = value % 360f;
if(_angle < 0f) _angle += 360f;
}
}
public static implicit operator Quaternion(AxisAngle aa)
{
return Quaternion.AngleAxis(aa.Angle, aa.Axis);
}
public static implicit operator AxisAngle(Quaternion q)
{
return new AxisAngle(q);
}
public static AxisAngle operator +(AxisAngle a, AxisAngle b)
{
var q = (Quaternion)a;
q *= (Quaterion)b;
return new AxisAngle(q);
}
public static AxisAngle operator -(AxisAngle a, AxisAngle b)
{
var q = (Quaternion)a;
q *= Quaternion.Inverse((Quaternion)b);
return new AxisAngle(q);
}
public static AxisAngle Slerp(AxisAngle from, AxisAngle b, float t)
{
return new AxisAngle(Quaternion.Slerp((Quaternion)a, (Quaternion)b, t));
}
}
With something like that you can just throw Quats and AxisAngles together. Since it’s an implicit conversion, the compiler will know what to do whenever you go and say try to assign a AxisAngle to the rotation property of something.
You could even go and define append, slerp, invert, etc operators as well, encapsulating the conversion, so you can do everything in this (I included 2 examples + and Slerp).
It of course will be a bit slower…
And of course you’ll probably want to go and write a custom editor for it to assist with the axis field. You could also make those field public, I merely made them private so as to validate passed in values.
But yeah… then you could just say things like:
AxisAngle a = transform.rotation; //I can't recall if C# allows implicit conversion in this scenario... might have to explicitly place (AxisAngle) on front
a += new AxisAngle(Vector3.up, 10f);
transform.rotation = a;
I still think it’s a lot of hoo-ha for no real reason. Might as well just use quats.
I mean heck… is this that different from this:
var a = transform.rotation;
a *= Quaternion.AngleAxis(10f, Vector3.up);
transform.rotation = a;
I mean, really, where is this AngleAxis all that useful other than an editor view? Where you don’t want the editor to display euler angles, but rather angle axis. In which case… you could write a custom PropertyDrawer to handle that, no need for this runtime AngleAxis slow conversion back and forth.
And as was explained earlier, you’re going to want to use the quat for the arithmetic for slerp, appending, inverting, etc… because doing it with angle axis directly is SLOW, the math is far more complicated than with the simple quaternion operators. This is WHY quats are so preferred these days… they’re actually really easy once you wrap your head around the very simple “amount of change in rotation” part. The only nuisance is DISPLAYING the quat in a human readable sense… and that’s just an editor script away, it just happens unity prefers to show quats in euler in the editor rather than angle axis.