EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
GaTypes.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the Gangsta Wrapper physics SDK abstraction library suite.
3  Copyright (C) 2005 Ed Jones (Green Eyed Monster)
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 
19  See also the files README.txt and LICENSE.txt in the root directory of this module.
20 */
21 #include "GaTypes.h"
22 
23 using namespace Ga;
24 GaQuat GaQuat::IDENTITY = GaQuat(1,0,0,0);
25 GaQuat GaQuat::ZERO = GaQuat(0,0,0,0);
26 
27 GaQuat::GaQuat(const GaRadian &a,const GaVec3 &axis)
28 {
29  w = Math::cosine(a.r * 0.5);
30 
31  GaFloat sin_a = Math::sine(a.r * 0.5);
32  v.x = axis.x * sin_a;
33  v.y = axis.y * sin_a;
34  v.z = axis.z * sin_a;
35 
36  v.x *= 57.2957795131; // 180/pi (rad->deg)
37  v.y *= 57.2957795131; // 180/pi (rad->deg)
38  v.z *= 57.2957795131; // 180/pi (rad->deg)
39 
40  if (v.x < 0)
41  v.x += 360;
42  if (v.y < 0)
43  v.y += 360;
44  if (v.z < 0)
45  v.z += 360;
46 }
47 
49 {
50  return m[r0][c0] * (m[r1][c1] * m[r2][c2] - m[r2][c1] * m[r1][c2]) -
51  m[r0][c1] * (m[r1][c0] * m[r2][c2] - m[r2][c0] * m[r1][c2]) +
52  m[r0][c2] * (m[r1][c0] * m[r2][c1] - m[r2][c0] * m[r1][c1]);
53 }
54 
55 GaFloat GaVec3::angle(float ax, float ay, float bx, float by)
56 {
57  GaFloat dx = bx - ax;
58  GaFloat dy = by - ay;
59  GaFloat result = ((atan2(dx , dy)) * 180 /Math::GaPi);
60  result -= 90;
61  if (result < 0)
62  result += 360;
63 
64  return result;
65 }
66 
67 GaVec3 GaVec3::rotationTo(const GaVec3 &pos) const
68 {
69  // yaw, pitch, roll = dunRotation
70 
71  GaQuat q(GaQuat::ZERO);
72  GaVec3 axis(*this);
73  axis.normalize();
74  /*
75  GaVec3 toVec((pos.x - x), (pos.y - y), (pos.z - z)); // (to, from)
76  toVec.normalize();
77  GaFloat dot = toVec.dotProduct(axis);
78  GaFloat radians = Math::arcCosine(dot);
79  if (isnan(radians))
80  return q;
81 
82  q.w = Math::cosine(radians * 0.5);
83  if ((q.w > 1) or (q.w < 0))
84  return GaQuat::ZERO;
85 */
86  q.v.x = Math::arcTangent(pos.z - z, pos.x - x); // rad from dir to target on z axis
87  q.v.y = axis.x;
88  q.v.z = 0;
89 
90  /*
91  GaFloat sin_a = Math::sine(radians * 0.5);
92  q.v.x = axis.x * sin_a;
93  q.v.y = axis.y * sin_a;
94  q.v.z = axis.z * sin_a;
95  */
96  //q.v.x *= Math::GaDegreesInRadian; //57.2957795131; // 180/pi (rad->deg)
97  //q.v.y *= Math::GaDegreesInRadian; //57.2957795131; // 180/pi (rad->deg)
98  q.v.z *= Math::GaDegreesInRadian; //57.2957795131; // 180/pi (rad->deg)
99 
100  /*
101  if (q.v.x < 0)
102  q.v.x += 360;
103  if (q.v.y < 0)
104  q.v.y += 360;
105  if (q.v.z < 0)
106  q.v.z += 360;
107  */
108 
109  return GaVec3(q.v.x, q.v.y, q.v.z);
110 }
111 /*
112 GaVec3 GaVec3::rotByQuat(GaVec3 v, GaQuat q)
113 {
114  // Extract the vector part of the quaternion
115  GaVec3 u(q.v.x, q.v.y, q.v.z);
116  // Extract the scalar part of the quaternion
117  double s = q.w;
118  // Do the math
119  return u* (2.0 * (u* v)) + v* (s*s - (u* u)) + (u^ v)* (2.0 * s);
120 }
121 
122 GaVec3 GaVec3::angleRot(GaVec3 from, GaVec3 to, double angle)
123 {
124  GaVec3 axis((to.x-from.x), (to.y-from.y), (to.z-from.z));
125  axis.normalize();
126  angle = angle / 2.0;
127 
128  GaQuat q_temp(0.0, 0.0, 0.0, 1.0 );
129  q_temp.v.x = axis.x * sin(angle);
130  q_temp.v.y = axis.y * sin(angle);
131  q_temp.v.z = axis.z * sin(angle);
132  q_temp.w = cos(angle);
133 */
134  /*
135  * q.v.x *= Math::GaDegreesInRadian; //57.2957795131; // 180/pi (rad->deg)
136  * q.v.y *= Math::GaDegreesInRadian; //57.2957795131; // 180/pi (rad->deg)
137  * q.v.z *= Math::GaDegreesInRadian; //57.2957795131; // 180/pi (rad->deg)
138  *
139  * if (q.v.x < 0)
140  * q.v.x += 360;
141  * if (q.v.y < 0)
142  * q.v.y += 360;
143  * if (q.v.z < 0)
144  * q.v.z += 360;
145  */
146  /*
147  return rotByQuat(from, q_temp);
148 }
149 */
151 {
152  // Only unit quaternions are valid rotations.
153  // Normalize to avoid undefined behavior.
154  v0.normalize();
155  v1.normalize();
156 
157  // Compute the cosine of the angle between the two vectors.
158  double dot = v0.dotProduct(v1);
159 
160  // If the dot product is negative, slerp won't take
161  // the shorter path. Note that v1 and -v1 are equivalent when
162  // the negation is applied to all four components. Fix by
163  // reversing one quaternion.
164  if (dot < 0.0f) {
165  v1 = (v1 * -1);
166  dot = -dot;
167  }
168 
169  if (dot > 0.9995) {
170  // If the inputs are too close for comfort, linearly interpolate
171  // and normalize the result.
172 
173  GaVec3 result = v0 + t*(v1 - v0);
174  result.normalize();
175  return result;
176  }
177 
178  // Since dot is in range [0, 0.9995], acos is safe
179  double theta_0 = acos(dot); // theta_0 = angle between input vectors
180  double theta = theta_0*t; // theta = angle between v0 and result
181  double sin_theta = sin(theta); // compute this value only once
182  double sin_theta_0 = sin(theta_0); // compute this value only once
183 
184  double s0 = cos(theta) - dot * sin_theta / sin_theta_0; // == sin(theta_0 - theta) / sin(theta_0)
185  double s1 = sin_theta / sin_theta_0;
186 
187  return (s0 * v0) + (s1 * v1);
188 }
189 
190 /*
191 public static Vector3 RotateX(Vector3 v1, double rad)
192 {
193  double x = v1.X;
194  double y = (v1.Y * Math.Cos(rad)) - (v1.Z * Math.Sin(rad));
195  double z = (v1.Y * Math.Sin(rad)) + (v1.Z * Math.Cos(rad));
196  return new Vector3(x, y, z);
197 }
198 
199 public Vector3 RotateX(double rad)
200 {
201  return RotateX(this, rad);
202 }
203 
204 public static Vector3 Pitch(Vector3 v1, double rad)
205 {
206  return RotateX(v1, rad);
207 }
208 
209 public Vector3 Pitch(double rad)
210 {
211  return Pitch(this, rad);
212 }
213 public static Vector3 RotateY(Vector3 v1, double rad)
214 {
215  double x = (v1.Z * Math.Sin(rad)) + (v1.X * Math.Cos(rad));
216  double y = v1.Y;
217  double z = (v1.Z * Math.Cos(rad)) - (v1.X * Math.Sin(rad));
218  return new Vector3(x, y, z);
219 }
220 
221 public Vector3 RotateY(double rad)
222 {
223  return RotateY(this, rad);
224 }
225 
226 public static Vector3 Yaw(Vector3 v1, double rad)
227 {
228  return RotateY(v1, rad);
229 }
230 
231 public Vector3 Yaw(double rad)
232 {
233  return Yaw(this, rad);
234 }
235 public static Vector3 RotateZ(Vector3 v1, double rad)
236 {
237  double x = (v1.X * Math.Cos(rad)) - (v1.Y * Math.Sin(rad));
238  double y = (v1.X * Math.Sin(rad)) + (v1.Y * Math.Cos(rad));
239  double z = v1.Z;
240  return new Vector3(x, y, z);
241 }
242 
243 public Vector3 RotateZ(double rad)
244 {
245  return RotateZ(this, rad);
246 }
247 
248 public static Vector3 Roll(Vector3 v1, double rad)
249 {
250  return RotateZ(v1, rad);
251 }
252 
253 public Vector3 Roll(double rad)
254 {
255  return Roll(this, rad);
256 }
257 */
258 
260 {
261  return GaMat4x4
262  (
263  matrix_minor(*this, 1, 2, 3, 1, 2, 3),
264  -matrix_minor(*this, 0, 2, 3, 1, 2, 3),
265  matrix_minor(*this, 0, 1, 3, 1, 2, 3),
266  -matrix_minor(*this, 0, 1, 2, 1, 2, 3),
267 
268  -matrix_minor(*this, 1, 2, 3, 0, 2, 3),
269  matrix_minor(*this, 0, 2, 3, 0, 2, 3),
270  -matrix_minor(*this, 0, 1, 3, 0, 2, 3),
271  matrix_minor(*this, 0, 1, 2, 0, 2, 3),
272 
273  matrix_minor(*this, 1, 2, 3, 0, 1, 3),
274  -matrix_minor(*this, 0, 2, 3, 0, 1, 3),
275  matrix_minor(*this, 0, 1, 3, 0, 1, 3),
276  -matrix_minor(*this, 0, 1, 2, 0, 1, 3),
277 
278  -matrix_minor(*this, 1, 2, 3, 0, 1, 2),
279  matrix_minor(*this, 0, 2, 3, 0, 1, 2),
280  -matrix_minor(*this, 0, 1, 3, 0, 1, 2),
281  matrix_minor(*this, 0, 1, 2, 0, 1, 2)
282  );
283 }
284 
286 {
287  return m[0][0] * matrix_minor(*this, 1, 2, 3, 1, 2, 3) -
288  m[0][1] * matrix_minor(*this, 1, 2, 3, 0, 2, 3) +
289  m[0][2] * matrix_minor(*this, 1, 2, 3, 0, 1, 3) -
290  m[0][3] * matrix_minor(*this, 1, 2, 3, 0, 1, 2);
291 }
292 
294 {
295  return adjoint() * (1.0f / determinant());
296 }
297 
299 {
300  // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
301  // article "Quaternion Calculus and Fast Animation".
302 
303  GaFloat fTrace = rot[0][0]+rot[1][1]+rot[2][2];
304  GaFloat fRoot;
305 
306  if ( fTrace > 0.0f )
307  {
308  // |w| > 1/2, may as well choose w > 1/2
309  fRoot = Math::squareRoot(fTrace + 1.0f); // 2w
310  w = 0.5f*fRoot;
311  fRoot = 0.5f/fRoot; // 1/(4w)
312  v.x = (rot[2][1]-rot[1][2])*fRoot;
313  v.y = (rot[0][2]-rot[2][0])*fRoot;
314  v.z = (rot[1][0]-rot[0][1])*fRoot;
315  }
316  else
317  {
318  // |w| <= 1/2
319  static GaUint s_iNext[3] = { 1, 2, 0 };
320  GaUint i = 0;
321  if ( rot[1][1] > rot[0][0] )
322  i = 1;
323  if ( rot[2][2] > rot[i][i] )
324  i = 2;
325  GaUint j = s_iNext[i];
326  GaUint k = s_iNext[j];
327 
328  fRoot = Math::squareRoot(rot[i][i]-rot[j][j]-rot[k][k] + 1.0f);
329  GaFloat* apkQuat[3] = { &v.x, &v.y, &v.z };
330  *apkQuat[i] = 0.5f*fRoot;
331  fRoot = 0.5f/fRoot;
332  w = (rot[k][j]-rot[j][k])*fRoot;
333  *apkQuat[j] = (rot[j][i]+rot[i][j])*fRoot;
334  *apkQuat[k] = (rot[k][i]+rot[i][k])*fRoot;
335  }
336 }
337 
339 {
340  GaFloat nrm = w*w + v.x*v.x + v.y*v.y + v.z*v.z;
341  if(nrm > 0.0)
342  {
343  GaFloat inv = 1.0f/nrm;
344  return GaQuat(w*inv,-v.x*inv,-v.y*inv,-v.z*inv);
345  }
346  else
347  {
348  return GaQuat(0,0,0,0);
349  }
350 }
351 
353 {
354  d = a.r * Math::GaRadianInDegree;
355 }
356 
GaMat4x4 inverse() const
Definition: GaTypes.cpp:293
GaVec3 v
Definition: GaTypes.h:267
GaExpInl GaFloat dotProduct(const GaVec3 &oth) const
Definition: GaTypes.h:150
static GaQuat IDENTITY
Definition: GaTypes.h:221
GaFloat m[4][4]
Definition: GaTypes.h:440
static const GaExport GaFloat GaPi
Definition: GaMath.h:31
unsigned int GaUint
Definition: GaPreReqs.h:66
Definition: GaMath.h:26
GaFloat determinant() const
Definition: GaTypes.cpp:285
GaFloat d
Definition: GaTypes.h:450
GaVec3 rotationTo(const Ga::GaVec3 &pos) const
Definition: GaTypes.cpp:67
GaFloat x
Definition: GaTypes.h:207
GaExpInl GaFloat normalize()
Definition: GaTypes.h:163
GaQuat inverse() const
Definition: GaTypes.cpp:338
GaFloat matrix_minor(const GaMat4x4 &m, GaUint r0, GaUint r1, GaUint r2, GaUint c0, GaUint c1, GaUint c2)
Definition: GaTypes.cpp:48
static GaFloat arcTangent(const GaFloat &r)
Definition: GaMath.h:41
GaExpInl GaDegree()
Definition: GaTypes.h:446
GaVec3 slerp(Ga::GaVec3 v0, Ga::GaVec3 v1, double t)
Definition: GaTypes.cpp:150
static GaQuat ZERO
Definition: GaTypes.h:222
static GaFloat squareRoot(GaFloat f)
Definition: GaMath.h:39
GaFloat angle(float ax, float ay, float bx, float by)
Definition: GaTypes.cpp:55
GaMat4x4 adjoint() const
Definition: GaTypes.cpp:259
GaExpInl GaQuat()
Definition: GaTypes.h:224
static const GaExport GaFloat GaDegreesInRadian
Definition: GaMath.h:32
GaFloat w
Definition: GaTypes.h:266
GaExpInl GaMat4x4()
Definition: GaTypes.h:335
static GaFloat sine(const GaFloat &r)
Definition: GaMath.h:44
GaFloat y
Definition: GaTypes.h:207
GaFloat r
Definition: GaTypes.h:460
GaExpInl GaVec3()
Definition: GaTypes.h:45
double GaFloat
Definition: GaPreReqs.h:69
static const GaExport GaFloat GaRadianInDegree
Definition: GaMath.h:33
GaFloat z
Definition: GaTypes.h:207
static GaFloat cosine(const GaFloat &r)
Definition: GaMath.h:43