| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* $Header: /Commando/Code/wwmath/quat.h 29 5/11/01 7:11p Jani_p $ */
- /***************************************************************************
- *** Confidential - Westwood Studios ***
- ***************************************************************************
- * *
- * Project Name : Voxel Technology *
- * *
- * File Name : QUAT.H *
- * *
- * Programmer : Greg Hjelstrom *
- * *
- * Start Date : 02/24/97 *
- * *
- * Last Update : February 24, 1997 [GH] *
- * *
- *-------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #if defined(_MSC_VER)
- #pragma once
- #endif
- #ifndef QUAT_H
- #define QUAT_H
- #include "always.h"
- #include "wwmath.h"
- #include "matrix3.h"
- #include "vector3.h"
- class Quaternion
- {
- private:
- public:
- // X,Y,Z are the imaginary parts of the quaterion
- // W is the real part
- float X;
- float Y;
- float Z;
- float W;
- public:
- WWINLINE Quaternion(void) {};
- WWINLINE explicit Quaternion(bool init) { if (init) { X = 0.0f; Y = 0.0f; Z = 0.0f; W = 1.0f; } }
- WWINLINE explicit Quaternion(float a, float b, float c, float d) { X=a; Y=b; Z=c; W=d; }
- WWINLINE explicit Quaternion(const Vector3 & axis,float angle);
- WWINLINE Quaternion & operator=(const Quaternion & source);
- WWINLINE void Set(float a = 0.0, float b = 0.0, float c = 0.0, float d = 1.0) { X = a; Y = b; Z = c; W = d; }
- WWINLINE void Make_Identity(void) { Set(); };
- WWINLINE void Scale(float s) { X = (float)(s*X); Y = (float)(s*Y); Z = (float)(s*Z); W = (float)(s*W); }
- // Array access
- WWINLINE float & operator [](int i) { return (&X)[i]; }
- WWINLINE const float & operator [](int i) const { return (&X)[i]; }
- // Unary operators.
- // Remember that q and -q represent the same 3D rotation.
- WWINLINE Quaternion operator-() const { return(Quaternion(-X,-Y,-Z,-W)); }
- WWINLINE Quaternion operator+() const { return *this; }
- // Every 3D rotation can be expressed by two different quaternions, This
- // function makes the current quaternion convert itself to the representation
- // which is closer on the 4D unit-hypersphere to the given quaternion.
- Quaternion & Make_Closest(const Quaternion & qto);
- // Square of the magnitude of the quaternion
- WWINLINE float Length2(void) const { return (X*X + Y*Y + Z*Z + W*W); }
- // Magnitude of the quaternion
- WWINLINE float Length(void) const { return WWMath::Sqrt(Length2()); }
- // Make the quaternion unit length
- void Normalize(void);
- // post-concatenate rotations about the coordinate axes
- void Rotate_X(float theta);
- void Rotate_Y(float theta);
- void Rotate_Z(float theta);
- // initialize this quaternion randomly (creates a random *unit* quaternion)
- void Randomize(void);
- // transform (rotate) a vector with this quaternion
- WWINLINE Vector3 Rotate_Vector(const Vector3 & v) const;
- WWINLINE void Rotate_Vector(const Vector3 & v,Vector3 * set_result) const;
- // verify that none of the members of this quaternion are invalid floats
- bool Is_Valid(void) const;
- };
- // Inverse of the quaternion (1/q)
- WWINLINE Quaternion Inverse(const Quaternion & a)
- {
- return Quaternion(-a[0],-a[1],-a[2],a[3]);
- }
- // Conjugate of the quaternion
- WWINLINE Quaternion Conjugate(const Quaternion & a)
- {
- return Quaternion(-a[0],-a[1],-a[2],a[3]);
- }
- // Add two quaternions
- WWINLINE Quaternion operator + (const Quaternion & a,const Quaternion & b)
- {
- return Quaternion(a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]);
- }
- // Subract two quaternions
- WWINLINE Quaternion operator - (const Quaternion & a,const Quaternion & b)
- {
- return Quaternion(a[0] - b[0], a[1] - b[1], a[2] - b[2], a[3] - b[3]);
- }
- // Multiply a quaternion by a scalar:
- WWINLINE Quaternion operator * (float scl, const Quaternion & a)
- {
- return Quaternion(scl*a[0], scl*a[1], scl*a[2], scl*a[3]);
- }
- // Multiply a quaternion by a scalar
- WWINLINE Quaternion operator * (const Quaternion & a, float scl)
- {
- return scl*a;
- }
- // Multiply two quaternions
- WWINLINE Quaternion operator * (const Quaternion & a,const Quaternion & b)
- {
- return Quaternion
- (
- a.W*b.X + b.W*a.X + (a.Y*b.Z - b.Y*a.Z),
- a.W*b.Y + b.W*a.Y - (a.X*b.Z - b.X*a.Z),
- a.W*b.Z + b.W*a.Z + (a.X*b.Y - b.X*a.Y),
- a.W * b.W - (a.X * b.X + a.Y * b.Y + a.Z * b.Z)
- );
- }
- // Divide two quaternions
- WWINLINE Quaternion operator / (const Quaternion & a,const Quaternion & b)
- {
- return a * Inverse(b);
- }
- // Normalized version of the quaternion
- WWINLINE Quaternion Normalize(const Quaternion & a)
- {
- float mag = a.Length();
- if (0.0f == mag) {
- return a;
- } else {
- float oomag = 1.0f / mag;
- return Quaternion(a[0] * oomag, a[1] * oomag, a[2] * oomag, a[3] * oomag);
- }
- }
- // This function computes a quaternion based on an axis
- // (defined by the given Vector a) and an angle about
- // which to rotate. The angle is expressed in radians.
- Quaternion Axis_To_Quat(const Vector3 &a, float angle);
- // Pass the x and y coordinates of the last and current position
- // of the mouse, scaled so they are from -1.0 to 1.0
- // The quaternion is the computed as the rotation of a trackball
- // between the two points projected onto a sphere. This can
- // be used to implement an intuitive viewing control system.
- Quaternion Trackball(float x0, float y0, float x1, float y1, float sphsize);
- // Spherical Linear interpolation of quaternions
- //Quaternion Slerp(const Quaternion & a,const Quaternion & b,float t);
- void __cdecl Slerp(Quaternion& result, const Quaternion & a,const Quaternion & b,float t);
- // Fast slerp is innaccurate but multiple times faster
- void __cdecl Fast_Slerp(Quaternion& result, const Quaternion & a,const Quaternion & b,float t);
- // Convert a rotation matrix into a quaternion
- Quaternion Build_Quaternion(const Matrix3 & matrix);
- Quaternion Build_Quaternion(const Matrix3D & matrix);
- Quaternion Build_Quaternion(const Matrix4 & matrix);
- // Convert a quaternion into a rotation matrix
- Matrix3 Build_Matrix3(const Quaternion & quat);
- Matrix3D Build_Matrix3D(const Quaternion & quat);
- Matrix4 Build_Matrix4(const Quaternion & quat);
- // Some values can be cached if you are performing multiple slerps
- // between the same two quaternions...
- struct SlerpInfoStruct
- {
- float SinT;
- float Theta;
- bool Flip;
- bool Linear;
- };
- // Cached slerp implementation
- void Slerp_Setup(const Quaternion & p,const Quaternion & q,SlerpInfoStruct * slerpinfo);
- void Cached_Slerp(const Quaternion & p,const Quaternion & q,float alpha,SlerpInfoStruct * slerpinfo,Quaternion * set_q);
- Quaternion Cached_Slerp(const Quaternion & p,const Quaternion & q,float alpha,SlerpInfoStruct * slerpinfo);
- WWINLINE Vector3 Quaternion::Rotate_Vector(const Vector3 & v) const
- {
- float x = W*v.X + (Y*v.Z - v.Y*Z);
- float y = W*v.Y - (X*v.Z - v.X*Z);
- float z = W*v.Z + (X*v.Y - v.X*Y);
- float w = -(X*v.X + Y*v.Y + Z*v.Z);
- return Vector3
- (
- w*(-X) + W*x + (y*(-Z) - (-Y)*z),
- w*(-Y) + W*y - (x*(-Z) - (-X)*z),
- w*(-Z) + W*z + (x*(-Y) - (-X)*y)
- );
- }
- WWINLINE void Quaternion::Rotate_Vector(const Vector3 & v,Vector3 * result) const
- {
- assert(result != NULL);
-
- float x = W*v.X + (Y*v.Z - v.Y*Z);
- float y = W*v.Y - (X*v.Z - v.X*Z);
- float z = W*v.Z + (X*v.Y - v.X*Y);
- float w = -(X*v.X + Y*v.Y + Z*v.Z);
- result->X = w*(-X) + W*x + (y*(-Z) - (-Y)*z);
- result->Y = w*(-Y) + W*y - (x*(-Z) - (-X)*z);
- result->Z = w*(-Z) + W*z + (x*(-Y) - (-X)*y);
- }
- WWINLINE bool Quaternion::Is_Valid(void) const
- {
- return ( WWMath::Is_Valid_Float(X) &&
- WWMath::Is_Valid_Float(Y) &&
- WWMath::Is_Valid_Float(Z) &&
- WWMath::Is_Valid_Float(W) );
- }
- WWINLINE bool Equal_Within_Epsilon(const Quaternion &a, const Quaternion &b, float epsilon)
- {
- return( (WWMath::Fabs(a.X - b.X) < epsilon) &&
- (WWMath::Fabs(a.Y - b.Y) < epsilon) &&
- (WWMath::Fabs(a.Z - b.Z) < epsilon) &&
- (WWMath::Fabs(a.W - b.W) < epsilon) );
- }
- /***********************************************************************************************
- * Quaternion::operator= -- Assignment operator *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 02/24/1997 GH : Created. *
- *=============================================================================================*/
- WWINLINE Quaternion & Quaternion::operator = (const Quaternion & source)
- {
- X = source[0];
- Y = source[1];
- Z = source[2];
- W = source[3];
- return *this;
- }
- #endif /* QUAT_H */
|