]> git.jsancho.org Git - lugaru.git/blob - Source/Quaternions.h
CLEANED UP WHITESPACE
[lugaru.git] / Source / Quaternions.h
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3
4 This file is part of Lugaru.
5
6 Lugaru is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
15 See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */
21
22
23 #ifndef _QUATERNIONS_H_
24 #define _QUATERNIONS_H_
25
26 #ifndef WIN32
27 #pragma mark -
28 #endif
29
30 //#include "Carbon.h"
31 #include "math.h"
32 #include "PhysicsMath.h"
33 #include "gamegl.h"
34
35 /**> Quaternion Structures <**/
36 #define PI      3.14159265355555897932384626
37 #define RADIANS 0
38 #define DEGREES 1
39 #define deg2rad .0174532925
40
41 //using namespace std;
42 typedef float Matrix_t [4][4];
43 struct euler {
44     float x, y, z;
45 };
46 struct angle_axis {
47     float x, y, z, angle;
48 };
49 struct quaternion {
50     float x, y, z, w;
51 };
52
53 class XYZ
54 {
55 public:
56     float x;
57     float y;
58     float z;
59     XYZ() : x(0.0f), y(0.0f), z(0.0f) {}
60     inline XYZ operator+(XYZ add);
61     inline XYZ operator-(XYZ add);
62     inline XYZ operator*(float add);
63     inline XYZ operator*(XYZ add);
64     inline XYZ operator/(float add);
65     inline void operator+=(XYZ add);
66     inline void operator-=(XYZ add);
67     inline void operator*=(float add);
68     inline void operator*=(XYZ add);
69     inline void operator/=(float add);
70     inline void operator=(float add);
71     inline void vec(Vector add);
72     inline bool operator==(XYZ add);
73 };
74
75 /*********************> Quaternion Function definition <********/
76 quaternion To_Quat(int Degree_Flag, euler Euler);
77 quaternion To_Quat(angle_axis Ang_Ax);
78 quaternion To_Quat(Matrix_t m);
79 angle_axis Quat_2_AA(quaternion Quat);
80 void Quat_2_Matrix(quaternion Quat, Matrix_t m);
81 quaternion Normalize(quaternion Quat);
82 quaternion Quat_Mult(quaternion q1, quaternion q2);
83 quaternion QNormalize(quaternion Quat);
84 XYZ Quat2Vector(quaternion Quat);
85
86 inline void CrossProduct(XYZ *P, XYZ *Q, XYZ *V);
87 inline void CrossProduct(XYZ P, XYZ Q, XYZ *V);
88 inline void Normalise(XYZ *vectory);
89 inline float normaldotproduct(XYZ point1, XYZ point2);
90 inline float fast_sqrt (register float arg);
91 bool PointInTriangle(XYZ *p, XYZ normal, XYZ *p1, XYZ *p2, XYZ *p3);
92 bool LineFacet(XYZ p1, XYZ p2, XYZ pa, XYZ pb, XYZ pc, XYZ *p);
93 float LineFacetd(XYZ p1, XYZ p2, XYZ pa, XYZ pb, XYZ pc, XYZ *p);
94 float LineFacetd(XYZ p1, XYZ p2, XYZ pa, XYZ pb, XYZ pc, XYZ n, XYZ *p);
95 float LineFacetd(XYZ *p1, XYZ *p2, XYZ *pa, XYZ *pb, XYZ *pc, XYZ *n, XYZ *p);
96 float LineFacetd(XYZ *p1, XYZ *p2, XYZ *pa, XYZ *pb, XYZ *pc, XYZ *p);
97 bool PointInTriangle(Vector *p, Vector normal, float p11, float p12, float p13, float p21, float p22, float p23, float p31, float p32, float p33);
98 bool LineFacet(Vector p1, Vector p2, Vector pa, Vector pb, Vector pc, Vector *p);
99 inline void ReflectVector(XYZ *vel, const XYZ *n);
100 inline void ReflectVector(XYZ *vel, const XYZ &n);
101 inline XYZ DoRotation(XYZ thePoint, float xang, float yang, float zang);
102 inline XYZ DoRotationRadian(XYZ thePoint, float xang, float yang, float zang);
103 inline float findDistance(XYZ *point1, XYZ *point2);
104 inline float findLength(XYZ *point1);
105 inline float findLengthfast(XYZ *point1);
106 inline float distsq(XYZ *point1, XYZ *point2);
107 inline float distsq(XYZ point1, XYZ point2);
108 inline float distsqflat(XYZ *point1, XYZ *point2);
109 inline float dotproduct(const XYZ *point1, const XYZ *point2);
110 bool sphere_line_intersection (
111     float x1, float y1 , float z1,
112     float x2, float y2 , float z2,
113     float x3, float y3 , float z3, float r );
114 bool sphere_line_intersection (
115     XYZ *p1, XYZ *p2, XYZ *p3, float *r );
116 inline bool DistancePointLine( XYZ *Point, XYZ *LineStart, XYZ *LineEnd, float *Distance, XYZ *Intersection );
117
118
119 inline void Normalise(XYZ *vectory)
120 {
121     static float d;
122     d = fast_sqrt(vectory->x * vectory->x + vectory->y * vectory->y + vectory->z * vectory->z);
123     if (d == 0) {
124         return;
125     }
126     vectory->x /= d;
127     vectory->y /= d;
128     vectory->z /= d;
129 }
130
131 inline XYZ XYZ::operator+(XYZ add)
132 {
133     static XYZ ne;
134     ne = add;
135     ne.x += x;
136     ne.y += y;
137     ne.z += z;
138     return ne;
139 }
140
141 inline XYZ XYZ::operator-(XYZ add)
142 {
143     static XYZ ne;
144     ne = add;
145     ne.x = x - ne.x;
146     ne.y = y - ne.y;
147     ne.z = z - ne.z;
148     return ne;
149 }
150
151 inline XYZ XYZ::operator*(float add)
152 {
153     static XYZ ne;
154     ne.x = x * add;
155     ne.y = y * add;
156     ne.z = z * add;
157     return ne;
158 }
159
160 inline XYZ XYZ::operator*(XYZ add)
161 {
162     static XYZ ne;
163     ne.x = x * add.x;
164     ne.y = y * add.y;
165     ne.z = z * add.z;
166     return ne;
167 }
168
169 inline XYZ XYZ::operator/(float add)
170 {
171     static XYZ ne;
172     ne.x = x / add;
173     ne.y = y / add;
174     ne.z = z / add;
175     return ne;
176 }
177
178 inline void XYZ::operator+=(XYZ add)
179 {
180     x += add.x;
181     y += add.y;
182     z += add.z;
183 }
184
185 inline void XYZ::operator-=(XYZ add)
186 {
187     x = x - add.x;
188     y = y - add.y;
189     z = z - add.z;
190 }
191
192 inline void XYZ::operator*=(float add)
193 {
194     x = x * add;
195     y = y * add;
196     z = z * add;
197 }
198
199 inline void XYZ::operator*=(XYZ add)
200 {
201     x = x * add.x;
202     y = y * add.y;
203     z = z * add.z;
204 }
205
206 inline void XYZ::operator/=(float add)
207 {
208     x = x / add;
209     y = y / add;
210     z = z / add;
211 }
212
213 inline void XYZ::operator=(float add)
214 {
215     x = add;
216     y = add;
217     z = add;
218 }
219
220 inline void XYZ::vec(Vector add)
221 {
222     x = add.x;
223     y = add.y;
224     z = add.z;
225 }
226
227 inline bool XYZ::operator==(XYZ add)
228 {
229     if (x == add.x && y == add.y && z == add.z)
230         return 1;
231     return 0;
232 }
233
234 inline void CrossProduct(XYZ *P, XYZ *Q, XYZ *V)
235 {
236     V->x = P->y * Q->z - P->z * Q->y;
237     V->y = P->z * Q->x - P->x * Q->z;
238     V->z = P->x * Q->y - P->y * Q->x;
239 }
240
241 inline void CrossProduct(XYZ P, XYZ Q, XYZ *V)
242 {
243     V->x = P.y * Q.z - P.z * Q.y;
244     V->y = P.z * Q.x - P.x * Q.z;
245     V->z = P.x * Q.y - P.y * Q.x;
246 }
247
248 inline float fast_sqrt (register float arg)
249 {
250 #if PLATFORM_MACOSX
251     // Can replace with slower return std::sqrt(arg);
252     register float result;
253
254     if (arg == 0.0)
255         return 0.0;
256
257     asm {
258         frsqrte     result, arg         // Calculate Square root
259     }
260
261     // Newton Rhapson iterations.
262     result = result + 0.5 * result * (1.0 - arg * result * result);
263     result = result + 0.5 * result * (1.0 - arg * result * result);
264
265     return result * arg;
266 #else
267     return sqrtf( arg);
268 #endif
269 }
270
271 inline float normaldotproduct(XYZ point1, XYZ point2)
272 {
273     static GLfloat returnvalue;
274     Normalise(&point1);
275     Normalise(&point2);
276     returnvalue = (point1.x * point2.x + point1.y * point2.y + point1.z * point2.z);
277     return returnvalue;
278 }
279
280 inline void ReflectVector(XYZ *vel, const XYZ *n)
281 {
282     ReflectVector(vel, *n);
283 }
284
285 inline void ReflectVector(XYZ *vel, const XYZ &n)
286 {
287     static XYZ vn;
288     static XYZ vt;
289     static float dotprod;
290
291     dotprod = dotproduct(&n, vel);
292     vn.x = n.x * dotprod;
293     vn.y = n.y * dotprod;
294     vn.z = n.z * dotprod;
295
296     vt.x = vel->x - vn.x;
297     vt.y = vel->y - vn.y;
298     vt.z = vel->z - vn.z;
299
300     vel->x = vt.x - vn.x;
301     vel->y = vt.y - vn.y;
302     vel->z = vt.z - vn.z;
303 }
304
305 inline float dotproduct(const XYZ *point1, const XYZ *point2)
306 {
307     static GLfloat returnvalue;
308     returnvalue = (point1->x * point2->x + point1->y * point2->y + point1->z * point2->z);
309     return returnvalue;
310 }
311
312 inline float findDistance(XYZ *point1, XYZ *point2)
313 {
314     return(fast_sqrt((point1->x - point2->x) * (point1->x - point2->x) + (point1->y - point2->y) * (point1->y - point2->y) + (point1->z - point2->z) * (point1->z - point2->z)));
315 }
316
317 inline float findLength(XYZ *point1)
318 {
319     return(fast_sqrt((point1->x) * (point1->x) + (point1->y) * (point1->y) + (point1->z) * (point1->z)));
320 }
321
322
323 inline float findLengthfast(XYZ *point1)
324 {
325     return((point1->x) * (point1->x) + (point1->y) * (point1->y) + (point1->z) * (point1->z));
326 }
327
328 inline float distsq(XYZ *point1, XYZ *point2)
329 {
330     return((point1->x - point2->x) * (point1->x - point2->x) + (point1->y - point2->y) * (point1->y - point2->y) + (point1->z - point2->z) * (point1->z - point2->z));
331 }
332
333 inline float distsq(XYZ point1, XYZ point2)
334 {
335     return((point1.x - point2.x) * (point1.x - point2.x) + (point1.y - point2.y) * (point1.y - point2.y) + (point1.z - point2.z) * (point1.z - point2.z));
336 }
337
338 inline float distsqflat(XYZ *point1, XYZ *point2)
339 {
340     return((point1->x - point2->x) * (point1->x - point2->x) + (point1->z - point2->z) * (point1->z - point2->z));
341 }
342
343 inline XYZ DoRotation(XYZ thePoint, float xang, float yang, float zang)
344 {
345     static XYZ newpoint;
346     if (xang) {
347         xang *= 6.283185f;
348         xang /= 360;
349     }
350     if (yang) {
351         yang *= 6.283185f;
352         yang /= 360;
353     }
354     if (zang) {
355         zang *= 6.283185f;
356         zang /= 360;
357     }
358
359
360     if (yang) {
361         newpoint.z = thePoint.z * cosf(yang) - thePoint.x * sinf(yang);
362         newpoint.x = thePoint.z * sinf(yang) + thePoint.x * cosf(yang);
363         thePoint.z = newpoint.z;
364         thePoint.x = newpoint.x;
365     }
366
367     if (zang) {
368         newpoint.x = thePoint.x * cosf(zang) - thePoint.y * sinf(zang);
369         newpoint.y = thePoint.y * cosf(zang) + thePoint.x * sinf(zang);
370         thePoint.x = newpoint.x;
371         thePoint.y = newpoint.y;
372     }
373
374     if (xang) {
375         newpoint.y = thePoint.y * cosf(xang) - thePoint.z * sinf(xang);
376         newpoint.z = thePoint.y * sinf(xang) + thePoint.z * cosf(xang);
377         thePoint.z = newpoint.z;
378         thePoint.y = newpoint.y;
379     }
380
381     return thePoint;
382 }
383
384 inline float square( float f )
385 {
386     return (f * f) ;
387 }
388
389 inline bool sphere_line_intersection (
390     float x1, float y1 , float z1,
391     float x2, float y2 , float z2,
392     float x3, float y3 , float z3, float r )
393 {
394
395     // x1,y1,z1  P1 coordinates (point of line)
396     // x2,y2,z2  P2 coordinates (point of line)
397     // x3,y3,z3, r  P3 coordinates and radius (sphere)
398     // x,y,z   intersection coordinates
399     //
400     // This function returns a pointer array which first index indicates
401     // the number of intersection point, followed by coordinate pairs.
402
403     //~ static float x , y , z;
404     static float a, b, c, /*mu,*/ i ;
405
406     if (x1 > x3 + r && x2 > x3 + r) return(0);
407     if (x1 < x3 - r && x2 < x3 - r) return(0);
408     if (y1 > y3 + r && y2 > y3 + r) return(0);
409     if (y1 < y3 - r && y2 < y3 - r) return(0);
410     if (z1 > z3 + r && z2 > z3 + r) return(0);
411     if (z1 < z3 - r && z2 < z3 - r) return(0);
412     a =  square(x2 - x1) + square(y2 - y1) + square(z2 - z1);
413     b =  2 * ( (x2 - x1) * (x1 - x3)
414                + (y2 - y1) * (y1 - y3)
415                + (z2 - z1) * (z1 - z3) ) ;
416     c =  square(x3) + square(y3) +
417          square(z3) + square(x1) +
418          square(y1) + square(z1) -
419          2 * ( x3 * x1 + y3 * y1 + z3 * z1 ) - square(r) ;
420     i =   b * b - 4 * a * c ;
421
422     if ( i < 0.0 ) {
423         // no intersection
424         return(0);
425     }
426     return(1);
427 }
428
429 inline bool sphere_line_intersection (
430     XYZ *p1, XYZ *p2, XYZ *p3, float *r )
431 {
432
433     // x1,p1->y,p1->z  P1 coordinates (point of line)
434     // p2->x,p2->y,p2->z  P2 coordinates (point of line)
435     // p3->x,p3->y,p3->z, r  P3 coordinates and radius (sphere)
436     // x,y,z   intersection coordinates
437     //
438     // This function returns a pointer array which first index indicates
439     // the number of intersection point, followed by coordinate pairs.
440
441     //~ static float x , y , z;
442     static float a, b, c, /*mu,*/ i ;
443
444     if (p1->x > p3->x + *r && p2->x > p3->x + *r) return(0);
445     if (p1->x < p3->x - *r && p2->x < p3->x - *r) return(0);
446     if (p1->y > p3->y + *r && p2->y > p3->y + *r) return(0);
447     if (p1->y < p3->y - *r && p2->y < p3->y - *r) return(0);
448     if (p1->z > p3->z + *r && p2->z > p3->z + *r) return(0);
449     if (p1->z < p3->z - *r && p2->z < p3->z - *r) return(0);
450     a =  square(p2->x - p1->x) + square(p2->y - p1->y) + square(p2->z - p1->z);
451     b =  2 * ( (p2->x - p1->x) * (p1->x - p3->x)
452                + (p2->y - p1->y) * (p1->y - p3->y)
453                + (p2->z - p1->z) * (p1->z - p3->z) ) ;
454     c =  square(p3->x) + square(p3->y) +
455          square(p3->z) + square(p1->x) +
456          square(p1->y) + square(p1->z) -
457          2 * ( p3->x * p1->x + p3->y * p1->y + p3->z * p1->z ) - square(*r) ;
458     i =   b * b - 4 * a * c ;
459
460     if ( i < 0.0 ) {
461         // no intersection
462         return(0);
463     }
464     return(1);
465 }
466
467 inline XYZ DoRotationRadian(XYZ thePoint, float xang, float yang, float zang)
468 {
469     static XYZ newpoint;
470     static XYZ oldpoint;
471
472     oldpoint = thePoint;
473
474     if (yang != 0) {
475         newpoint.z = oldpoint.z * cosf(yang) - oldpoint.x * sinf(yang);
476         newpoint.x = oldpoint.z * sinf(yang) + oldpoint.x * cosf(yang);
477         oldpoint.z = newpoint.z;
478         oldpoint.x = newpoint.x;
479     }
480
481     if (zang != 0) {
482         newpoint.x = oldpoint.x * cosf(zang) - oldpoint.y * sinf(zang);
483         newpoint.y = oldpoint.y * cosf(zang) + oldpoint.x * sinf(zang);
484         oldpoint.x = newpoint.x;
485         oldpoint.y = newpoint.y;
486     }
487
488     if (xang != 0) {
489         newpoint.y = oldpoint.y * cosf(xang) - oldpoint.z * sinf(xang);
490         newpoint.z = oldpoint.y * sinf(xang) + oldpoint.z * cosf(xang);
491         oldpoint.z = newpoint.z;
492         oldpoint.y = newpoint.y;
493     }
494
495     return oldpoint;
496
497 }
498
499 inline bool DistancePointLine( XYZ *Point, XYZ *LineStart, XYZ *LineEnd, float *Distance, XYZ *Intersection )
500 {
501     float LineMag;
502     float U;
503
504     LineMag = findDistance( LineEnd, LineStart );
505
506     U = ( ( ( Point->x - LineStart->x ) * ( LineEnd->x - LineStart->x ) ) +
507           ( ( Point->y - LineStart->y ) * ( LineEnd->y - LineStart->y ) ) +
508           ( ( Point->z - LineStart->z ) * ( LineEnd->z - LineStart->z ) ) ) /
509         ( LineMag * LineMag );
510
511     if ( U < 0.0f || U > 1.0f )
512         return 0;   // closest point does not fall within the line segment
513
514     Intersection->x = LineStart->x + U * ( LineEnd->x - LineStart->x );
515     Intersection->y = LineStart->y + U * ( LineEnd->y - LineStart->y );
516     Intersection->z = LineStart->z + U * ( LineEnd->z - LineStart->z );
517
518     *Distance = findDistance( Point, Intersection );
519
520     return 1;
521 }
522
523 #endif