DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Quat.cpp (6472B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #pragma hdrstop
     30 #include "../precompiled.h"
     31 
     32 /*
     33 =====================
     34 idQuat::ToAngles
     35 =====================
     36 */
     37 idAngles idQuat::ToAngles() const {
     38 	return ToMat3().ToAngles();
     39 }
     40 
     41 /*
     42 =====================
     43 idQuat::ToRotation
     44 =====================
     45 */
     46 idRotation idQuat::ToRotation() const {
     47 	idVec3 vec;
     48 	float angle;
     49 
     50 	vec.x = x;
     51 	vec.y = y;
     52 	vec.z = z;
     53 	angle = idMath::ACos( w );
     54 	if ( angle == 0.0f ) {
     55 		vec.Set( 0.0f, 0.0f, 1.0f );
     56 	} else {
     57 		//vec *= (1.0f / sin( angle ));
     58 		vec.Normalize();
     59 		vec.FixDegenerateNormal();
     60 		angle *= 2.0f * idMath::M_RAD2DEG;
     61 	}
     62 	return idRotation( vec3_origin, vec, angle );
     63 }
     64 
     65 /*
     66 =====================
     67 idQuat::ToMat3
     68 =====================
     69 */
     70 idMat3 idQuat::ToMat3() const {
     71 	idMat3	mat;
     72 	float	wx, wy, wz;
     73 	float	xx, yy, yz;
     74 	float	xy, xz, zz;
     75 	float	x2, y2, z2;
     76 
     77 	x2 = x + x;
     78 	y2 = y + y;
     79 	z2 = z + z;
     80 
     81 	xx = x * x2;
     82 	xy = x * y2;
     83 	xz = x * z2;
     84 
     85 	yy = y * y2;
     86 	yz = y * z2;
     87 	zz = z * z2;
     88 
     89 	wx = w * x2;
     90 	wy = w * y2;
     91 	wz = w * z2;
     92 
     93 	mat[ 0 ][ 0 ] = 1.0f - ( yy + zz );
     94 	mat[ 0 ][ 1 ] = xy - wz;
     95 	mat[ 0 ][ 2 ] = xz + wy;
     96 
     97 	mat[ 1 ][ 0 ] = xy + wz;
     98 	mat[ 1 ][ 1 ] = 1.0f - ( xx + zz );
     99 	mat[ 1 ][ 2 ] = yz - wx;
    100 
    101 	mat[ 2 ][ 0 ] = xz - wy;
    102 	mat[ 2 ][ 1 ] = yz + wx;
    103 	mat[ 2 ][ 2 ] = 1.0f - ( xx + yy );
    104 
    105 	return mat;
    106 }
    107 
    108 /*
    109 =====================
    110 idQuat::ToMat4
    111 =====================
    112 */
    113 idMat4 idQuat::ToMat4() const {
    114 	return ToMat3().ToMat4();
    115 }
    116 
    117 /*
    118 =====================
    119 idQuat::ToCQuat
    120 =====================
    121 */
    122 idCQuat idQuat::ToCQuat() const {
    123 	if ( w < 0.0f ) {
    124 		return idCQuat( -x, -y, -z );
    125 	}
    126 	return idCQuat( x, y, z );
    127 }
    128 
    129 /*
    130 ============
    131 idQuat::ToAngularVelocity
    132 ============
    133 */
    134 idVec3 idQuat::ToAngularVelocity() const {
    135 	idVec3 vec;
    136 
    137 	vec.x = x;
    138 	vec.y = y;
    139 	vec.z = z;
    140 	vec.Normalize();
    141 	return vec * idMath::ACos( w );
    142 }
    143 
    144 /*
    145 =============
    146 idQuat::ToString
    147 =============
    148 */
    149 const char *idQuat::ToString( int precision ) const {
    150 	return idStr::FloatArrayToString( ToFloatPtr(), GetDimension(), precision );
    151 }
    152 
    153 /*
    154 =====================
    155 idQuat::Slerp
    156 
    157 Spherical linear interpolation between two quaternions.
    158 =====================
    159 */
    160 idQuat &idQuat::Slerp( const idQuat &from, const idQuat &to, float t ) {
    161 	idQuat	temp;
    162 	float	omega, cosom, sinom, scale0, scale1;
    163 
    164 	if ( t <= 0.0f ) {
    165 		*this = from;
    166 		return *this;
    167 	}
    168 
    169 	if ( t >= 1.0f ) {
    170 		*this = to;
    171 		return *this;
    172 	}
    173 
    174 	if ( from == to ) {
    175 		*this = to;
    176 		return *this;
    177 	}
    178 
    179 	cosom = from.x * to.x + from.y * to.y + from.z * to.z + from.w * to.w;
    180 	if ( cosom < 0.0f ) {
    181 		temp = -to;
    182 		cosom = -cosom;
    183 	} else {
    184 		temp = to;
    185 	}
    186 
    187 	if ( ( 1.0f - cosom ) > 1e-6f ) {
    188 #if 0
    189 		omega = acos( cosom );
    190 		sinom = 1.0f / sin( omega );
    191 		scale0 = sin( ( 1.0f - t ) * omega ) * sinom;
    192 		scale1 = sin( t * omega ) * sinom;
    193 #else
    194 		scale0 = 1.0f - cosom * cosom;
    195 		sinom = idMath::InvSqrt( scale0 );
    196 		omega = idMath::ATan16( scale0 * sinom, cosom );
    197 		scale0 = idMath::Sin16( ( 1.0f - t ) * omega ) * sinom;
    198 		scale1 = idMath::Sin16( t * omega ) * sinom;
    199 #endif
    200 	} else {
    201 		scale0 = 1.0f - t;
    202 		scale1 = t;
    203 	}
    204 
    205 	*this = ( scale0 * from ) + ( scale1 * temp );
    206 	return *this;
    207 }
    208 
    209 /*
    210 ========================
    211 idQuat::Lerp
    212 
    213 Approximation of spherical linear interpolation between two quaternions. The interpolation 
    214 traces out the exact same curve as Slerp but does not maintain a constant speed across the arc.
    215 ========================
    216 */
    217 idQuat &idQuat::Lerp( const idQuat &from, const idQuat &to, const float t ) {
    218 	if ( t <= 0.0f ) {
    219 		*this = from;
    220 		return *this;
    221 	}
    222 
    223 	if ( t >= 1.0f ) {
    224 		*this = to;
    225 		return *this;
    226 	}
    227 
    228 	if ( from == to ) {
    229 		*this = to;
    230 		return *this;
    231 	}
    232 
    233 	float cosom = from.x * to.x + from.y * to.y + from.z * to.z + from.w * to.w;
    234 
    235 	float scale0 = 1.0f - t;
    236 	float scale1 = ( cosom >= 0.0f ) ? t : -t;
    237 
    238 	x = scale0 * from.x + scale1 * to.x;
    239 	y = scale0 * from.y + scale1 * to.y;
    240 	z = scale0 * from.z + scale1 * to.z;
    241 	w = scale0 * from.w + scale1 * to.w;
    242 
    243 	float s = idMath::InvSqrt( x * x + y * y + z * z + w * w );
    244 
    245 	x *= s;
    246 	y *= s;
    247 	z *= s;
    248 	w *= s;
    249 
    250 	return *this;
    251 }
    252 
    253 /*
    254 =============
    255 idCQuat::ToAngles
    256 =============
    257 */
    258 idAngles idCQuat::ToAngles() const {
    259 	return ToQuat().ToAngles();
    260 }
    261 
    262 /*
    263 =============
    264 idCQuat::ToRotation
    265 =============
    266 */
    267 idRotation idCQuat::ToRotation() const {
    268 	return ToQuat().ToRotation();
    269 }
    270 
    271 /*
    272 =============
    273 idCQuat::ToMat3
    274 =============
    275 */
    276 idMat3 idCQuat::ToMat3() const {
    277 	return ToQuat().ToMat3();
    278 }
    279 
    280 /*
    281 =============
    282 idCQuat::ToMat4
    283 =============
    284 */
    285 idMat4 idCQuat::ToMat4() const {
    286 	return ToQuat().ToMat4();
    287 }
    288 
    289 /*
    290 =============
    291 idCQuat::ToString
    292 =============
    293 */
    294 const char *idCQuat::ToString( int precision ) const {
    295 	return idStr::FloatArrayToString( ToFloatPtr(), GetDimension(), precision );
    296 }
    297 
    298 /*
    299 =====================
    300 Slerp
    301 
    302 Spherical linear interpolation between two quaternions.
    303 =====================
    304 */
    305 idQuat Slerp( const idQuat & from, const idQuat & to, const float t ) {
    306 	return idQuat().Slerp( from, to, t );
    307 }