Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
w3dquat.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program 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
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/* $Header: /Commando/Code/Tools/max2w3d/w3dquat.cpp 29 2/03/00 4:55p Jason_a $ */
20/***********************************************************************************************
21 *** Confidential - Westwood Studios ***
22 ***********************************************************************************************
23 * *
24 * Project Name : Voxel Technology *
25 * *
26 * File Name : QUAT.CPP *
27 * *
28 * Programmer : Greg Hjelstrom *
29 * *
30 * Start Date : 02/24/97 *
31 * *
32 * Last Update : February 28, 1997 [GH] *
33 * *
34 *---------------------------------------------------------------------------------------------*
35 * Functions: *
36 * Quaternion::Quaternion -- constructor *
37 * Quaternion::Set -- Set the quaternion *
38 * Quaternion::operator= -- Assignment operator *
39 * Quaternion::Make_Closest -- Use nearest representation to the given quaternion. *
40 * Trackball -- Computes a "trackball" quaternion given 2D mouse coordinates *
41 * Axis_To_Quat -- Creates a quaternion given an axis and angle of rotation *
42 * Slerp -- Spherical Linear interpolation! *
43 * Build_Quaternion -- Creates a quaternion from a Matrix *
44 * Build_Matrix -- Creates a Matrix from a Quaternion *
45 * Normalize -- normalizes a quaternion *
46 * Quaternion::Quaternion -- constructor *
47 * Slerp_Setup -- Get ready to call "Cached_Slerp" *
48 * Cached_Slerp -- Quaternion slerping, optimized with cached values *
49 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
50
51
52#include "w3dquat.h"
53#include "matrix3d.h"
54#include "matrix4.h"
55#include "wwmath.h"
56
57#include <stdio.h>
58//#include <iostream.h>
59#include <stdlib.h>
60#include <math.h>
61#include <assert.h>
62
63#define SLERP_EPSILON 0.001
64
65static int _nxt[3] = { 1 , 2 , 0 };
66
67
68// ------------------------------------------------------------
69// local functions
70// ------------------------------------------------------------
71static float project_to_sphere(float,float,float);
72
73
74/***********************************************************************************************
75 * Quaternion::Quaternion -- constructor *
76 * *
77 * constructs a quaternion from the given axis and angle of rotation (in RADIANS of course) *
78 * *
79 * INPUT: *
80 * axis - axis of the rotation *
81 * angle - rotation angle *
82 * *
83 * OUTPUT: *
84 * *
85 * WARNINGS: *
86 * *
87 * HISTORY: *
88 * 12/10/97 GTH : Created. *
89 *=============================================================================================*/
90Quaternion::Quaternion(const Vector3 & axis,float angle)
91{
92 float s = sinf(angle/2);
93 float c = cosf(angle/2);
94 X = s * axis.X;
95 Y = s * axis.Y;
96 Z = s * axis.Z;
97 W = c;
98}
99
100
101/***********************************************************************************************
102 * Quaternion::Normalize -- Normalize to a unit quaternion *
103 * *
104 * INPUT: *
105 * *
106 * OUTPUT: *
107 * *
108 * WARNINGS: *
109 * *
110 * HISTORY: *
111 * 02/24/1997 GH : Created. *
112 *=============================================================================================*/
114{
115 float mag = WWMath::Sqrt(X * X + Y * Y + Z * Z + W * W);
116
117 if (0.0f == mag) {
118 return;
119 } else {
120 X /= mag;
121 Y /= mag;
122 Z /= mag;
123 W /= mag;
124 }
125}
126
127/***********************************************************************************************
128 * Quaternion::operator= -- Assignment operator *
129 * *
130 * INPUT: *
131 * *
132 * OUTPUT: *
133 * *
134 * WARNINGS: *
135 * *
136 * HISTORY: *
137 * 02/24/1997 GH : Created. *
138 *=============================================================================================*/
140{
141 X = source[0];
142 Y = source[1];
143 Z = source[2];
144 W = source[3];
145
146 return *this;
147}
148
149/***********************************************************************************************
150 * Q::Make_Closest -- Use nearest representation to the given quaternion. *
151 * *
152 * INPUT: *
153 * *
154 * OUTPUT: *
155 * *
156 * WARNINGS: *
157 * *
158 * HISTORY: *
159 * 02/28/1997 GH : Created. *
160 *=============================================================================================*/
162{
163 float cos_t = qto.X * X + qto.Y * Y + qto.Z * Z + qto.W * W;
164
165 // if we are on opposite hemisphere from qto, negate ourselves
166 if (cos_t < 0.0) {
167 X = -X;
168 Y = -Y;
169 Z = -Z;
170 W = -W;
171 }
172
173 return *this;
174}
175
176/***********************************************************************************************
177 * Trackball -- Computes a "trackball" quaternion given 2D mouse coordinates *
178 * *
179 * INPUT: *
180 * x0,y0 - x1,y1 - "normalized" mouse coordinates for the mouse movement *
181 * sphsize - size of the trackball sphere *
182 * *
183 * OUTPUT: *
184 * a quaternion representing the rotation of a trackball *
185 * *
186 * WARNINGS: *
187 * *
188 * HISTORY: *
189 * 02/28/1997 GH : Created. *
190 *=============================================================================================*/
191Quaternion Trackball(float x0, float y0, float x1, float y1, float sphsize)
192{
193 Vector3 a;
194 Vector3 p1;
195 Vector3 p2;
196 Vector3 d;
197
198 float phi,t;
199
200 if ((x0 == x1) && (y0 == y1)) {
201 return Quaternion(0.0f, 0.0f, 0.0f, 1.0f); // Zero rotation
202 }
203
204
205 // Compute z coordinates for projection of p1 and p2 to
206 // deformed sphere
207 p1[0] = x0;
208 p1[1] = y0;
209 p1[2] = project_to_sphere(sphsize, x0, y0);
210
211 p2[0] = x1;
212 p2[1] = y1;
213 p2[2] = project_to_sphere(sphsize, x1, y1);
214
215
216 // Find their cross product
217 Vector3::Cross_Product(p2,p1,&a);
218
219 // Compute how much to rotate
220 d = p1 - p2;
221 t = d.Length() / (2.0f * sphsize);
222
223 // Avoid problems with out of control values
224 if (t > 1.0f) t = 1.0f;
225 if (t < -1.0f) t = -1.0f;
226 phi = 2.0f * asin(t);
227
228 return Axis_To_Quat(a, phi);
229}
230
231
232/***********************************************************************************************
233 * Axis_To_Quat -- Creates a quaternion given an axis and angle of rotation *
234 * *
235 * INPUT: *
236 * *
237 * OUTPUT: *
238 * *
239 * WARNINGS: *
240 * *
241 * HISTORY: *
242 * 02/28/1997 GH : Created. *
243 *=============================================================================================*/
244Quaternion Axis_To_Quat(const Vector3 &a, float phi)
245{
247 Vector3 tmp = a;
248
249 tmp.Normalize();
250 q[0] = tmp[0];
251 q[1] = tmp[1];
252 q[2] = tmp[2];
253
254 q.Scale(sinf(phi / 2.0f));
255 q[3] = cosf(phi / 2.0f);
256
257 return q;
258}
259
260/***********************************************************************************************
261 * Slerp -- Spherical Linear interpolation! *
262 * *
263 * INPUT: *
264 * p - start quaternion *
265 * q - end quaternion *
266 * alpha - interpolating parameter *
267 * *
268 * OUTPUT: *
269 * *
270 * WARNINGS: *
271 * *
272 * HISTORY: *
273 * 02/28/1997 GH : Created. *
274 *=============================================================================================*/
275Quaternion Slerp(const Quaternion & p,const Quaternion & q,float alpha)
276{
277 float beta; // complementary interploation parameter
278 float theta; // angle between p and q
279 float sin_t,cos_t; // sine, cosine of theta
280 float oo_sin_t;
281 int qflip; // use flip of q?
282
283 // cos theta = dot product of p and q
284 cos_t = p.X * q.X + p.Y * q.Y + p.Z * q.Z + p.W * q.W;
285
286 // if q is on opposite hemisphere from A, use -B instead
287 if (cos_t < 0.0) {
288 cos_t = -cos_t;
289 qflip = true;
290 } else {
291 qflip = false;
292 }
293
294 if (1.0 - cos_t < SLERP_EPSILON) {
295
296 // if q is very close to p, just linearly interpolate
297 // between the two.
298 beta = 1.0 - alpha;
299
300 } else {
301
302 // normal slerp!
303 theta = acos(cos_t);
304 sin_t = sinf(theta);
305 oo_sin_t = 1.0 / sin_t;
306 beta = sinf(theta - alpha*theta) * oo_sin_t;
307 alpha = sinf(alpha*theta) * oo_sin_t;
308 }
309
310 if (qflip) {
311 alpha = -alpha;
312 }
313
314 Quaternion res;
315 res.X = beta*p.X + alpha*q.X;
316 res.Y = beta*p.Y + alpha*q.Y;
317 res.Z = beta*p.Z + alpha*q.Z;
318 res.W = beta*p.W + alpha*q.W;
319
320 return res;
321}
322
323
324/***********************************************************************************************
325 * Slerp_Setup -- Get ready to call "Cached_Slerp" *
326 * *
327 * INPUT: *
328 * *
329 * OUTPUT: *
330 * *
331 * WARNINGS: *
332 * *
333 * HISTORY: *
334 * 2/27/98 GTH : Created. *
335 *=============================================================================================*/
336void Slerp_Setup(const Quaternion & p,const Quaternion & q,SlerpInfoStruct * slerpinfo)
337{
338 float cos_t;
339
340 assert(slerpinfo != NULL);
341
342 // cos theta = dot product of p and q
343 cos_t = p.X * q.X + p.Y * q.Y + p.Z * q.Z + p.W * q.W;
344
345 // if q is on opposite hemisphere from A, use -B instead
346 if (cos_t < 0.0) {
347 cos_t = -cos_t;
348 slerpinfo->Flip = true;
349 } else {
350 slerpinfo->Flip = false;
351 }
352
353 if (1.0 - cos_t < SLERP_EPSILON) {
354
355 slerpinfo->Linear = true;
356 slerpinfo->Theta = 0.0f;
357 slerpinfo->SinT = 0.0f;
358
359 } else {
360
361 slerpinfo->Linear = false;
362 slerpinfo->Theta = acos(cos_t);
363 slerpinfo->SinT = sinf(slerpinfo->Theta);
364
365 }
366}
367
368/***********************************************************************************************
369 * Cached_Slerp -- Quaternion slerping, optimized with cached values *
370 * *
371 * INPUT: *
372 * *
373 * OUTPUT: *
374 * *
375 * WARNINGS: *
376 * *
377 * HISTORY: *
378 * 2/27/98 GTH : Created. *
379 *=============================================================================================*/
380Quaternion Cached_Slerp(const Quaternion & p,const Quaternion & q,float alpha,SlerpInfoStruct * slerpinfo)
381{
382 float beta; // complementary interploation parameter
383 float oo_sin_t;
384
385 if (slerpinfo->Linear) {
386
387 // if q is very close to p, just linearly interpolate
388 // between the two.
389 beta = 1.0 - alpha;
390
391 } else {
392
393 // normal slerp!
394 oo_sin_t = 1.0 / slerpinfo->Theta;
395 beta = sin(slerpinfo->Theta - alpha*slerpinfo->Theta) * oo_sin_t;
396 alpha = sin(alpha*slerpinfo->Theta) * oo_sin_t;
397 }
398
399 if (slerpinfo->Flip) {
400 alpha = -alpha;
401 }
402
403 Quaternion res;
404 res.X = beta*p.X + alpha*q.X;
405 res.Y = beta*p.Y + alpha*q.Y;
406 res.Z = beta*p.Z + alpha*q.Z;
407 res.W = beta*p.W + alpha*q.W;
408
409 return res;
410}
411
412void Cached_Slerp(const Quaternion & p,const Quaternion & q,float alpha,SlerpInfoStruct * slerpinfo,Quaternion * set_q)
413{
414 float beta; // complementary interploation parameter
415 float oo_sin_t;
416
417 if (slerpinfo->Linear) {
418
419 // if q is very close to p, just linearly interpolate
420 // between the two.
421 beta = 1.0 - alpha;
422
423 } else {
424
425 // normal slerp!
426 oo_sin_t = 1.0 / slerpinfo->Theta;
427 beta = sin(slerpinfo->Theta - alpha*slerpinfo->Theta) * oo_sin_t;
428 alpha = sin(alpha*slerpinfo->Theta) * oo_sin_t;
429 }
430
431 if (slerpinfo->Flip) {
432 alpha = -alpha;
433 }
434
435 set_q->X = beta*p.X + alpha*q.X;
436 set_q->Y = beta*p.Y + alpha*q.Y;
437 set_q->Z = beta*p.Z + alpha*q.Z;
438 set_q->W = beta*p.W + alpha*q.W;
439}
440
441/***********************************************************************************************
442 * Build_Quaternion -- Creates a quaternion from a Matrix *
443 * *
444 * INPUT: *
445 * *
446 * OUTPUT: *
447 * *
448 * WARNINGS: *
449 * Matrix MUST NOT have scaling! *
450 * *
451 * HISTORY: *
452 * 02/28/1997 GH : Created. *
453 *=============================================================================================*/
455{
456 float tr,s;
457 int i,j,k;
459
460 // sum the diagonal of the rotation matrix
461 tr = mat[0][0] + mat[1][1] + mat[2][2];
462
463 if (tr > 0.0f) {
464
465 s = sqrt(tr + 1.0);
466 q[3] = s * 0.5;
467 s = 0.5 / s;
468
469 q[0] = (mat[2][1] - mat[1][2]) * s;
470 q[1] = (mat[0][2] - mat[2][0]) * s;
471 q[2] = (mat[1][0] - mat[0][1]) * s;
472
473 } else {
474
475 i=0;
476 if (mat[1][1] > mat[0][0]) i = 1;
477 if (mat[2][2] > mat[i][i]) i = 2;
478 j = _nxt[i];
479 k = _nxt[j];
480
481 s = sqrt((mat[i][i] - (mat[j][j] + mat[k][k])) + 1.0);
482
483 q[i] = s * 0.5;
484 if (s != 0.0) {
485 s = 0.5 / s;
486 }
487
488 q[3] = ( mat[k][j] - mat[j][k] ) * s;
489 q[j] = ( mat[j][i] + mat[i][j] ) * s;
490 q[k] = ( mat[k][i] + mat[i][k] ) * s;
491
492 }
493
494 return q;
495}
496
498{
499 float tr,s;
500 int i,j,k;
502
503 // sum the diagonal of the rotation matrix
504 tr = mat[0][0] + mat[1][1] + mat[2][2];
505
506 if (tr > 0.0) {
507
508 s = sqrt(tr + 1.0);
509 q[3] = s * 0.5;
510 s = 0.5 / s;
511
512 q[0] = (mat[2][1] - mat[1][2]) * s;
513 q[1] = (mat[0][2] - mat[2][0]) * s;
514 q[2] = (mat[1][0] - mat[0][1]) * s;
515
516 } else {
517
518 i = 0;
519 if (mat[1][1] > mat[0][0]) i = 1;
520 if (mat[2][2] > mat[i][i]) i = 2;
521
522 j = _nxt[i];
523 k = _nxt[j];
524
525 s = sqrt( (mat[i][i] - (mat[j][j]+mat[k][k])) + 1.0);
526
527 q[i] = s * 0.5;
528
529 if (s != 0.0) {
530 s = 0.5/s;
531 }
532
533 q[3] = ( mat[k][j] - mat[j][k] ) * s;
534 q[j] = ( mat[j][i] + mat[i][j] ) * s;
535 q[k] = ( mat[k][i] + mat[i][k] ) * s;
536 }
537
538 return q;
539}
540
542{
543 float tr,s;
544 int i,j,k;
546
547 // sum the diagonal of the rotation matrix
548 tr = mat[0][0] + mat[1][1] + mat[2][2];
549
550 if (tr > 0.0) {
551
552 s = sqrt(tr + 1.0);
553 q[3] = s * 0.5;
554 s = 0.5 / s;
555
556 q[0] = (mat[2][1] - mat[1][2]) * s;
557 q[1] = (mat[0][2] - mat[2][0]) * s;
558 q[2] = (mat[1][0] - mat[0][1]) * s;
559
560 } else {
561
562 i = 0;
563 if (mat[1][1] > mat[0][0]) i = 1;
564 if (mat[2][2] > mat[i][i]) i = 2;
565
566 j = _nxt[i];
567 k = _nxt[j];
568
569 s = sqrt( (mat[i][i] - (mat[j][j]+mat[k][k])) + 1.0);
570
571 q[i] = s * 0.5;
572 if (s != 0.0) {
573 s = 0.5/s;
574 }
575 q[3] = ( mat[k][j] - mat[j][k] ) * s;
576 q[j] = ( mat[j][i] + mat[i][j] ) * s;
577 q[k] = ( mat[k][i] + mat[i][k] ) * s;
578 }
579
580 return q;
581}
582
583
584/***********************************************************************************************
585 * Build_Matrix -- Creates a Matrix from a Quaternion *
586 * *
587 * INPUT: *
588 * *
589 * OUTPUT: *
590 * *
591 * WARNINGS: *
592 * *
593 * HISTORY: *
594 * 02/28/1997 GH : Created. *
595 *=============================================================================================*/
597{
598 Matrix3 m;
599
600 m[0][0] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]));
601 m[0][1] = (float)(2.0 * (q[0] * q[1] - q[2] * q[3]));
602 m[0][2] = (float)(2.0 * (q[2] * q[0] + q[1] * q[3]));
603
604 m[1][0] = (float)(2.0 * (q[0] * q[1] + q[2] * q[3]));
605 m[1][1] = (float)(1.0 - 2.0f * (q[2] * q[2] + q[0] * q[0]));
606 m[1][2] = (float)(2.0 * (q[1] * q[2] - q[0] * q[3]));
607
608 m[2][0] = (float)(2.0 * (q[2] * q[0] - q[1] * q[3]));
609 m[2][1] = (float)(2.0 * (q[1] * q[2] + q[0] * q[3]));
610 m[2][2] =(float)(1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]));
611
612 return m;
613}
614
616{
617 Matrix3D m;
618
619 // initialize the rotation sub-matrix
620 m[0][0] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]));
621 m[0][1] = (float)(2.0 * (q[0] * q[1] - q[2] * q[3]));
622 m[0][2] = (float)(2.0 * (q[2] * q[0] + q[1] * q[3]));
623
624 m[1][0] = (float)(2.0 * (q[0] * q[1] + q[2] * q[3]));
625 m[1][1] = (float)(1.0 - 2.0f * (q[2] * q[2] + q[0] * q[0]));
626 m[1][2] = (float)(2.0 * (q[1] * q[2] - q[0] * q[3]));
627
628 m[2][0] = (float)(2.0 * (q[2] * q[0] - q[1] * q[3]));
629 m[2][1] = (float)(2.0 * (q[1] * q[2] + q[0] * q[3]));
630 m[2][2] =(float)(1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]));
631
632 // no translation
633 m[0][3] = m[1][3] = m[2][3] = 0.0f;
634
635 return m;
636}
637
639{
640 Matrix4 m;
641
642 // initialize the rotation sub-matrix
643 m[0][0] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]));
644 m[0][1] = (float)(2.0 * (q[0] * q[1] - q[2] * q[3]));
645 m[0][2] = (float)(2.0 * (q[2] * q[0] + q[1] * q[3]));
646
647 m[1][0] = (float)(2.0 * (q[0] * q[1] + q[2] * q[3]));
648 m[1][1] = (float)(1.0 - 2.0f * (q[2] * q[2] + q[0] * q[0]));
649 m[1][2] = (float)(2.0 * (q[1] * q[2] - q[0] * q[3]));
650
651 m[2][0] = (float)(2.0 * (q[2] * q[0] - q[1] * q[3]));
652 m[2][1] = (float)(2.0 * (q[1] * q[2] + q[0] * q[3]));
653 m[2][2] = (float)(1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]));
654
655 // no translation
656 m[0][3] = m[1][3] = m[2][3] = 0.0f;
657
658 // last row
659 m[3][0] = m[3][1] = m[3][2] = 0.0f;
660 m[3][3] = 1.0f;
661 return m;
662}
663
664void Quaternion::Rotate_X(float theta)
665{
666 // TODO: optimize this
667 *this = (*this) * Quaternion(Vector3(1,0,0),theta);
668}
669
670void Quaternion::Rotate_Y(float theta)
671{
672 // TODO: optimize this
673 *this = (*this) * Quaternion(Vector3(0,1,0),theta);
674}
675
676void Quaternion::Rotate_Z(float theta)
677{
678 // TODO: optimize this
679 *this = (*this) * Quaternion(Vector3(0,0,1),theta);
680}
681
682float project_to_sphere(float r, float x, float y)
683{
684 const float SQRT2 = 1.41421356f;
685 float t, z;
686 float d = WWMath::Sqrt(x * x + y * y);
687
688 if (d < r * (SQRT2/(2.0f))) // inside sphere
689 z = WWMath::Sqrt(r * r - d * d);
690 else { // on hyperbola
691 t = r / SQRT2;
692 z = t * t / d;
693 }
694
695 return z;
696}
697
698
699void Quaternion::Randomize(void)
700{
701 X = ((float) (rand() & 0xFFFF)) / 65536.0f;
702 Y = ((float) (rand() & 0xFFFF)) / 65536.0f;
703 Z = ((float) (rand() & 0xFFFF)) / 65536.0f;
704 W = ((float) (rand() & 0xFFFF)) / 65536.0f;
705
706 Normalize();
707}
708
709
#define NULL
Definition BaseType.h:92
float X
Definition quat.h:60
WWINLINE Quaternion(void)
Definition quat.h:67
void Rotate_Y(float theta)
Definition quat.cpp:856
Quaternion & Make_Closest(const Quaternion &qto)
Definition quat.cpp:139
void Normalize(void)
Definition quat.cpp:112
WWINLINE Quaternion & operator=(const Quaternion &source)
Definition quat.h:303
float Z
Definition quat.h:62
void Rotate_X(float theta)
Definition quat.cpp:850
float Y
Definition quat.h:61
void Rotate_Z(float theta)
Definition quat.cpp:862
float W
Definition quat.h:63
void Randomize(void)
Definition quat.cpp:885
float X
Definition vector3.h:90
float Z
Definition vector3.h:92
float Y
Definition vector3.h:91
WWINLINE float Length(void) const
Definition vector3.h:453
void Normalize(void)
Definition vector3.h:417
static WWINLINE void Cross_Product(const Vector3 &a, const Vector3 &b, Vector3 *result)
Definition vector3.h:374
static float Sqrt(float val)
Definition wwmath.h:568
int q
Definition test1.cpp:94
#define SLERP_EPSILON
Definition quat.cpp:62
float Theta
Definition quat.h:236
bool Linear
Definition quat.h:238
float SinT
Definition quat.h:235
Quaternion Cached_Slerp(const Quaternion &p, const Quaternion &q, float alpha, SlerpInfoStruct *slerpinfo)
Definition w3dquat.cpp:380
void Slerp_Setup(const Quaternion &p, const Quaternion &q, SlerpInfoStruct *slerpinfo)
Definition w3dquat.cpp:336
Matrix3 Build_Matrix3(const Quaternion &q)
Definition w3dquat.cpp:596
Matrix3D Build_Matrix3D(const Quaternion &q)
Definition w3dquat.cpp:615
Matrix4 Build_Matrix4(const Quaternion &q)
Definition w3dquat.cpp:638
Quaternion Build_Quaternion(const Matrix3D &mat)
Definition w3dquat.cpp:454
Quaternion Trackball(float x0, float y0, float x1, float y1, float sphsize)
Definition w3dquat.cpp:191
Quaternion Slerp(const Quaternion &p, const Quaternion &q, float alpha)
Definition w3dquat.cpp:275
Quaternion Axis_To_Quat(const Vector3 &a, float phi)
Definition w3dquat.cpp:244