Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

Quaternion.h

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 // Lamp : Open source game middleware
00003 // Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
00004 //
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //------------------------------------------------------------------------------
00019 
00020 /** @file
00021  * 四元数ヘッダ
00022  * @author Junpee
00023  */
00024 
00025 #ifndef QUATERNION_H_
00026 #define QUATERNION_H_
00027 
00028 #include <Core/Primitive/Vector3.h>
00029 
00030 namespace Lamp{
00031 
00032 //------------------------------------------------------------------------------
00033 /**
00034  * 四元数
00035  *
00036  * このクラスは継承しないで下さい。
00037  */
00038 class Quaternion{
00039 public:
00040     //--------------------------------------------------------------------------
00041     // メンバ変数
00042     //--------------------------------------------------------------------------
00043     /// メンバ変数
00044     union{
00045         /// 各要素
00046         struct{
00047             /// X値
00048             float x;
00049             /// Y値
00050             float y;
00051             /// Z値
00052             float z;
00053             /// W値
00054             float w;
00055         };
00056 
00057         /// 配列
00058         float array[4];
00059     };
00060 
00061     //--------------------------------------------------------------------------
00062     // 定数
00063     //--------------------------------------------------------------------------
00064     /// ゼロ四元数
00065     static const Quaternion zero;
00066 
00067     /// 恒等四元数
00068     static const Quaternion identity;
00069 
00070     //--------------------------------------------------------------------------
00071     // コンストラクタ
00072     //--------------------------------------------------------------------------
00073     /**
00074      * コンストラクタ
00075      *
00076      * このコンストラクタは初期値の設定を行わないため値は不定です。
00077      */
00078     inline Quaternion(){}
00079 
00080     /**
00081      * コンストラクタ
00082      * @param sourceX Xの初期値
00083      * @param sourceY Yの初期値
00084      * @param sourceZ Zの初期値
00085      * @param sourceW Wの初期値
00086      */
00087     inline Quaternion(
00088         float sourceX, float sourceY, float sourceZ, float sourceW) :
00089         x(sourceX), y(sourceY), z(sourceZ), w(sourceW){
00090     }
00091 
00092     /**
00093      * コンストラクタ
00094      * @param source 初期値配列
00095      */
00096     inline explicit Quaternion(const float* const source) :
00097         x(source[0]), y(source[1]), z(source[2]), w(source[3]){
00098     }
00099 
00100     //--------------------------------------------------------------------------
00101     // 値の設定
00102     //--------------------------------------------------------------------------
00103     /**
00104      * 値の設定
00105      * @param sourceX Xの設定値
00106      * @param sourceY Yの設定値
00107      * @param sourceZ Zの設定値
00108      * @param sourceW Wの設定値
00109      */
00110     inline void set(float sourceX, float sourceY, float sourceZ, float sourceW){
00111         x = sourceX;
00112         y = sourceY;
00113         z = sourceZ;
00114         w = sourceW;
00115     }
00116 
00117     /**
00118      * 値の設定
00119      * @param source 設定値配列
00120      */
00121     inline void set(const float* const source){
00122         x = source[0];
00123         y = source[1];
00124         z = source[2];
00125         w = source[3];
00126     }
00127 
00128     /**
00129      * ゼロ四元数の設定
00130      */
00131     inline void setZero(){
00132         set(0.f, 0.f, 0.f, 0.f);
00133     }
00134 
00135     /**
00136      * 恒等四元数の設定
00137      */
00138     inline void setIdentity(){
00139         set(0.f, 0.f, 0.f, 1.f);
00140     }
00141 
00142     //--------------------------------------------------------------------------
00143     // 回転
00144     //--------------------------------------------------------------------------
00145     /**
00146      * 軸指定回転の設定
00147      * @param axis 回転軸
00148      * @param radian ラジアン単位での回転角度
00149      */
00150     inline void setRotationAxis(const Vector3& axis, float radian){
00151         Assert(axis.isUnit());
00152         float halfRadian = radian * 0.5f;
00153         float sin = Math::sin(halfRadian);
00154         x = axis.x * sin;
00155         y = axis.y * sin;
00156         z = axis.z * sin;
00157         w = Math::cos(halfRadian);
00158     }
00159 
00160     /**
00161      * 軸指定回転の追加
00162      * @param axis 回転軸
00163      * @param radian ラジアン単位での回転角度
00164      */
00165     inline void addRotationAxis(const Vector3& axis, float radian){
00166         Quaternion quaternion;
00167         quaternion.setRotationAxis(axis, radian);
00168         (*this) = quaternion * (*this);
00169     }
00170 
00171     /**
00172      * 軸指定回転の取得
00173      * @param axis [out]回転軸を格納するベクトルへのポインタ。
00174      *  回転していないときはゼロベクトル
00175      * @param radian [out]ラジアン単位での回転角度を格納するfloatへのポインタ
00176      */
00177     inline void getRotationAxis(Vector3* axis, float* radian) const{
00178         Assert(isUnit());
00179         axis->set(array);
00180         float halfRadian = Math::acos(w);
00181         *radian = 2.f * halfRadian;
00182         (*axis) *= 1.f / Math::sin(halfRadian);
00183     }
00184 
00185     //--------------------------------------------------------------------------
00186     // 三軸オイラー回転
00187     //--------------------------------------------------------------------------
00188     /**
00189      * XYZ軸回転の設定
00190      * @param radian 各軸におけるラジアン単位での回転角度
00191      */
00192     inline void setRotationXYZ(const Vector3& radian){
00193         float xRadian = radian.x * 0.5f;
00194         float yRadian = radian.y * 0.5f;
00195         float zRadian = radian.z * 0.5f;
00196         float sinX = Math::sin(xRadian);
00197         float cosX = Math::cos(xRadian);
00198         float sinY = Math::sin(yRadian);
00199         float cosY = Math::cos(yRadian);
00200         float sinZ = Math::sin(zRadian);
00201         float cosZ = Math::cos(zRadian);
00202         x =  sinX * cosY * cosZ - cosX * sinY * sinZ;
00203         y =  cosX * sinY * cosZ + sinX * cosY * sinZ;
00204         z =  cosX * cosY * sinZ - sinX * sinY * cosZ;
00205         w =  cosX * cosY * cosZ + sinX * sinY * sinZ;
00206     }
00207 
00208     /**
00209      * XYZ軸回転の追加
00210      * @param radian 各軸におけるラジアン単位での回転角度
00211      */
00212     inline void addRotationXYZ(const Vector3& radian){
00213         Quaternion quaternion;
00214         quaternion.setRotationXYZ(radian);
00215         (*this) = quaternion * (*this);
00216     }
00217 
00218     /**
00219      * XYZ軸回転の取得
00220      * @param radian [out] 各軸におけるラジアン単位での回転角度
00221      * @return 答えが単一であればtrue
00222      */
00223     inline bool getRotationXYZ(Vector3* radian) const{
00224         // Y回転を求める
00225         float x2 = x + x;
00226         float y2 = y + y;
00227         float z2 = z + z;
00228         float xz2 = x * z2;
00229         float wy2 = w * y2;
00230         float temp = -(xz2 - wy2);
00231         // 誤差対策
00232         if(temp >= 1.f){ temp = 1.f; }
00233         else if(temp <= -1.f){ temp = -1.f; }
00234         float yRadian = Math::asin(temp);
00235         radian->y = yRadian;
00236         // 他の回転を求める
00237         float xx2 = x * x2;
00238         float xy2 = x * y2;
00239         float zz2 = z * z2;
00240         float wz2 = w * z2;
00241         if(yRadian < Math::halfPI){
00242             if(yRadian > -Math::halfPI){
00243                 float yz2 = y * z2;
00244                 float wx2 = w * x2;
00245                 float yy2 = y * y2;
00246                 radian->x = Math::atan2((yz2 + wx2), (1.f - (xx2 + yy2)));
00247                 radian->z = Math::atan2((xy2 + wz2), (1.f - (yy2 + zz2)));
00248                 return true;
00249             }else{
00250                 radian->x = -Math::atan2((xy2 - wz2), (1.f - (xx2 + zz2)));
00251                 radian->z = 0.f;
00252                 return false;
00253             }
00254         }else{
00255             radian->x = Math::atan2((xy2 - wz2), (1.f - (xx2 + zz2)));
00256             radian->z = 0.f;
00257             return false;
00258         }
00259     }
00260 
00261     //--------------------------------------------------------------------------
00262     /**
00263      * ZYX軸回転の設定
00264      * @param radian 各軸におけるラジアン単位での回転角度
00265      */
00266     inline void setRotationZYX(const Vector3& radian){
00267         float xRadian = radian.x * 0.5f;
00268         float yRadian = radian.y * 0.5f;
00269         float zRadian = radian.z * 0.5f;
00270         float sinX = Math::sin(xRadian);
00271         float cosX = Math::cos(xRadian);
00272         float sinY = Math::sin(yRadian);
00273         float cosY = Math::cos(yRadian);
00274         float sinZ = Math::sin(zRadian);
00275         float cosZ = Math::cos(zRadian);
00276         x =  sinX * cosY * cosZ + cosX * sinY * sinZ;
00277         y =  cosX * sinY * cosZ - sinX * cosY * sinZ;
00278         z =  cosX * cosY * sinZ + sinX * sinY * cosZ;
00279         w =  cosX * cosY * cosZ - sinX * sinY * sinZ;
00280     }
00281 
00282     /**
00283      * ZYX軸回転の追加
00284      * @param radian 各軸におけるラジアン単位での回転角度
00285      */
00286     inline void addRotationZYX(const Vector3& radian){
00287         Quaternion quaternion;
00288         quaternion.setRotationZYX(radian);
00289         (*this) = quaternion * (*this);
00290     }
00291 
00292     /**
00293      * ZYX軸回転の取得
00294      * @param radian [out] 各軸におけるラジアン単位での回転角度
00295      * @return 答えが単一であればtrue
00296      */
00297     inline bool getRotationZYX(Vector3* radian) const{
00298         // Y回転を求める
00299         float x2 = x + x;
00300         float y2 = y + y;
00301         float z2 = z + z;
00302         float xz2 = x * z2;
00303         float wy2 = w * y2;
00304         float temp = (xz2 + wy2);
00305         // 誤差対策
00306         if(temp >= 1.f){ temp = 1.f; }
00307         else if(temp <= -1.f){ temp = -1.f; }
00308         float yRadian = Math::asin(temp);
00309         radian->y = yRadian;
00310         // 他の回転を求める
00311         float xy2 = x * y2;
00312         float wz2 = w * z2;
00313         if(yRadian < Math::halfPI){
00314             if(yRadian > -Math::halfPI){
00315                 float yy2 = y * y2;
00316                 float zz2 = z * z2;
00317                 float yz2 = y * z2;
00318                 float wx2 = w * x2;
00319                 float xx2 = x * x2;
00320                 radian->z = Math::atan2(-(xy2 - wz2), (1.f - (yy2 + zz2)));
00321                 radian->x = Math::atan2(-(yz2 - wx2), (1.f - (xx2 + yy2)));
00322                 return true;
00323             }else{
00324                 radian->z = -Math::atan2(-(xy2 + wz2), (xz2 - wy2));
00325                 radian->x = 0.f;
00326                 return false;
00327             }
00328         }else{
00329             radian->z = Math::atan2((xy2 + wz2), -(xz2 - wy2));
00330             radian->x = 0.f;
00331             return false;
00332         }
00333     }
00334 
00335     //--------------------------------------------------------------------------
00336     // 演算
00337     //--------------------------------------------------------------------------
00338     /**
00339      * 加算
00340      * @param addQuaternion 加算する四元数
00341      * @return 加算された四元数
00342      */
00343     inline Quaternion operator +(const Quaternion& addQuaternion) const{
00344         return Quaternion(
00345             x + addQuaternion.x,
00346             y + addQuaternion.y,
00347             z + addQuaternion.z,
00348             w + addQuaternion.w);
00349     }
00350 
00351     /**
00352      * 減算
00353      * @param subQuaternion 減算する四元数
00354      * @return 減算された四元数
00355      */
00356     inline Quaternion operator -(const Quaternion& subQuaternion) const{
00357         return Quaternion(
00358             x - subQuaternion.x,
00359             y - subQuaternion.y,
00360             z - subQuaternion.z,
00361             w - subQuaternion.w);
00362     }
00363 
00364     /**
00365      * 乗算
00366      * @param mulQuat 乗算する四元数
00367      * @return 乗算された四元数
00368      */
00369     inline Quaternion operator *(const Quaternion& mulQuat) const{
00370         // xyz = (q0.xyz * q1.w) + (q1.xyz * q0.w) + cross(q0.xyz, q1.xyz)
00371         // w = q0.w * q1.w - dot(q0.xyz, q1.xyz)
00372         return Quaternion(
00373             y * mulQuat.z - z * mulQuat.y + x * mulQuat.w + w * mulQuat.x,
00374             z * mulQuat.x - x * mulQuat.z + y * mulQuat.w + w * mulQuat.y,
00375             x * mulQuat.y - y * mulQuat.x + z * mulQuat.w + w * mulQuat.z,
00376             w * mulQuat.w - x * mulQuat.x - y * mulQuat.y - z * mulQuat.z);
00377     }
00378 
00379     /**
00380      * 乗算
00381      * @param mulValue 乗算する値
00382      * @return 乗算された四元数
00383      */
00384     inline Quaternion operator *(float mulValue) const{
00385         return Quaternion(
00386             x * mulValue, y * mulValue, z * mulValue, w * mulValue);
00387     }
00388 
00389     /**
00390      * 乗算
00391      * @param mulValue 乗算する値
00392      * @param mulQuaternion 乗算する四元数
00393      * @return 乗算された四元数
00394      */
00395     inline friend Quaternion operator *(
00396         float mulValue, const Quaternion& mulQuaternion){
00397         return Quaternion(
00398             mulQuaternion.x * mulValue,
00399             mulQuaternion.y * mulValue,
00400             mulQuaternion.z * mulValue,
00401             mulQuaternion.w * mulValue);
00402     }
00403 
00404     /**
00405      * ベクトル乗算
00406      * @param mulVector 乗算するベクトル
00407      * @return 乗算されたベクトル
00408      */
00409     inline Vector3 operator *(const Vector3& mulVector) const{
00410         Vector3 quaternion(x, y, z);
00411         Vector3 cross1 = quaternion.crossProduct(mulVector);
00412         Vector3 cross2 = quaternion.crossProduct(cross1);
00413         cross1 *= (w * 2.f);
00414         cross1 += mulVector;
00415         cross2 *= 2.f;
00416         cross1 += cross2;
00417         return cross1;
00418     }
00419 
00420     /**
00421      * +演算子
00422      * @return 四元数のコピー
00423      */
00424     inline Quaternion operator +() const{ return *this; }
00425 
00426     /**
00427      * -演算子
00428      * @return 値の符号が反転した四元数
00429      */
00430     inline Quaternion operator -() const{ return Quaternion(-x, -y, -z, -w); }
00431 
00432     //--------------------------------------------------------------------------
00433     // 代入演算
00434     //--------------------------------------------------------------------------
00435     /**
00436      * 代入加算
00437      * @param addQuaternion 加算する四元数
00438      * @return 加算された四元数
00439      */
00440     inline Quaternion& operator +=(const Quaternion& addQuaternion){
00441         x += addQuaternion.x;
00442         y += addQuaternion.y;
00443         z += addQuaternion.z;
00444         w += addQuaternion.w;
00445         return *this;
00446     }
00447 
00448     /**
00449      * 代入減算
00450      * @param subQuaternion 減算する四元数
00451      * @return 減算された四元数
00452      */
00453     inline Quaternion& operator -=(const Quaternion& subQuaternion){
00454         x -= subQuaternion.x;
00455         y -= subQuaternion.y;
00456         z -= subQuaternion.z;
00457         w -= subQuaternion.w;
00458         return *this;
00459     }
00460 
00461     /**
00462      * 代入乗算
00463      * @param mulQuat 乗算する四元数
00464      * @return 乗算された四元数
00465      */
00466     inline Quaternion& operator *=(const Quaternion& mulQuat){
00467         // xyz = (q0.xyz * q1.w) + (q1.xyz * q0.w) + cross(q0.xyz, q1.xyz)
00468         // w = q0.w * q1.w - dot(q0.xyz, q1.xyz)
00469         set(y * mulQuat.z - z * mulQuat.y + x * mulQuat.w + w * mulQuat.x,
00470             z * mulQuat.x - x * mulQuat.z + y * mulQuat.w + w * mulQuat.y,
00471             x * mulQuat.y - y * mulQuat.x + z * mulQuat.w + w * mulQuat.z,
00472             w * mulQuat.w - x * mulQuat.x - y * mulQuat.y - z * mulQuat.z);
00473         return *this;
00474     }
00475 
00476     /**
00477      * 代入乗算
00478      * @param mulValue 乗算する値
00479      * @return 乗算された四元数
00480      */
00481     inline Quaternion& operator *=(float mulValue){
00482         x *= mulValue;
00483         y *= mulValue;
00484         z *= mulValue;
00485         w *= mulValue;
00486         return *this;
00487     }
00488 
00489     //--------------------------------------------------------------------------
00490     // 長さ関連
00491     //--------------------------------------------------------------------------
00492     /**
00493      * 長さの取得
00494      * @return 長さ
00495      */
00496     inline float getLength() const{
00497         return Math::sqrt(x * x + y * y + z * z + w * w);
00498     }
00499 
00500     /**
00501      * ゼロ四元数かどうか
00502      * @return ゼロ四元数ならtrueを返す
00503      */
00504     inline bool isZero() const{
00505         return (getLength() <= Math::epsilon);
00506     }
00507 
00508     /**
00509      * 単位四元数かどうか
00510      * @return 単位四元数ならtrueを返す
00511      */
00512     inline bool isUnit() const{
00513         return (Math::abs(getLength() - 1.f) <= Math::epsilon);
00514     }
00515 
00516     /**
00517      * 正規化
00518      * @return 正規化された四元数
00519      */
00520     inline Quaternion& normalize(){
00521         float legnth = getLength();
00522         Assert(legnth >= Math::epsilon);
00523         float inverseLength = 1.f / legnth;
00524         (*this) *= inverseLength;
00525         return *this;
00526     }
00527 
00528     //--------------------------------------------------------------------------
00529     // 四元数演算
00530     //--------------------------------------------------------------------------
00531     /**
00532      * ノルムの取得
00533      * @return ノルム
00534      */
00535     inline float getNorm() const{
00536         return x * x + y * y + z * z + w * w;
00537     }
00538 
00539     /**
00540      * 共役
00541      * @return 共役化された四元数
00542      */
00543     inline Quaternion& conjugate(){
00544         x = -x;
00545         y = -y;
00546         z = -z;
00547         return *this;
00548     }
00549 
00550     /**
00551      * 内積
00552      * @param dotQuaternion 内積をとる四元数
00553      * @return 内積値
00554      */
00555     inline float dotProduct(const Quaternion& dotQuaternion) const{
00556         return x * dotQuaternion.x + y * dotQuaternion.y +
00557             z * dotQuaternion.z + w * dotQuaternion.w;
00558     }
00559 
00560     /**
00561      * 逆四元数
00562      * @return 逆四元数
00563      */
00564     inline Quaternion& invert(){
00565         Assert(!isZero());
00566         float inverseNorm = 1.f / getNorm();
00567         x = -x * inverseNorm;
00568         y = -y * inverseNorm;
00569         z = -z * inverseNorm;
00570         w =  w * inverseNorm;
00571         return *this;
00572     }
00573 
00574     /**
00575      * 単位逆四元数
00576      * @return 逆四元数
00577      */
00578     inline Quaternion& unitInvert(){
00579         Assert(isUnit());
00580         return conjugate();
00581     }
00582 
00583     //--------------------------------------------------------------------------
00584     // 補間
00585     //--------------------------------------------------------------------------
00586     /**
00587      * 球面線形補間
00588      * @param source 補間開始四元数
00589      * @param target 補間終了四元数
00590      * @param alpha 補間係数
00591      * @return 補間済み四元数
00592      */
00593     static Quaternion slerp(
00594         const Quaternion& source, const Quaternion& target, float alpha){
00595         Assert(source.isUnit());
00596         Assert(target.isUnit());
00597         float dot = source.dotProduct(target);
00598         // 誤差対策
00599         if(dot >= 1.f){
00600             dot = 1.f;
00601         }else if(dot <= -1.f){
00602             dot = -1.f;
00603         }
00604         float radian = Math::acos(dot);
00605         if(Math::abs(radian) < Math::epsilon){ return target; }
00606         float inverseSin = 1.f / Math::sin(radian);
00607         float leftScale = Math::sin((1.f - alpha) * radian) * inverseSin;
00608         float rightScale = Math::sin(alpha * radian) * inverseSin;
00609         return source * leftScale + target * rightScale;
00610     }
00611 
00612     /**
00613      * 補正付球面線形補間
00614      * @param source 補間開始四元数
00615      * @param target 補間終了四元数
00616      * @param alpha 補間係数
00617      * @return 補間済み四元数
00618      */
00619     static Quaternion correctSlerp(
00620         const Quaternion& source, const Quaternion& target, float alpha){
00621         Assert(source.isUnit());
00622         Assert(target.isUnit());
00623         float dot = source.dotProduct(target);
00624         // 反転処理
00625         Quaternion correctTarget;
00626         if(dot < 0.f){
00627             correctTarget = -target;
00628             dot = -dot;
00629         }else{
00630             correctTarget = target;
00631         }
00632         // 誤差対策
00633         if(dot >= 1.f){ dot = 1.f; }
00634         float radian = Math::acos(dot);
00635         if(Math::abs(radian) < Math::epsilon){ return correctTarget; }
00636         float inverseSin = 1.f / Math::sin(radian);
00637         float leftScale = Math::sin((1.f - alpha) * radian) * inverseSin;
00638         float rightScale = Math::sin(alpha * radian) * inverseSin;
00639         return source * leftScale + correctTarget * rightScale;
00640     }
00641 
00642     /**
00643      * 球面二次補間
00644      * @param source 補間開始四元数
00645      * @param sourceHandle 補間開始四元数ハンドル
00646      * @param targetHandle 補間終了四元数ハンドル
00647      * @param target 補間終了四元数
00648      * @param alpha 補間係数
00649      * @return 補間済み四元数
00650      */
00651     static Quaternion squad(
00652         const Quaternion& source, const Quaternion& sourceHandle,
00653         const Quaternion& targetHandle, const Quaternion& target, float alpha){
00654         Quaternion slerpOriginal = slerp(source, target, alpha);
00655         Quaternion slerpHandle = slerp(sourceHandle, targetHandle, alpha);
00656         return slerp(slerpOriginal, slerpHandle, 2.f * alpha * (1.f - alpha));
00657     }
00658 
00659     /**
00660      * 補正付球面二次補間
00661      * @param source 補間開始四元数
00662      * @param sourceHandle 補間開始四元数ハンドル
00663      * @param targetHandle 補間終了四元数ハンドル
00664      * @param target 補間終了四元数
00665      * @param alpha 補間係数
00666      * @return 補間済み四元数
00667      */
00668     static Quaternion correctSquad(
00669         const Quaternion& source, const Quaternion& sourceHandle,
00670         const Quaternion& targetHandle, const Quaternion& target, float alpha){
00671         Quaternion slerpOriginal =
00672             correctSlerp(source, target, alpha);
00673         Quaternion slerpHandle =
00674             correctSlerp(sourceHandle, targetHandle, alpha);
00675         return correctSlerp(
00676             slerpOriginal, slerpHandle, 2.f * alpha * (1.f - alpha));
00677     }
00678 
00679     //--------------------------------------------------------------------------
00680     // 論理演算
00681     //--------------------------------------------------------------------------
00682     /**
00683      * 四元数が同じかどうか
00684      * @param target 比較する四元数
00685      * @return 同じ値であればtrueを返す
00686      */
00687     inline bool operator ==(const Quaternion& target) const{
00688         return ((x == target.x) && (y == target.y) &&
00689             (z == target.z) && (w == target.w));
00690     }
00691 
00692     /**
00693      * 四元数が同じかどうか
00694      * @param target 比較する四元数
00695      * @param epsilon 誤差
00696      * @return 誤差の範囲内で同じ値であればtrueを返す
00697      */
00698     inline bool epsilonEquals(const Quaternion& target, float epsilon) const{
00699         Assert(epsilon >= 0.f);
00700         return (
00701             (Math::abs(x - target.x) <= epsilon) &&
00702             (Math::abs(y - target.y) <= epsilon) &&
00703             (Math::abs(z - target.z) <= epsilon) &&
00704             (Math::abs(w - target.w) <= epsilon));
00705     }
00706 
00707     /**
00708      * 四元数が同じでないかどうか
00709      * @param target 比較する四元数
00710      * @return 同じでない値であればtrueを返す
00711      */
00712     inline bool operator !=(const Quaternion& target) const{
00713         return ((x != target.x) || (y != target.y) ||
00714             (z != target.z) || (w != target.w));
00715     }
00716 
00717     /**
00718      * 四元数が同じでないかどうか
00719      * @param target 比較する四元数
00720      * @param epsilon 誤差
00721      * @return 誤差の範囲内で同じでない値であればtrueを返す
00722      */
00723     inline bool notEpsilonEquals(const Quaternion& target, float epsilon) const{
00724         Assert(epsilon >= 0.f);
00725         return (
00726             (Math::abs(x - target.x) > epsilon) ||
00727             (Math::abs(y - target.y) > epsilon) ||
00728             (Math::abs(z - target.z) > epsilon) ||
00729             (Math::abs(w - target.w) > epsilon));
00730     }
00731 
00732     //--------------------------------------------------------------------------
00733     /**
00734      * 四元数が同じ回転をあらわすかどうか
00735      * @param target 比較する四元数
00736      * @return 同じ回転をあらわせばtrueを返す
00737      */
00738     inline bool rotationEquals(const Quaternion& target) const{
00739         if((*this) == target){ return true; }
00740         if((*this) == -target){ return true; }
00741         return false;
00742     }
00743 
00744     /**
00745      * 四元数が同じ回転をあらわすかどうか
00746      * @param target 比較する四元数
00747      * @param epsilon 誤差
00748      * @return 誤差の範囲内で同じ回転をあらわせばtrueを返す
00749      */
00750     inline bool epsilonRotationEquals(
00751         const Quaternion& target, float epsilon) const{
00752         if(epsilonEquals(target, epsilon)){ return true; }
00753         if(epsilonEquals(-target, epsilon)){ return true; }
00754         return false;
00755     }
00756 
00757     //--------------------------------------------------------------------------
00758     // その他
00759     //--------------------------------------------------------------------------
00760     /**
00761      * 文字列化
00762      * @return ベクトルの文字列表記
00763      */
00764     inline String toString() const{
00765         String returnString;
00766         returnString.format("( < %.8f, %.8f, %.8f > %.8f )", x, y, z, w);
00767         return returnString;
00768     }
00769 
00770     //--------------------------------------------------------------------------
00771 private:
00772 
00773 };
00774 
00775 //------------------------------------------------------------------------------
00776 } // End of namespace Lamp
00777 #endif // End of QUATERNION_H_
00778 //------------------------------------------------------------------------------

Generated on Wed Mar 16 10:29:34 2005 for Lamp by doxygen 1.3.2