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