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

Matrix33.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  * 3×3行列ヘッダ
00022  * @author Junpee
00023  */
00024 
00025 #ifndef MATRIX33_H_
00026 #define MATRIX33_H_
00027 
00028 #include <Core/Primitive/Vector3.h>
00029 #include <Core/Primitive/Quaternion.h>
00030 
00031 namespace Lamp{
00032 
00033 class Matrix34;
00034 class Matrix44;
00035 
00036 //------------------------------------------------------------------------------
00037 /**
00038  * 3×3行列
00039  *
00040  * 右手座標系を使用します。
00041  * このクラスは継承しないで下さい。
00042  */
00043 class Matrix33{
00044 public:
00045     //--------------------------------------------------------------------------
00046     // メンバ変数
00047     //--------------------------------------------------------------------------
00048     /// メンバ変数
00049     union{
00050         /// 各要素
00051         struct{
00052             /// 00要素
00053             float m00;
00054             /// 01要素
00055             float m01;
00056             /// 02要素
00057             float m02;
00058             /// 10要素
00059             float m10;
00060             /// 11要素
00061             float m11;
00062             /// 12要素
00063             float m12;
00064             /// 20要素
00065             float m20;
00066             /// 21要素
00067             float m21;
00068             /// 22要素
00069             float m22;
00070         };
00071 
00072         /// 行列値
00073         float m[3][3];
00074 
00075         /// 配列
00076         float array[9];
00077     };
00078 
00079     //--------------------------------------------------------------------------
00080     // 定数
00081     //--------------------------------------------------------------------------
00082     /// ゼロ行列
00083     static const Matrix33 zero;
00084 
00085     /// 単位行列
00086     static const Matrix33 unit;
00087 
00088     //--------------------------------------------------------------------------
00089     // コンストラクタ
00090     //--------------------------------------------------------------------------
00091     /**
00092      * コンストラクタ
00093      *
00094      * このコンストラクタは初期値の設定を行わないため値は不定です。
00095      */
00096     Matrix33(){}
00097 
00098     /**
00099      * コンストラクタ
00100      * @param i00 m00の初期値
00101      * @param i01 m01の初期値
00102      * @param i02 m02の初期値
00103      * @param i10 m10の初期値
00104      * @param i11 m11の初期値
00105      * @param i12 m12の初期値
00106      * @param i20 m20の初期値
00107      * @param i21 m21の初期値
00108      * @param i22 m22の初期値
00109      */
00110     inline Matrix33(
00111         float i00, float i01, float i02,
00112         float i10, float i11, float i12,
00113         float i20, float i21, float i22) :
00114         m00(i00), m01(i01), m02(i02),
00115         m10(i10), m11(i11), m12(i12),
00116         m20(i20), m21(i21), m22(i22){
00117     }
00118 
00119     /**
00120      * コンストラクタ
00121      * @param source 初期値配列
00122      */
00123     inline explicit Matrix33(const float* const source) :
00124         m00(source[ 0]), m01(source[ 1]), m02(source[ 2]),
00125         m10(source[ 3]), m11(source[ 4]), m12(source[ 5]),
00126         m20(source[ 6]), m21(source[ 7]), m22(source[ 8]){
00127     }
00128 
00129     //--------------------------------------------------------------------------
00130     // 値の設定
00131     //--------------------------------------------------------------------------
00132     /**
00133      * 値の設定
00134      * @param s00 m00の設定値
00135      * @param s01 m01の設定値
00136      * @param s02 m02の設定値
00137      * @param s10 m10の設定値
00138      * @param s11 m11の設定値
00139      * @param s12 m12の設定値
00140      * @param s20 m20の設定値
00141      * @param s21 m21の設定値
00142      * @param s22 m22の設定値
00143      */
00144     inline void set(
00145         float s00, float s01, float s02,
00146         float s10, float s11, float s12,
00147         float s20, float s21, float s22){
00148         m00 = s00; m01 = s01; m02 = s02;
00149         m10 = s10; m11 = s11; m12 = s12;
00150         m20 = s20; m21 = s21; m22 = s22;
00151     }
00152 
00153     /**
00154      * 値の設定
00155      * @param source 設定値配列
00156      */
00157     inline void set(const float* const source){
00158         m00 = source[ 0]; m01 = source[ 1]; m02 = source[ 2];
00159         m10 = source[ 3]; m11 = source[ 4]; m12 = source[ 5];
00160         m20 = source[ 6]; m21 = source[ 7]; m22 = source[ 8];
00161     }
00162 
00163     /**
00164      * ゼロ行列設定
00165      */
00166     inline void setZero(){
00167         set(0.f, 0.f, 0.f,
00168             0.f, 0.f, 0.f,
00169             0.f, 0.f, 0.f);
00170     }
00171 
00172     /**
00173      * 単位行列設定
00174      */
00175     inline void setUnit(){
00176         set(1.f, 0.f, 0.f,
00177             0.f, 1.f, 0.f,
00178             0.f, 0.f, 1.f);
00179     }
00180 
00181     /**
00182      * 3×4行列の設定
00183      * @param source 設定元行列
00184      */
00185     void set(const Matrix34& source);
00186 
00187     /**
00188      * 4×4行列の設定
00189      * @param source 設定元行列
00190      */
00191     void set(const Matrix44& source);
00192 
00193     //--------------------------------------------------------------------------
00194     // スケール
00195     //--------------------------------------------------------------------------
00196     /**
00197      * スケールの設定
00198      * @param scaleX Xスケール値
00199      * @param scaleY Yスケール値
00200      * @param scaleZ Zスケール値
00201      */
00202     inline void setScale(float scaleX, float scaleY, float scaleZ){
00203         set(scaleX,    0.f,    0.f,
00204                0.f, scaleY,    0.f,
00205                0.f,    0.f, scaleZ);
00206     }
00207 
00208     /**
00209      * スケールの設定
00210      * @param scale スケール値
00211      */
00212     inline void setScale(const Vector3& scale){
00213         setScale(scale.x, scale.y, scale.z);
00214     }
00215 
00216     /**
00217      * スケールの追加
00218      * @param scaleX Xスケール値
00219      * @param scaleY Yスケール値
00220      * @param scaleZ Zスケール値
00221      */
00222     inline void addScale(float scaleX, float scaleY, float scaleZ){
00223         Matrix33 matrix;
00224         matrix.setScale(scaleX, scaleY, scaleZ);
00225         (*this) = matrix * (*this);
00226     }
00227 
00228     /**
00229      * スケールの追加
00230      * @param scale スケール値
00231      */
00232     inline void addScale(const Vector3& scale){
00233         Matrix33 matrix;
00234         matrix.setScale(scale.x, scale.y, scale.z);
00235         (*this) = matrix * (*this);
00236     }
00237 
00238     //--------------------------------------------------------------------------
00239     // 回転
00240     //--------------------------------------------------------------------------
00241     /**
00242      * X軸回転の設定
00243      * @param radian ラジアン単位での回転角度
00244      */
00245     inline void setRotationX(float radian){
00246         float sin = Math::sin(radian);
00247         float cos = Math::cos(radian);
00248         set( 1.f,  0.f,   0.f,
00249              0.f,  cos,  -sin,
00250              0.f,  sin,   cos);
00251     }
00252 
00253     /**
00254      * X軸回転の追加
00255      * @param radian ラジアン単位での回転角度
00256      */
00257     inline void addRotationX(float radian){
00258         Matrix33 matrix;
00259         matrix.setRotationX(radian);
00260         (*this) = matrix * (*this);
00261     }
00262 
00263     //--------------------------------------------------------------------------
00264     /**
00265      * Y軸回転の設定
00266      * @param radian ラジアン単位での回転角度
00267      */
00268     inline void setRotationY(float radian){
00269         float sin = Math::sin(radian);
00270         float cos = Math::cos(radian);
00271         set( cos,  0.f,  sin,
00272              0.f,  1.f,  0.f,
00273             -sin,  0.f,  cos);
00274     }
00275 
00276     /**
00277      * Y軸回転の追加
00278      * @param radian ラジアン単位での回転角度
00279      */
00280     inline void addRotationY(float radian){
00281         Matrix33 matrix;
00282         matrix.setRotationY(radian);
00283         (*this) = matrix * (*this);
00284     }
00285 
00286     //--------------------------------------------------------------------------
00287     /**
00288      * Z軸回転の設定
00289      * @param radian ラジアン単位での回転角度
00290      */
00291     inline void setRotationZ(float radian){
00292         float sin = Math::sin(radian);
00293         float cos = Math::cos(radian);
00294         set( cos, -sin,  0.f,
00295              sin,  cos,  0.f,
00296              0.f,  0.f,  1.f);
00297     }
00298 
00299     /**
00300      * Z軸回転の追加
00301      * @param radian ラジアン単位での回転角度
00302      */
00303     inline void addRotationZ(float radian){
00304         Matrix33 matrix;
00305         matrix.setRotationZ(radian);
00306         (*this) = matrix * (*this);
00307     }
00308 
00309     //--------------------------------------------------------------------------
00310     /**
00311      * 軸指定回転の設定
00312      * @param axis 回転軸
00313      * @param radian ラジアン単位での回転角度
00314      */
00315     inline void setRotationAxis(const Vector3& axis, float radian){
00316         Assert(axis.isUnit());
00317         float sin = Math::sin(radian);
00318         float cos = Math::cos(radian);
00319         float invCos = 1.f - cos;
00320         float xyInv = axis.x * axis.y * invCos;
00321         float xzInv = axis.x * axis.z * invCos;
00322         float yzInv = axis.y * axis.z * invCos;
00323         float xSin = axis.x * sin;
00324         float ySin = axis.y * sin;
00325         float zSin = axis.z * sin;
00326         set((axis.x * axis.x * invCos + cos), (xyInv - zSin), (xzInv + ySin),
00327             (xyInv + zSin), (axis.y * axis.y * invCos + cos), (yzInv - xSin),
00328             (xzInv - ySin), (yzInv + xSin), (axis.z * axis.z * invCos + cos));
00329     }
00330 
00331     /**
00332      * 軸指定回転の追加
00333      * @param axis 回転軸
00334      * @param radian ラジアン単位での回転角度
00335      */
00336     inline void addRotationAxis(const Vector3& axis, float radian){
00337         Matrix33 matrix;
00338         matrix.setRotationAxis(axis, radian);
00339         (*this) = matrix * (*this);
00340     }
00341 
00342     /**
00343      * 軸指定回転の取得
00344      * @param axis [out]回転軸を格納するベクトルへのポインタ
00345      * @param radian [out]ラジアン単位での回転角度を格納するfloatへのポインタ
00346      */
00347     inline void getRotationAxis(Vector3* axis, float* radian) const{
00348         float radianResult = Math::acos(0.5f * ((m00 + m11 + m22) - 1.f));
00349         *radian = radianResult;
00350         if(radianResult > 0.f){
00351             if(radianResult < Math::PI){
00352                 axis->set(m21 - m12, m02 - m20, m10 - m01);
00353                 axis->normalize();
00354             }else{
00355                 if(m00 >= m11){
00356                     if(m00 >= m22){
00357                         axis->x = 0.5f * Math::sqrt(m00 - m11 - m22 + 1.f);
00358                         float halfInverse = 0.5f / axis->x;
00359                         axis->y = halfInverse * m01;
00360                         axis->z = halfInverse * m02;
00361                     }else{
00362                         axis->z = 0.5f * Math::sqrt(m22 - m00 - m11 + 1.f);
00363                         float halfInverse = 0.5f / axis->z;
00364                         axis->x = halfInverse * m02;
00365                         axis->y = halfInverse * m12;
00366                     }
00367                 }else{
00368                     if(m11 >= m22){
00369                         axis->y = 0.5f * Math::sqrt(m11 - m00 - m22 + 1.f);
00370                         float halfInverse = 0.5f / axis->y;
00371                         axis->x = halfInverse * m01;
00372                         axis->z = halfInverse * m12;
00373                     }else{
00374                         axis->z = 0.5f * Math::sqrt(m22 - m00 - m11 + 1.f);
00375                         float halfInverse = 0.5f / axis->z;
00376                         axis->x = halfInverse * m02;
00377                         axis->y = halfInverse * m12;
00378                     }
00379                 }
00380             }
00381         }else{
00382             axis->set(1.f, 0.f, 0.f);
00383         }
00384     }
00385 
00386     //--------------------------------------------------------------------------
00387     /**
00388      * 四元数回転の設定
00389      * @param quaternion 四元数
00390      */
00391     inline void setRotationQuaternion(const Quaternion& quaternion){
00392         Assert(quaternion.isUnit());
00393         float x2 = quaternion.x + quaternion.x;
00394         float y2 = quaternion.y + quaternion.y;
00395         float z2 = quaternion.z + quaternion.z;
00396         float xx2 = quaternion.x * x2;
00397         float xy2 = quaternion.x * y2;
00398         float xz2 = quaternion.x * z2;
00399         float yy2 = quaternion.y * y2;
00400         float yz2 = quaternion.y * z2;
00401         float zz2 = quaternion.z * z2;
00402         float wx2 = quaternion.w * x2;
00403         float wy2 = quaternion.w * y2;
00404         float wz2 = quaternion.w * z2;
00405         m00 = 1.f - (yy2 + zz2);
00406         m01 = xy2 - wz2;
00407         m02 = xz2 + wy2;
00408 
00409         m10 = xy2 + wz2;
00410         m11 = 1.f - (xx2 + zz2);
00411         m12 = yz2 - wx2;
00412 
00413         m20 = xz2 - wy2;
00414         m21 = yz2 + wx2;
00415         m22 = 1.f - (xx2 + yy2);
00416     }
00417 
00418     /**
00419      * 四元数回転の追加
00420      * @param quaternion 四元数
00421      */
00422     inline void addRotationQuaternion(const Quaternion& quaternion){
00423         Matrix33 matrix;
00424         matrix.setRotationQuaternion(quaternion);
00425         (*this) = matrix * (*this);
00426     }
00427 
00428     /**
00429      * 四元数回転の取得
00430      * @return 回転を表す四元数
00431      */
00432     inline Quaternion getRotationQuaternion() const{
00433         Quaternion result;
00434         float trace = m00 + m11 + m22;
00435         if(trace > 0.f){
00436             float scale = Math::sqrt(trace + 1.f);
00437             result.w = scale * 0.5f;
00438             scale = 0.5f / scale;
00439             result.x = (m21 - m12) * scale;
00440             result.y = (m02 - m20) * scale;
00441             result.z = (m10 - m01) * scale;
00442         }else{
00443             int i = 0;
00444             if(m11 > m00){ i = 1; }
00445             if(m22 > m[i][i]){ i = 2; }
00446             int nextTable[] = { 1, 2, 0 };
00447             int j = nextTable[i];
00448             int k = nextTable[j];
00449             float scale = Math::sqrt(m[i][i] - m[j][j] - m[k][k] + 1.f);
00450             result.array[i] = 0.5f * scale;
00451             scale = 0.5f / scale;
00452             result.w = (m[k][j] - m[j][k]) * scale;
00453             result.array[j] = (m[j][i] + m[i][j]) * scale;
00454             result.array[k] = (m[k][i] + m[i][k]) * scale;
00455         }
00456         return result;
00457     }
00458 
00459     //--------------------------------------------------------------------------
00460     // 三軸指定回転
00461     //--------------------------------------------------------------------------
00462     /**
00463      * XYZ軸回転の設定
00464      * @param radian 各軸におけるラジアン単位での回転角度
00465      */
00466     inline void setRotationXYZ(const Vector3& radian){
00467         float sinX = Math::sin(radian.x);
00468         float cosX = Math::cos(radian.x);
00469         float sinY = Math::sin(radian.y);
00470         float cosY = Math::cos(radian.y);
00471         float sinZ = Math::sin(radian.z);
00472         float cosZ = Math::cos(radian.z);
00473         m00 = cosY * cosZ;
00474         m01 = sinX * sinY * cosZ - cosX * sinZ;
00475         m02 = cosX * sinY * cosZ + sinX * sinZ;
00476 
00477         m10 = cosY * sinZ;
00478         m11 = sinX * sinY * sinZ + cosX * cosZ;
00479         m12 = cosX * sinY * sinZ - sinX * cosZ;
00480 
00481         m20 = -sinY;
00482         m21 = sinX * cosY;
00483         m22 = cosX * cosY;
00484     }
00485 
00486     /**
00487      * XYZ軸回転の追加
00488      * @param radian 各軸におけるラジアン単位での回転角度
00489      */
00490     inline void addRotationXYZ(const Vector3& radian){
00491         Matrix33 matrix;
00492         matrix.setRotationXYZ(radian);
00493         (*this) = matrix * (*this); 
00494     }
00495 
00496     /**
00497      * XYZ軸回転の取得
00498      * @param radian [out] 各軸におけるラジアン単位での回転角度
00499      * @return 答えが単一であればtrue
00500      */
00501     inline bool getRotationXYZ(Vector3* radian) const{
00502         float yRadian = Math::asin(-m20);
00503         radian->y = yRadian;
00504         if(yRadian < Math::halfPI){
00505             if(yRadian > -Math::halfPI){
00506                 radian->x = Math::atan2(m21, m22);
00507                 radian->z = Math::atan2(m10, m00);
00508                 return true;
00509             }else{
00510                 radian->x = -Math::atan2(m01, m11);
00511                 radian->z = 0.f;
00512                 return false;
00513             }
00514         }else{
00515             radian->x = Math::atan2(m01, m11);
00516             radian->z = 0.f;
00517             return false;
00518         }
00519     }
00520 
00521     //--------------------------------------------------------------------------
00522     /**
00523      * XZY軸回転の設定
00524      * @param radian 各軸におけるラジアン単位での回転角度
00525      */
00526     // 展開すれば高速化できる
00527     inline void setRotationXZY(const Vector3& radian){
00528         setRotationX(radian.x);
00529         addRotationZ(radian.z);
00530         addRotationY(radian.y);
00531     }
00532 
00533     /**
00534      * XZY軸回転の追加
00535      * @param radian 各軸におけるラジアン単位での回転角度
00536      */
00537     inline void addRotationXZY(const Vector3& radian){
00538         Matrix33 matrix;
00539         matrix.setRotationXZY(radian);
00540         (*this) = matrix * (*this); 
00541     }
00542 
00543     /**
00544      * XZY軸回転の取得
00545      * @param radian [out] 各軸におけるラジアン単位での回転角度
00546      * @return 答えが単一であればtrue
00547      */
00548     inline bool getRotationXZY(Vector3* radian) const{
00549         float zRadian = Math::asin(m10);
00550         radian->z = zRadian;
00551         if(zRadian < Math::halfPI){
00552             if(zRadian > -Math::halfPI){
00553                 radian->x = Math::atan2(-m12, m11);
00554                 radian->y = Math::atan2(-m20, m00);
00555                 return true;
00556             }else{
00557                 radian->x = -Math::atan2(m02, m22);
00558                 radian->y = 0.f;
00559                 return false;
00560             }
00561         }else{
00562             radian->x = Math::atan2(m02, m22);
00563             radian->y = 0.f;
00564             return false;
00565         }
00566     }
00567 
00568     //--------------------------------------------------------------------------
00569     /**
00570      * YXZ軸回転の設定
00571      * @param radian 各軸におけるラジアン単位での回転角度
00572      */
00573     // 展開すれば高速化できる
00574     inline void setRotationYXZ(const Vector3& radian){
00575         setRotationY(radian.y);
00576         addRotationX(radian.x);
00577         addRotationZ(radian.z);
00578     }
00579 
00580     /**
00581      * YXZ軸回転の追加
00582      * @param radian 各軸におけるラジアン単位での回転角度
00583      */
00584     inline void addRotationYXZ(const Vector3& radian){
00585         Matrix33 matrix;
00586         matrix.setRotationYXZ(radian);
00587         (*this) = matrix * (*this); 
00588     }
00589 
00590     /**
00591      * YXZ軸回転の取得
00592      * @param radian [out] 各軸におけるラジアン単位での回転角度
00593      * @return 答えが単一であればtrue
00594      */
00595     inline bool getRotationYXZ(Vector3* radian) const{
00596         float xRadian = Math::asin(m21);
00597         radian->x = xRadian;
00598         if(xRadian < Math::halfPI){
00599             if(xRadian > -Math::halfPI){
00600                 radian->y = Math::atan2(-m20, m22);
00601                 radian->z = Math::atan2(-m01, m11);
00602                 return true;
00603             }else{
00604                 radian->y = -Math::atan2(-m10, m00);
00605                 radian->z = 0.f;
00606                 return false;
00607             }
00608         }else{
00609             radian->y = Math::atan2(-m10, m00);
00610             radian->z = 0.f;
00611             return false;
00612         }
00613     }
00614 
00615     //--------------------------------------------------------------------------
00616     /**
00617      * YZX軸回転の設定
00618      * @param radian 各軸におけるラジアン単位での回転角度
00619      */
00620     // 展開すれば高速化できる
00621     inline void setRotationYZX(const Vector3& radian){
00622         setRotationY(radian.y);
00623         addRotationZ(radian.z);
00624         addRotationX(radian.x);
00625     }
00626 
00627     /**
00628      * YZX軸回転の追加
00629      * @param radian 各軸におけるラジアン単位での回転角度
00630      */
00631     inline void addRotationYZX(const Vector3& radian){
00632         Matrix33 matrix;
00633         matrix.setRotationYZX(radian);
00634         (*this) = matrix * (*this); 
00635     }
00636 
00637     /**
00638      * YZX軸回転の取得
00639      * @param radian [out] 各軸におけるラジアン単位での回転角度
00640      * @return 答えが単一であればtrue
00641      */
00642     inline bool getRotationYZX(Vector3* radian) const{
00643         float zRadian = Math::asin(-m01);
00644         radian->z = zRadian;
00645         if(zRadian < Math::halfPI){
00646             if(zRadian > -Math::halfPI){
00647                 radian->y = Math::atan2(m02, m00);
00648                 radian->x = Math::atan2(m21, m11);
00649                 return true;
00650             }else{
00651                 radian->y = -Math::atan2(m12, m22);
00652                 radian->x = 0.f;
00653                 return false;
00654             }
00655         }else{
00656             radian->y = Math::atan2(m12, m22);
00657             radian->x = 0.f;
00658             return false;
00659         }
00660     }
00661 
00662     //--------------------------------------------------------------------------
00663     /**
00664      * ZXY軸回転の設定
00665      * @param radian 各軸におけるラジアン単位での回転角度
00666      */
00667     // 展開すれば高速化できる
00668     inline void setRotationZXY(const Vector3& radian){
00669         setRotationZ(radian.z);
00670         addRotationX(radian.x);
00671         addRotationY(radian.y);
00672     }
00673 
00674     /**
00675      * ZXY軸回転の追加
00676      * @param radian 各軸におけるラジアン単位での回転角度
00677      */
00678     inline void addRotationZXY(const Vector3& radian){
00679         Matrix33 matrix;
00680         matrix.setRotationZXY(radian);
00681         (*this) = matrix * (*this); 
00682     }
00683 
00684     /**
00685      * ZXY軸回転の取得
00686      * @param radian [out] 各軸におけるラジアン単位での回転角度
00687      * @return 答えが単一であればtrue
00688      */
00689     inline bool getRotationZXY(Vector3* radian) const{
00690         float xRadian = Math::asin(-m12);
00691         radian->x = xRadian;
00692         if(xRadian < Math::halfPI){
00693             if(xRadian > -Math::halfPI){
00694                 radian->z = Math::atan2(m10, m11);
00695                 radian->y = Math::atan2(m02, m22);
00696                 return true;
00697             }else{
00698                 radian->z = -Math::atan2(m20, m00);
00699                 radian->y = 0.f;
00700                 return false;
00701             }
00702         }else{
00703             radian->z = Math::atan2(m20, m00);
00704             radian->y = 0.f;
00705             return false;
00706         }
00707     }
00708 
00709     //--------------------------------------------------------------------------
00710     /**
00711      * ZYX軸回転の設定
00712      * @param radian 各軸におけるラジアン単位での回転角度
00713      */
00714     // 展開すれば高速化できる
00715     inline void setRotationZYX(const Vector3& radian){
00716         setRotationZ(radian.z);
00717         addRotationY(radian.y);
00718         addRotationX(radian.x);
00719     }
00720 
00721     /**
00722      * ZYX軸回転の追加
00723      * @param radian 各軸におけるラジアン単位での回転角度
00724      */
00725     inline void addRotationZYX(const Vector3& radian){
00726         Matrix33 matrix;
00727         matrix.setRotationZYX(radian);
00728         (*this) = matrix * (*this); 
00729     }
00730 
00731     /**
00732      * ZYX軸回転の取得
00733      * @param radian [out] 各軸におけるラジアン単位での回転角度
00734      * @return 答えが単一であればtrue
00735      */
00736     inline bool getRotationZYX(Vector3* radian) const{
00737         float yRadian = Math::asin(m02);
00738         radian->y = yRadian;
00739         if(yRadian < Math::halfPI){
00740             if(yRadian > -Math::halfPI){
00741                 radian->z = Math::atan2(-m01, m00);
00742                 radian->x = Math::atan2(-m12, m22);
00743                 return true;
00744             }else{
00745                 radian->z = -Math::atan2(-m10, m20);
00746                 radian->x = 0.f;
00747                 return false;
00748             }
00749         }else{
00750             radian->z = Math::atan2(m10, -m20);
00751             radian->x = 0.f;
00752             return false;
00753         }
00754     }
00755 
00756     //--------------------------------------------------------------------------
00757     // 乗算
00758     //--------------------------------------------------------------------------
00759     /**
00760      * 行列乗算
00761      *
00762      * 左側の行列から順に計算が適用されます。
00763      * @param mtx 乗算する行列
00764      * @return 乗算された行列
00765      */
00766     inline Matrix33 operator *(const Matrix33& mtx) const{
00767         return Matrix33(
00768             (m00 * mtx.m00) + (m01 * mtx.m10) + (m02 * mtx.m20),
00769             (m00 * mtx.m01) + (m01 * mtx.m11) + (m02 * mtx.m21),
00770             (m00 * mtx.m02) + (m01 * mtx.m12) + (m02 * mtx.m22),
00771             (m10 * mtx.m00) + (m11 * mtx.m10) + (m12 * mtx.m20),
00772             (m10 * mtx.m01) + (m11 * mtx.m11) + (m12 * mtx.m21),
00773             (m10 * mtx.m02) + (m11 * mtx.m12) + (m12 * mtx.m22),
00774             (m20 * mtx.m00) + (m21 * mtx.m10) + (m22 * mtx.m20),
00775             (m20 * mtx.m01) + (m21 * mtx.m11) + (m22 * mtx.m21),
00776             (m20 * mtx.m02) + (m21 * mtx.m12) + (m22 * mtx.m22));
00777     }
00778 
00779     /**
00780      * 代入行列乗算
00781      *
00782      * 左側の行列から順に計算が適用されます。
00783      * @param mtx 乗算する行列
00784      * @return 乗算された行列
00785      */
00786     inline Matrix33& operator *=(Matrix33 mtx){
00787         float old00 = m00;
00788         float old01 = m01;
00789         m00 = (old00 * mtx.m00) + (old01 * mtx.m10) + (m02 * mtx.m20);
00790         m01 = (old00 * mtx.m01) + (old01 * mtx.m11) + (m02 * mtx.m21);
00791         m02 = (old00 * mtx.m02) + (old01 * mtx.m12) + (m02 * mtx.m22);
00792         float old10 = m10;
00793         float old11 = m11;
00794         m10 = (old10 * mtx.m00) + (old11 * mtx.m10) + (m12 * mtx.m20);
00795         m11 = (old10 * mtx.m01) + (old11 * mtx.m11) + (m12 * mtx.m21);
00796         m12 = (old10 * mtx.m02) + (old11 * mtx.m12) + (m12 * mtx.m22);
00797         float old20 = m20;
00798         float old21 = m21;
00799         m20 = (old20 * mtx.m00) + (old21 * mtx.m10) + (m22 * mtx.m20);
00800         m21 = (old20 * mtx.m01) + (old21 * mtx.m11) + (m22 * mtx.m21);
00801         m22 = (old20 * mtx.m02) + (old21 * mtx.m12) + (m22 * mtx.m22);
00802         return *this;
00803     }
00804 
00805     /**
00806      * ベクトル乗算
00807      * @param vector 乗算するベクトル
00808      * @return 乗算されたベクトル
00809      */
00810     inline Vector3 operator *(const Vector3& vector) const{
00811         return Vector3(
00812             vector.x * m00 + vector.y * m01 + vector.z * m02,
00813             vector.x * m10 + vector.y * m11 + vector.z * m12,
00814             vector.x * m20 + vector.y * m21 + vector.z * m22);
00815     }
00816 
00817     /**
00818      * スカラー乗算
00819      * @param value 乗算するスカラー
00820      * @return 乗算された行列
00821      */
00822     inline Matrix33 operator *(float value) const{
00823         return Matrix33(
00824             m00 * value, m01 * value, m02 * value,
00825             m10 * value, m11 * value, m12 * value,
00826             m20 * value, m21 * value, m22 * value);
00827     }
00828 
00829     /**
00830      * スカラー乗算
00831      * @param value 乗算するスカラー
00832      * @return 乗算された行列
00833      */
00834     inline Matrix33& operator *=(float value){
00835         m00 *= value;
00836         m01 *= value;
00837         m02 *= value;
00838         m10 *= value;
00839         m11 *= value;
00840         m12 *= value;
00841         m20 *= value;
00842         m21 *= value;
00843         m22 *= value;
00844         return *this;
00845     }
00846 
00847     //--------------------------------------------------------------------------
00848     // 行列演算
00849     //--------------------------------------------------------------------------
00850     /**
00851      * 転置
00852      *
00853      * m30、m31、m32は0クリアされます。
00854      */
00855     inline void transpose(){
00856         float swap;
00857         swap = m01; m01 = m10; m10 = swap;
00858         swap = m02; m02 = m20; m20 = swap;
00859         swap = m12; m12 = m21; m21 = swap;
00860     }
00861 
00862     /**
00863      * 行列式
00864      * @return 行列式
00865      */
00866     inline float determinant() const{
00867         return
00868             m00 * (m11 * m22 - m12 * m21) -
00869             m01 * (m10 * m22 - m12 * m20) +
00870             m02 * (m10 * m21 - m11 * m20);
00871     }
00872 
00873     /**
00874      * 逆行列
00875      * @return 行列式
00876      */
00877     inline float invert(){
00878         Matrix33 invertMatrix;
00879         // 行列式を出す
00880         invertMatrix.m00 = m11 * m22 - m12 * m21;
00881         invertMatrix.m10 = -(m10 * m22 - m12 * m20);
00882         invertMatrix.m20 = m10 * m21 - m11 * m20;
00883         float determ =
00884             m00 * invertMatrix.m00 +
00885             m01 * invertMatrix.m10 +
00886             m02 * invertMatrix.m20;
00887         Assert(determ > Math::epsilon);
00888         // 各要素の算出
00889         invertMatrix.m01 = -(m01 * m22 - m02 * m21);
00890         invertMatrix.m02 = m01 * m12 - m02 * m11;
00891         invertMatrix.m11 = m00 * m22 - m02 * m20;
00892         invertMatrix.m12 = -(m00 * m12 - m02 * m10);
00893         invertMatrix.m21 = -(m00 * m21 - m01 * m20);
00894         invertMatrix.m22 = m00 * m11 - m01 * m10;
00895         // 行列式の逆数を掛ける
00896         float invDeterm = 1.f / determ;
00897         invertMatrix *= invDeterm;
00898         (*this) = invertMatrix;
00899         return determ;
00900     }
00901 
00902     /**
00903      * 逆行列
00904      * @param invertMatrix [out] 逆行列を格納する行列へのポインタ
00905      * @return 行列式
00906      */
00907     inline float invert(Matrix33* invertMatrix) const{
00908         Assert(invertMatrix != NULL);
00909         Assert(invertMatrix != this);
00910         // 行列式を出す
00911         invertMatrix->m00 = m11 * m22 - m12 * m21;
00912         invertMatrix->m10 = -(m10 * m22 - m12 * m20);
00913         invertMatrix->m20 = m10 * m21 - m11 * m20;
00914         float determ =
00915             m00 * invertMatrix->m00 +
00916             m01 * invertMatrix->m10 +
00917             m02 * invertMatrix->m20;
00918         Assert(determ > Math::epsilon);
00919         // 各要素の算出
00920         invertMatrix->m01 = -(m01 * m22 - m02 * m21);
00921         invertMatrix->m02 = m01 * m12 - m02 * m11;
00922         invertMatrix->m11 = m00 * m22 - m02 * m20;
00923         invertMatrix->m12 = -(m00 * m12 - m02 * m10);
00924         invertMatrix->m21 = -(m00 * m21 - m01 * m20);
00925         invertMatrix->m22 = m00 * m11 - m01 * m10;
00926         // 行列式の逆数を掛ける
00927         float invDeterm = 1.f / determ;
00928         (*invertMatrix) *= invDeterm;
00929         return determ;
00930     }
00931 
00932     //--------------------------------------------------------------------------
00933     // 論理演算
00934     //--------------------------------------------------------------------------
00935     /**
00936      * 行列が同じかどうか
00937      * @param target 比較する行列
00938      * @return 同じ値であればtrueを返す
00939      */
00940     inline bool operator ==(const Matrix33& target) const{
00941         return (
00942             (m00 == target.m00) && (m01 == target.m01) && (m02 == target.m02) &&
00943             (m10 == target.m10) && (m11 == target.m11) && (m12 == target.m12) &&
00944             (m20 == target.m20) && (m21 == target.m21) && (m22 == target.m22));
00945     }
00946 
00947     /**
00948      * 行列が同じかどうか
00949      * @param target 比較する行列
00950      * @param epsilon 誤差
00951      * @return 誤差の範囲内で同じ値であればtrueを返す
00952      */
00953     inline bool epsilonEquals(const Matrix33& target, float epsilon) const{
00954         Assert(epsilon >= 0.f);
00955         return (
00956             (Math::abs(m00 - target.m00) <= epsilon) &&
00957             (Math::abs(m01 - target.m01) <= epsilon) &&
00958             (Math::abs(m02 - target.m02) <= epsilon) &&
00959             (Math::abs(m10 - target.m10) <= epsilon) &&
00960             (Math::abs(m11 - target.m11) <= epsilon) &&
00961             (Math::abs(m12 - target.m12) <= epsilon) &&
00962             (Math::abs(m20 - target.m20) <= epsilon) &&
00963             (Math::abs(m21 - target.m21) <= epsilon) &&
00964             (Math::abs(m22 - target.m22) <= epsilon));
00965     }
00966 
00967     /**
00968      * 行列が同じでないかどうか
00969      * @param target 比較する行列
00970      * @return 同じでない値であればtrueを返す
00971      */
00972     inline bool operator !=(const Matrix33& target) const{
00973         return (
00974             (m00 != target.m00) || (m01 != target.m01) || (m02 != target.m02) ||
00975             (m10 != target.m10) || (m11 != target.m11) || (m12 != target.m12) ||
00976             (m20 != target.m20) || (m21 != target.m21) || (m22 != target.m22));
00977     }
00978 
00979     /**
00980      * 行列が同じでないかどうか
00981      * @param target 比較する行列
00982      * @param epsilon 誤差
00983      * @return 誤差の範囲内で同じでない値であればtrueを返す
00984      */
00985     inline bool notEpsilonEquals(const Matrix33& target, float epsilon) const{
00986         Assert(epsilon >= 0.f);
00987         return (
00988             (Math::abs(m00 - target.m00) > epsilon) ||
00989             (Math::abs(m01 - target.m01) > epsilon) ||
00990             (Math::abs(m02 - target.m02) > epsilon) ||
00991             (Math::abs(m10 - target.m10) > epsilon) ||
00992             (Math::abs(m11 - target.m11) > epsilon) ||
00993             (Math::abs(m12 - target.m12) > epsilon) ||
00994             (Math::abs(m20 - target.m20) > epsilon) ||
00995             (Math::abs(m21 - target.m21) > epsilon) ||
00996             (Math::abs(m22 - target.m22) > epsilon));
00997     }
00998 
00999     //--------------------------------------------------------------------------
01000     // その他
01001     //--------------------------------------------------------------------------
01002     /**
01003      * 文字列化
01004      * @return 行列の文字列表記
01005      */
01006     inline String toString() const{
01007         String returnString;
01008         returnString.format(
01009             "{\n  ( %.8f, %.8f, %.8f )\n  ( %.8f, %.8f, %.8f )\n"
01010             "  ( %.8f, %.8f, %.8f )\n}",
01011             m00, m01, m02, m10, m11, m12, m20, m21, m22);
01012         return returnString;
01013     }
01014 
01015     //--------------------------------------------------------------------------
01016 private:
01017 
01018 };
01019 
01020 //------------------------------------------------------------------------------
01021 } // End of namespace Lamp
01022 #endif // End of MATRIX33_H_
01023 //------------------------------------------------------------------------------

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