Falco Engine 3.9.0.1 (beta)
Quaternion.cs
Go to the documentation of this file.
1using System;
2using System.Runtime.CompilerServices;
3
4namespace FalcoEngine
5{
6 public struct Quaternion
7 {
8 public const float kEpsilon = 0.000001F;
9
10 public float x;
11 public float y;
12 public float z;
13 public float w;
14
15 public static Quaternion identity { get; } = new Quaternion(0, 0, 0, 1);
16
17 public Quaternion(float x, float y, float z, float w)
18 {
19 this.x = x;
20 this.y = y;
21 this.z = z;
22 this.w = w;
23 }
24
26 {
27 return new Quaternion(lhs.w * rhs.x + lhs.x * rhs.w + lhs.y * rhs.z - lhs.z * rhs.y, lhs.w * rhs.y + lhs.y * rhs.w + lhs.z * rhs.x - lhs.x * rhs.z, lhs.w * rhs.z + lhs.z * rhs.w + lhs.x * rhs.y - lhs.y * rhs.x, lhs.w * rhs.w - lhs.x * rhs.x - lhs.y * rhs.y - lhs.z * rhs.z);
28 }
29
30 public static Vector3 operator *(Quaternion rotation, Vector3 point)
31 {
32 float num = rotation.x * 2f;
33 float num2 = rotation.y * 2f;
34 float num3 = rotation.z * 2f;
35 float num4 = rotation.x * num;
36 float num5 = rotation.y * num2;
37 float num6 = rotation.z * num3;
38 float num7 = rotation.x * num2;
39 float num8 = rotation.x * num3;
40 float num9 = rotation.y * num3;
41 float num10 = rotation.w * num;
42 float num11 = rotation.w * num2;
43 float num12 = rotation.w * num3;
44 Vector3 result = default(Vector3);
45 result.x = (1f - (num5 + num6)) * point.x + (num7 - num12) * point.y + (num8 + num11) * point.z;
46 result.y = (num7 + num12) * point.x + (1f - (num4 + num6)) * point.y + (num9 - num10) * point.z;
47 result.z = (num8 - num11) * point.x + (num9 + num10) * point.y + (1f - (num4 + num5)) * point.z;
48 return result;
49 }
50
52 {
53 return new Quaternion(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
54 }
55
57 {
58 return new Quaternion(-q.x, -q.y, -q.z, -q.w);
59 }
60
61 // Is the dot product of two quaternions within tolerance for them to be considered equal?
62 private static bool IsEqualUsingDot(float dot)
63 {
64 // Returns false in the presence of NaN values.
65 return dot > 1.0f - kEpsilon;
66 }
67
68 // Are two quaternions equal to each other?
69 public static bool operator ==(Quaternion lhs, Quaternion rhs)
70 {
71 return IsEqualUsingDot(Dot(lhs, rhs));
72 }
73
74 // Are two quaternions different from each other?
75 public static bool operator !=(Quaternion lhs, Quaternion rhs)
76 {
77 // Returns true in the presence of NaN values.
78 return !(lhs == rhs);
79 }
80
81 // The dot product between two rotations.
82 public static float Dot(Quaternion a, Quaternion b)
83 {
84 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
85 }
86
87 public static Quaternion Euler(Vector3 angles)
88 {
89 INTERNAL_Euler(ref angles, out Quaternion value);
90 return value;
91 }
92
93 public static Quaternion Euler(float x, float y, float z)
94 {
95 Vector3 vec = new Vector3(x, y, z);
96 INTERNAL_Euler(ref vec, out Quaternion value);
97 return value;
98 }
99
100 public static Quaternion AngleAxis(float angle, Vector3 axis)
101 {
102 INTERNAL_AngleAxis(angle, ref axis, out Quaternion ret);
103 return ret;
104 }
105
106 public static Quaternion LookRotation(Vector3 direction, Vector3 axis)
107 {
108 INTERNAL_LookRotation(ref direction, out Quaternion ret);
109
110 return ret;
111 }
112
113 // Set x, y, z and w components of an existing Quaternion.
114 public void Set(float newX, float newY, float newZ, float newW)
115 {
116 x = newX;
117 y = newY;
118 z = newZ;
119 w = newW;
120 }
121
123
124 public void SetLookRotation(Vector3 view)
125 {
126 Vector3 up = Vector3.up;
127 SetLookRotation(view, up);
128 }
129
130 // Creates a rotation with the specified /forward/ and /upwards/ directions.
131 public void SetLookRotation(Vector3 view, Vector3 up)
132 {
133 this = LookRotation(view, up);
134 }
135
136 // Returns the angle in degrees between two rotations /a/ and /b/.
137 public static float Angle(Quaternion a, Quaternion b)
138 {
139 float dot = Dot(a, b);
140 return IsEqualUsingDot(dot) ? 0.0f : Mathf.Acos(Mathf.Min(Mathf.Abs(dot), 1.0F)) * 2.0F * Mathf.Rad2Deg;
141 }
142
143 public static Quaternion Slerp(Quaternion q1, Quaternion q2, float t)
144 {
145 INTERNAL_Slerp(ref q1, ref q2, t, out Quaternion ret);
146
147 return ret;
148 }
149
150 public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta)
151 {
152 float angle = Quaternion.Angle(from, to);
153 if (angle == 0.0f) return to;
154 return Slerp(from, to, Mathf.Min(1.0f, maxDegreesDelta / angle));
155 }
156
158 {
159 float mag = Mathf.Sqrt(Dot(q, q));
160
161 if (mag < Mathf.Epsilon)
162 return Quaternion.identity;
163
164 return new Quaternion(q.x / mag, q.y / mag, q.z / mag, q.w / mag);
165 }
166
167 public void Normalize()
168 {
169 this = Normalize(this);
170 }
171
173 {
174 get { return Normalize(this); }
175 }
176
177 // used to allow Quaternions to be used as keys in hash tables
178 public override int GetHashCode()
179 {
180 return x.GetHashCode() ^ (y.GetHashCode() << 2) ^ (z.GetHashCode() >> 2) ^ (w.GetHashCode() >> 1);
181 }
182
183 // also required for being able to use Quaternions as keys in hash tables
184 public override bool Equals(object other)
185 {
186 if (!(other is Quaternion)) return false;
187
188 return Equals((Quaternion)other);
189 }
190
191 public bool Equals(Quaternion other)
192 {
193 return x.Equals(other.x) && y.Equals(other.y) && z.Equals(other.z) && w.Equals(other.w);
194 }
195
196 public string ToString(string format, IFormatProvider formatProvider)
197 {
198 if (string.IsNullOrEmpty(format))
199 format = "F1";
200 return string.Format("({0}, {1}, {2}, {3})", x.ToString(format, formatProvider), y.ToString(format, formatProvider), z.ToString(format, formatProvider), w.ToString(format, formatProvider));
201 }
202
204 get
205 {
206 INTERNAL_EulerAngles(ref this, out Vector3 ret);
207 return ret;
208 }
209 set
210 {
211 this = Euler(value);
212 }
213 }
214
216 {
217 return new Quaternion(-x, -y, -z, w);
218 }
219
221 {
222 return new Quaternion(x * s, y * s, z * s, w * s);
223 }
224
226 {
227 float norm = x * x + y * y + z * z + w * w;
228
229 return Conjugate().Scale(1.0f / norm);
230 }
231
232 /*----------- INTERNAL CALLS ------------*/
233
234 [MethodImpl(MethodImplOptions.InternalCall)]
235 private extern static void INTERNAL_Euler(ref Vector3 euler, out Quaternion value);
236
237 [MethodImpl(MethodImplOptions.InternalCall)]
238 private extern static void INTERNAL_AngleAxis(float angle, ref Vector3 axis, out Quaternion value);
239
240 [MethodImpl(MethodImplOptions.InternalCall)]
241 private extern static void INTERNAL_LookRotation(ref Vector3 direction, out Quaternion ret);
242
243 [MethodImpl(MethodImplOptions.InternalCall)]
244 private extern static void INTERNAL_EulerAngles(ref Quaternion quaternion, out Vector3 ret);
245
246 [MethodImpl(MethodImplOptions.InternalCall)]
247 private extern static void INTERNAL_Slerp(ref Quaternion q1, ref Quaternion q2, float t, out Quaternion ret);
248 }
249}
static float Acos(float f)
Definition: Mathf.cs:93
static float Min(float a, float b)
Definition: Mathf.cs:150
const float Rad2Deg
Definition: Mathf.cs:34
static float Abs(float f)
Definition: Mathf.cs:130
static float Sqrt(float f)
Definition: Mathf.cs:121
static readonly float Epsilon
Definition: Mathf.cs:45
bool Equals(Quaternion other)
Definition: Quaternion.cs:191
string ToString(string format, IFormatProvider formatProvider)
Definition: Quaternion.cs:196
Quaternion Scale(float s)
Definition: Quaternion.cs:220
override int GetHashCode()
Definition: Quaternion.cs:178
override bool Equals(object other)
Definition: Quaternion.cs:184
static Quaternion AngleAxis(float angle, Vector3 axis)
Definition: Quaternion.cs:100
const float kEpsilon
Definition: Quaternion.cs:8
void SetLookRotation(Vector3 view, Vector3 up)
Definition: Quaternion.cs:131
static Quaternion operator+(Quaternion a, Quaternion b)
Definition: Quaternion.cs:51
static Quaternion Normalize(Quaternion q)
Definition: Quaternion.cs:157
void Set(float newX, float newY, float newZ, float newW)
Definition: Quaternion.cs:114
static bool operator==(Quaternion lhs, Quaternion rhs)
Definition: Quaternion.cs:69
Quaternion Conjugate()
Definition: Quaternion.cs:215
static Quaternion identity
Definition: Quaternion.cs:15
static float Angle(Quaternion a, Quaternion b)
Definition: Quaternion.cs:137
static float Dot(Quaternion a, Quaternion b)
Definition: Quaternion.cs:82
Quaternion Inverse()
Definition: Quaternion.cs:225
static Quaternion LookRotation(Vector3 direction, Vector3 axis)
Definition: Quaternion.cs:106
static Quaternion Slerp(Quaternion q1, Quaternion q2, float t)
Definition: Quaternion.cs:143
void SetLookRotation(Vector3 view)
Definition: Quaternion.cs:124
static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta)
Definition: Quaternion.cs:150
static bool operator!=(Quaternion lhs, Quaternion rhs)
Definition: Quaternion.cs:75
Quaternion(float x, float y, float z, float w)
Definition: Quaternion.cs:17
static Quaternion operator*(Quaternion lhs, Quaternion rhs)
Definition: Quaternion.cs:25
static Quaternion Euler(float x, float y, float z)
Definition: Quaternion.cs:93
static Quaternion operator-(Quaternion q)
Definition: Quaternion.cs:56
static Quaternion Euler(Vector3 angles)
Definition: Quaternion.cs:87
static Vector3 up
Definition: Vector3.cs:87