3D数学基础:Matrix4*3类代码清单
生活随笔
收集整理的這篇文章主要介紹了
3D数学基础:Matrix4*3类代码清单
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Matrix4×3矩陣和RotationMatrix矩陣是《3D數學基礎》中的兩大矩陣。相比于只能運用于旋轉功能的RotationMatrix矩陣,Matrix 4×3矩陣更加一般化,能夠支持更加復雜的變換。以下給出代碼清單。
程序清單:Matrix4×3.h
///////////////////////////////////////////////////////////////////////////// // // 3D數學基礎:游戲與圖形開發 // 3D Math Primer for Games and Graphics Development // // Matrix4x3.h - Matrix4x3類聲明 // Matrix4x3.h - Declarations for class Matrix4x3 //// 更多細節,請看Matrix4x3.cpp // For more details, see Matrix4x3.cpp // /////////////////////////////////////////////////////////////////////////////#ifndef __MATRIX4X3_H_INCLUDED__ #define __MATRIX4X3_H_INCLUDED__class Vector3; class EulerAngles; class Quaternion; class RotationMatrix; //--------------------------------------------------------------------------- // Matrix4x3類 // class Matrix4x3 // // 實現4x3轉化矩陣。這個類可以表現任何仿射變化。 // Implement a 4x3 transformation matrix. This class can represent // any 3D affine transformation.class Matrix4x3 { public:// 公有數據 // Public data// 這個矩陣的值。上面3x3部分基本上包括了所有線性變換,最后一行是平移部分。// 查看Matrix4x3.cpp來獲得更多細節。// The values of the matrix. Basically the upper 3x3 portion// contains a linear transformation, and the last row is the// translation portion. See the Matrix4x3.cpp for more// details.float m11, m12, m13;float m21, m22, m23;float m31, m32, m33;float tx, ty, tz;// 公有操作 // Public operations// 設為單位矩陣// Set to identityvoid identity();// 直接使用矩陣平移部分// Access the translation portion of the matrix directlyvoid zeroTranslation();void setTranslation(const Vector3 &d);void setupTranslation(const Vector3 &d);// 構造矩陣來表現一個從父空間到局部空間或相反方向的特定的轉換,// 假定本地空間是父空間的具體指定位置和朝向。// 這個朝向可能是被歐拉角或者旋轉矩陣來指定的。// Setup the matrix to perform a specific transforms from parent <->// local space, assuming the local space is in the specified position// and orientation within the parent space. The orientation may be// specified using either Euler angles, or a rotation matrixvoid setupLocalToParent(const Vector3 &pos, const EulerAngles &orient);void setupLocalToParent(const Vector3 &pos, const RotationMatrix &orient);void setupParentToLocal(const Vector3 &pos, const EulerAngles &orient);void setupParentToLocal(const Vector3 &pos, const RotationMatrix &orient);// 構建矩陣執行關于主要軸的旋轉// Setup the matrix to perform a rotation about a cardinal axisvoid setupRotate(int axis, float theta);// 構建關于任意軸的旋轉矩陣。// Setup the matrix to perform a rotation about an arbitrary axisvoid setupRotate(const Vector3 &axis, float theta);// 構建矩陣來執行旋轉,給定一個四元數形式的角位移。// Setup the matrix to perform a rotation, given// the angular displacement in quaternion formvoid fromQuaternion(const Quaternion &q);// 構建矩陣來執行每根軸上的縮放。使用向量形式的Vector3(k,k,k)來統一縮放k倍。// Setup the matrix to perform scale on each axisvoid setupScale(const Vector3 &s);// 構建矩陣來執行沿著任意軸的縮放。// Setup the matrix to perform scale along an arbitrary axisvoid setupScaleAlongAxis(const Vector3 &axis, float k);// 構建矩陣來執行切變// Setup the matrix to perform a shearvoid setupShear(int axis, float s, float t);// 構建矩陣來執行投影到一個通過原點的平面。// Setup the matrix to perform a projection onto a plane passing// through the originvoid setupProject(const Vector3 &n);// 構建矩陣關于一個平行于基本平面的反射。// Setup the matrix to perform a reflection about a plane parallel// to a cardinal planevoid setupReflect(int axis, float k = 0.0f);// 設置矩陣執行關于任意通過原點的平面的反射。// Setup the matrix to perform a reflection about an arbitrary plane// through the originvoid setupReflect(const Vector3 &n); };// 操作*用來變換點,也用來連接矩陣。 // 從左到右相乘的順序和變換的順序是一樣的。 // Operator* is used to transforms a point, and also concatonate matrices. // The order of multiplications from left to right is the same as // the order of transformationsVector3 operator*(const Vector3 &p, const Matrix4x3 &m); Matrix4x3 operator*(const Matrix4x3 &a, const Matrix4x3 &b);// 操作*=使得和C++標準一致 // Operator *= for conformance to C++ standardsVector3 &operator*=(Vector3 &p, const Matrix4x3 &m); Matrix4x3 &operator*=(const Matrix4x3 &a, const Matrix4x3 &m);// 計算3x3矩陣部分的行列式 // Compute the determinant of the 3x3 portion of the matrixfloat determinant(const Matrix4x3 &m);// 計算矩陣的逆 // Compute the inverse of a matrixMatrix4x3 inverse(const Matrix4x3 &m);// 從矩陣中提取平移部分 // Extract the translation portion of the matrixVector3 getTranslation(const Matrix4x3 &m);// 從局部坐標系->父坐標系或父坐標系->局部坐標系提取位置/方位 // Extract the position/orientation from a local->parent matrix, // or a parent->local matrixVector3 getPositionFromParentToLocalMatrix(const Matrix4x3 &m); Vector3 getPositionFromLocalToParentMatrix(const Matrix4x3 &m);///////////////////////////////////////////////////////////////////////////// #endif // #ifndef __ROTATIONMATRIX_H_INCLUDED__程序清單:Matrix4×3.cpp
///////////////////////////////////////////////////////////////////////////// // // 《3D數學基礎:游戲與圖形開發》 // 3D Math Primer for Games and Graphics Development // // Matrix4x3.cpp - Matrix4x3實現 // Matrix4x3.cpp - Implementation of class Matrix4x3 //// 更多細節請看11.5節 // For more details see section 11.5. // /////////////////////////////////////////////////////////////////////////////#include <assert.h> #include <math.h>#include "Vector3.h" #include "EulerAngles.h" #include "Quaternion.h" #include "RotationMatrix.h" #include "Matrix4x3.h" #include "MathUtil.h"///////////////////////////////////////////////////////////////////////////// // // 注意: // Notes: // // 請看11章獲得類設計決策的更多信息。 // See Chapter 11 for more information on class design decisions. // //--------------------------------------------------------------------------- // // 矩陣組織 // MATRIX ORGANIZATION // // 這個類的目的是為了用戶可能執行轉換操作,而不用擺弄加號、減號或者轉置矩陣直到輸出“看起來是正確的”。 // 不過當然,這個內部表述的詳細情況是很重要的。不單是為了這個文件的實現是正確的, // 而且偶爾直接進入矩陣變量也是必須的,或者有益于優化。因此,這里我們記錄我們的矩陣約定。 // The purpose of this class is so that a user might perform transformations // without fiddling with plus or minus signs or transposing the matrix // until the output "looks right." But of course, the specifics of the // internal representation is important. Not only for the implementation // in this file to be correct, but occasionally direct access to the // matrix variables is necessary, or beneficial for optimization. Thus, // we document our matrix conventions here. // // 我們使用行向量,所以跟矩陣相乘看起來是這樣的: // We use row vectors, so multiplying by our matrix looks like this: // // | m11 m12 m13 | // [ x y z ] | m21 m22 m23 | = [ x' y' z' ] // | m31 m32 m33 | // | tx ty tz | // // 嚴格執行線性代數規則規定了這個乘法實際是未定義的。 // 為了繞過這個問題,我們可以假定輸入和輸出向量有第四個坐標為1。 // 同樣,我們不可以根據線性代數規則以學術形式地反轉4x3矩陣,我們也會假設 // 最右列是[ 0 0 0 1 ]。它看起來像如下這樣的: // Strict adherance to linear algebra rules dictates that this // multiplication is actually undefined. To circumvent this, we can // consider the input and output vectors as having an assumed fourth // coordinate of 1. Also, since we cannot technically invert a 4x3 matrix // according to linear algebra rules, we will also assume a rightmost // column of [ 0 0 0 1 ]. This is shown below: // // | m11 m12 m13 0 | // [ x y z 1 ] | m21 m22 m23 0 | = [ x' y' z' 1 ] // | m31 m32 m33 0 | // | tx ty tz 1 | // // 萬一你忘了矩陣乘法的線性代數規則(在第7.1.6和7.1.7節中描述過),查看操作*的擴展計算定義。 // In case you have forgotten your linear algebra rules for multiplying // matrices (which are described in section 7.1.6 and 7.1.7), see the // definition of operator* for the expanded computations. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Matrix4x3類成員 // Matrix4x3 class members // ///////////////////////////////////////////////////////////////////////////////--------------------------------------------------------------------------- // Matrix4x3::identity // // 設置矩陣為單位矩陣 // Set the matrix to identityvoid Matrix4x3::identity() {m11 = 1.0f; m12 = 0.0f; m13 = 0.0f;m21 = 0.0f; m22 = 1.0f; m23 = 0.0f;m31 = 0.0f; m32 = 0.0f; m33 = 1.0f;tx = 0.0f; ty = 0.0f; tz = 1.0f; }//--------------------------------------------------------------------------- // Matrix4x3::zeroTranslation // // 將矩陣的第四行都置為0,該行包含了平移部分 // Zero the 4th row of the matrix, which contains the translation portion.void Matrix4x3::zeroTranslation() {tx = ty = tz = 0.0f; }//--------------------------------------------------------------------------- // Matrix4x3::setTranslation // // 用向量形式設置矩陣的平移部分 // Sets the translation portion of the matrix in vector formvoid Matrix4x3::setTranslation(const Vector3 &d) {tx = d.x; ty = d.y; tz = d.z; }//--------------------------------------------------------------------------- // Matrix4x3::setupTranslation // // 用向量形式設置矩陣的平移部分,并設置線性變換部分為單位矩陣 // Sets the translation portion of the matrix in vector formvoid Matrix4x3::setupTranslation(const Vector3 &d) {// 設置線性變換部分為單位矩陣// Set the linear transformation portion to identitym11 = 1.0f; m12 = 0.0f; m13 = 0.0f;m21 = 0.0f; m22 = 1.0f; m23 = 0.0f;m31 = 0.0f; m32 = 0.0f; m33 = 1.0f;// 設置平移部分// Set the translation portiontx = d.x; ty = d.y; tz = d.z; }//--------------------------------------------------------------------------- // Matrix4x3::setupLocalToParent // // 給定一個父參考幀中的局部參考幀的位置和朝向,構造矩陣來執行從局部空間->父空間的轉換。 // Setup the matrix to perform a local -> parent transformation, given // the position and orientation of the local reference frame within the // parent reference frame. // // 一個非常常見的用法是構造從物體->世界矩陣。 // 作為一個示例,這種情況的轉換是很直接的。 // 我們首先從物體坐標系到慣性坐標系的轉換,然后平移到世界空間。 // A very common use of this will be to construct a object -> world matrix. // As an example, the transformation in this case is straightforward. We // first rotate from object space into inertial space, then we translate // into world space. // // 我們允許通過歐拉角或者旋轉矩陣來指定方位。 // We allow the orientation to be specified using either euler angles, // or a RotationMatrixvoid Matrix4x3::setupLocalToParent(const Vector3 &pos, const EulerAngles &orient) {// 創建旋轉矩陣// Create a rotation matrix.RotationMatrix orientMatrix;orientMatrix.setup(orient);// 構造4x3矩陣。注意:如果我們真的關心速度,我們可以直接創建這個矩陣到各個變量,// 而不用使用臨時的旋轉矩陣。這會節約函數調用和一些的拷貝操作開銷。// Setup the 4x3 matrix. Note: if we were really concerned with// speed, we could create the matrix directly into these variables,// without using the temporary RotationMatrix object. This would// save us a function call and a few copy operations.setupLocalToParent(pos, orientMatrix); }void Matrix4x3::setupLocalToParent(const Vector3 &pos, const RotationMatrix &orient) {// 復制矩陣的旋轉部分。根據RotationMatrix.cpp的注釋,這個旋轉矩陣通常是慣性坐標系->物體坐標系的矩陣,// 也就是從父空間->局部空間。我們想要局部空間->父空間旋轉,復制的時候必須要轉置。// Copy the rotation portion of the matrix. According to// the comments in RotationMatrix.cpp, the rotation matrix// is "normally" an inertial->object matrix, which is// parent->local. We want a local->parent rotation, so we// must transpose while copyingm11 = orient.m11; m12 = orient.m21; m13 = orient.m31;m21 = orient.m12; m22 = orient.m22; m23 = orient.m32;m31 = orient.m13; m32 = orient.m23; m33 = orient.m33;// 現在設置平移部分。平移發生在3x3部分之后,所以我們可以簡單直接地復制位置。// Now set the translation portion. Translation happens "after"// the 3x3 portion, so we can simply copy the position// field directlytx = pos.x; ty = pos.y; tz = pos.z; }//--------------------------------------------------------------------------- // Matrix4x3::setupParentToLocal // // 給定在父空間參考幀下的局部坐標的位置和方向參考幀,構造矩陣來執行父空間->局部空間。 // Setup the matrix to perform a parent -> local transformation, given // the position and orientation of the local reference frame within the // parent reference frame. // // 它的一個非常常見的用法就是從世界坐標系->物體坐標系。 // 為了執行這個轉換,我們通常首先會從世界坐標系到慣性坐標系的轉換,然后從慣性坐標系到物體坐標系的旋轉。 // 然而4x3矩陣可以完成后一個轉換。所以我們可以創建兩個矩陣T和R,然后連接M = TR。 // A very common use of this will be to construct a world -> object matrix. // To perform this transformation, we would normally FIRST transform // from world to inertial space, and then rotate from inertial space into // object space. However, out 4x3 matrix always translates last. So // we think about creating two matrices T and R, and then concatonating // M = TR. // // 我們允許使用歐拉角或者旋轉矩陣來指定朝向。 // We allow the orientation to be specified using either euler angles, // or a RotationMatrixvoid Matrix4x3::setupParentToLocal(const Vector3 &pos, const EulerAngles &orient) {// 創建一個旋轉矩陣。// Create a rotation matrix.RotationMatrix orientMatrix;orientMatrix.setup(orient);// 構造4x3矩陣。// Setup the 4x3 matrix.setupParentToLocal(pos, orientMatrix); }void Matrix4x3::setupParentToLocal(const Vector3 &pos, const RotationMatrix &orient) {// 復制矩陣的旋轉部分。我們根據RotationMatrix.cpp注釋中的布局,可以直接復制元素(不用轉置)// Copy the rotation portion of the matrix. We can copy the// elements directly (without transposing) according// to the layout as commented in RotationMatrix.cppm11 = orient.m11; m12 = orient.m12; m13 = orient.m13;m21 = orient.m21; m22 = orient.m22; m23 = orient.m23;m31 = orient.m31; m32 = orient.m32; m33 = orient.m33;// 現在設置平移部分。通常地,我們通過取位置的負號來實現從世界到慣性坐標系。// 然而,我們必須修正這個事實——旋轉是先發生的。所以必須先旋轉平移部分。// 這和創建一個平移矩陣T來平移-pos,和旋轉矩陣R,并且創建一個連接矩陣TR是一樣的。// Now set the translation portion. Normally, we would// translate by the negative of the position to translate// from world to inertial space. However, we must correct// for the fact that the rotation occurs "first." So we// must rotate the translation portion. This is the same// as create a translation matrix T to translate by -pos,// and a rotation matrix R, and then creating the matrix// as the concatenation of TRtx = -(pos.x*m11 + pos.y*m21 + pos.z*m31);ty = -(pos.x*m12 + pos.y*m22 + pos.z*m32);tz = -(pos.x*m13 + pos.y*m23 + pos.z*m33); }//--------------------------------------------------------------------------- // Matrix4x3::setupRotate // // 構建矩陣執行關于主要軸的旋轉 // Setup the matrix to perform a rotation about a cardinal axis // // 使用基于1的索引指定旋轉軸 // The axis of rotation is specified using a 1-based index: // // 1 => 關于x軸旋轉 // 2 => 關于y軸旋轉 // 3 => 關于z軸旋轉 // 1 => rotate about the x-axis // 2 => rotate about the y-axis // 3 => rotate about the z-axis // // theta是以弧度計的旋轉量。使用左手法則定義正方向的旋轉。 // theta is the amount of rotation, in radians. The left-hand rule is // used to define "positive" rotation. // // 平移部分被重設。 // The translation portion is reset. // // 參見8.2.2獲得更多信息。 // See 8.2.2 for more info.void Matrix4x3::setupRotate(int axis, float theta) {// 獲得旋轉角的sin和cos值// Get sin and cosine of rotation anglefloat s, c;sinCos(&s, &c, theta);// 檢查關于哪根軸旋轉// Check which axis they are rotating aboutswitch (axis) {// 關于x軸旋轉case 1: // Rotate about the x-axism11 = 1.0f; m12 = 0.0f; m13 = 0.0f;m21 = 0.0f; m22 = c; m23 = s;m31 = 0.0f; m32 = -s; m33 = c;break;// 關于y軸旋轉case 2: // Rotate about the y-axism11 = c; m12 = 0.0f; m13 = -s;m21 = 0.0f; m22 = 1.0f; m23 = 0.0f;m31 = s; m32 = 0.0f; m33 = c;break;// 關于z軸旋轉case 3: // Rotate about the z-axism11 = c; m12 = s; m13 = 0.0f;m21 = -s; m22 = c; m23 = 0.0f;m31 = 0.0f; m32 = 0.0f; m33 = 1.0f;break;default:// 不存在的軸索引// bogus axis indexassert(false);}// 重設平移部分// Reset the translation portiontx = ty = tz = 0.0f; }//--------------------------------------------------------------------------- // Matrix4x3::setupRotate // // 構建關于任意軸的旋轉矩陣。 // 該軸必須通過原點。 // Setup the matrix to perform a rotation about an arbitrary axis. // The axis of rotation must pass through the origin. // // axis定義了哪根旋轉軸,并且必須是單位向量。 // axis defines the axis of rotation, and must be a unit vector. // // theta是旋轉量,以弧度計。左手法則定義了旋轉的正方向。 // theta is the amount of rotation, in radians. The left-hand rule is // used to define "positive" rotation. // // 平移部分會被重置。 // The translation portion is reset. // // 查看8.2.3來獲得更多信息。 // See 8.2.3 for more info.void Matrix4x3::setupRotate(const Vector3 &axis, float theta) {// 快速清楚檢查確保axis是單位向量// Quick sanity check to make sure they passed in a unit vector// to specify the axisassert(fabs(axis*axis - 1.0f) < .01f);// 獲得旋轉角的sin和cos值// Get sin and cosine of rotation anglefloat s, c;sinCos(&s, &c, theta);// 計算1 - cos(theta) 和一些公共的子表達式// Compute 1 - cos(theta) and some common subexpressionsfloat a = 1.0f - c;float ax = a * axis.x;float ay = a * axis.y;float az = a * axis.z;// 設置矩陣元素。這里仍然有一些機會去優化,出于許多公共的子表達式。// 我們會讓編譯器來處理它..// Set the matrix elements. There is still a little more// opportunity for optimization due to the many common// subexpressions. We'll let the compiler handle that...m11 = ax*axis.x + c;m12 = ax*axis.y + axis.z*s;m13 = ax*axis.z - axis.y*s;m21 = ay*axis.x - axis.z*s;m22 = ay*axis.y + c;m23 = ay*axis.z + axis.x*s;m31 = az*axis.x + axis.y*s;m32 = az*axis.y - axis.x*s;m33 = az*axis.z + c;// 重置平移部分// Reset the translation portiontx = ty = tz = 0.0f; }//--------------------------------------------------------------------------- // Matrix4x3::fromQuaternion // // 構建矩陣來執行旋轉,給定一個四元數形式的角位移。 // Setup the matrix to perform a rotation, given the angular displacement // in quaternion form. // // 平抑部分會被重置。 // The translation portion is reset. // // 查看10.6.3來獲得更多信息。 // See 10.6.3 for more info.void Matrix4x3::fromQuaternion(const Quaternion &q) {// 計算一些值來優化公共子表達式// Compute a few values to optimize common subexpressionsfloat ww = 2.0f * q.w;float xx = 2.0f * q.x;float yy = 2.0f * q.y;float zz = 2.0f * q.z;// 設置矩陣元素。這里仍然有一些機會去優化,出于許多公共的子表達式。// 我們會讓編譯器來處理它..// Set the matrix elements. There is still a little more// opportunity for optimization due to the many common// subexpressions. We'll let the compiler handle that...m11 = 1.0f - yy*q.y - zz*q.z;m12 = xx*q.y + ww*q.z;m13 = xx*q.z - ww*q.x;m21 = xx*q.y - ww*q.z;m22 = 1.0f - xx*q.x - zz*q.z;m23 = yy*q.z + ww*q.x;m31 = xx*q.z + ww*q.y;m32 = yy*q.z - ww*q.x;m33 = 1.0f - xx*q.x - yy*q.y;// 重置平移部分。// Reset the translation portiontx = ty = tz = 0.0f; }//--------------------------------------------------------------------------- // Matrix4x3::setupScale // // 構建矩陣來執行每根軸上的縮放。使用向量形式的Vector3(k,k,k)來統一縮放k倍。 // Setup the matrix to perform scale on each axis. For uniform scale by k, // use a vector of the form Vector3(k,k,k) // // 這個平移部分會被重置。 // The translation portion is reset. // // 查看8.3.1來獲得更多信息。 // See 8.3.1 for more info.void Matrix4x3::setupScale(const Vector3 &s) {// 設置矩陣元素。相當直接// Set the matrix elements. Pretty straightforwardm11 = s.x; m12 = 0.0f; m13 = 0.0f;m21 = 0.0f; m22 = s.y; m23 = 0.0f;m31 = 0.0f; m32 = 0.0f; m33 = s.z;// 重置平移部分。// Reset the translation portiontx = ty = tz = 0.0f; }//--------------------------------------------------------------------------- // Matrix4x3::setupScaleAlongAxis // // 構建矩陣來執行沿著任意軸的縮放。 // Setup the matrix to perform scale along an arbitrary axis. // // 這根軸被單位向量指定。 // The axis is specified using a unit vector. // // 平移部分會被重置。 // The translation portion is reset. // // 查看8.3.2節來獲得更多信息。 // See 8.3.2 for more info.void Matrix4x3::setupScaleAlongAxis(const Vector3 &axis, float k) {// 快速清楚檢查確保axis是單位向量// Quick sanity check to make sure they passed in a unit vector// to specify the axisassert(fabs(axis*axis - 1.0f) < .01f);// 計算k-1和一些公共子表達式// Compute k-1 and some common subexpressionsfloat a = k - 1.0f;float ax = a * axis.x;float ay = a * axis.y;float az = a * axis.z;// 填充矩陣元素。我們會完成我們的公共子表達式的優化,因為對角相應的矩陣元素是相等的// Fill in the matrix elements. We'll do the common// subexpression optimization ourselves here, since diagonally// opposite matrix elements are equalm11 = ax*axis.x + 1.0f;m22 = ay*axis.y + 1.0f;m32 = az*axis.z + 1.0f;m12 = m21 = ax*axis.y;m13 = m31 = ax*axis.z;m23 = m32 = ay*axis.z;// 重設平移部分// Reset the translation portiontx = ty = tz = 0.0f; }//--------------------------------------------------------------------------- // Matrix4x3::setupShear // // 構建矩陣來執行切變 // Setup the matrix to perform a shear // // 切變類型被基于1的軸索引指定。通過一個矩陣變換一個點的效果如下面的偽代碼所示: // The type of shear is specified by the 1-based "axis" index. The effect // of transforming a point by the matrix is described by the pseudocode // below: // // axis == 1 => y += s*x, z += t*x // axis == 2 => x += s*y, z += t*y // axis == 3 => x += s*z, y += t*z // // 平移部分會被重置。 // The translation portion is reset. // // 查看8.6來獲得更多信息。 // See 8.6 for more info.void Matrix4x3::setupShear(int axis, float s, float t) {// 檢查它們想要那種切變類型// Check which type of shear they wantswitch (axis) {// 使用x切變y和zcase 1: // Shear y and z using xm11 = 1.0f; m12 = s; m13 = t;m21 = 0.0f; m22 = 1.0f; m23 = 0.0f;m31 = 0.0f; m32 = 0.0f; m33 = 1.0f;break;//使用y切變x和zcase 2: // Shear x and z using ym11 = 1.0f; m12 = 0.0f; m13 = 0.0f;m21 = s; m22 = 1.0f; m23 = t;m31 = 0.0f; m32 = 0.0f; m33 = 1.0f;break;// 使用z來切變x和ycase 3: // Shear x and y using zm11 = 1.0f; m12 = 0.0f; m13 = 0.0f;m21 = 0.0f; m22 = 1.0f; m23 = 0.0f;m31 = s; m32 = t; m33 = 1.0f;break;default:// 不存在的軸索引// bogus axis indexassert(false);}// 重設平移部分// Reset the translation portiontx = ty = tz = 0.0f; }//--------------------------------------------------------------------------- // Matrix4x3::setupProject // // 構建矩陣來執行投影到一個通過原點的平面。這個平面垂直于單位向量n。 // Setup the matrix to perform a projection onto a plane passing // through the origin. The plane is perpendicular to the // unit vector n. // // 查看8.4.2來獲得更多的信息。 // See 8.4.2 for more info.void Matrix4x3::setupProject(const Vector3 &n) {// 快速清楚檢查確保axis是單位向量// Quick sanity check to make sure they passed in a unit vector// to specify the axisassert(fabs(n*n - 1.0f) < .01f);// 填充矩陣元素。我們會完成我們的公共子表達式的優化,因為對角相應的矩陣元素是相等的// Fill in the matrix elements. We'll do the common// subexpression optimization ourselves here, since diagonally// opposite matrix elements are equalm11 = 1.0f - n.x*n.x;m22 = 1.0f - n.y*n.y;m33 = 1.0f - n.z*n.z;m12 = m21 = -n.x*n.y;m13 = m31 = -n.x*n.z;m23 = m32 = -n.y*n.z;// 重置平移部分// Reset the translation portiontx = ty = tz = 0.0f; }//--------------------------------------------------------------------------- // Matrix4x3::setupReflect // // 構建矩陣關于一個平行于基本平面的反射。 // Setup the matrix to perform a reflection about a plane parallel // to a cardinal plane. // // axis軸是基于1的索引,指定了關于哪個平面的投影: // axis is a 1-based index which specifies the plane to project about: // // 1 => 關于平面 x=k 的反射 // 2 => 關于平面 y=k 的反射 // 3 => 關于平面 z=k 的反射 // 1 => reflect about the plane x=k // 2 => reflect about the plane y=k // 3 => reflect about the plane z=k // // 平移部分會被恰當地設置,因為如果k!=0的時候平移必須會發生。 // The translation is set appropriately, since translation must occur if // k != 0 // // See 8.5 for more info.void Matrix4x3::setupReflect(int axis, float k) {// 檢查關于哪個平面的反射// Check which plane they want to reflect aboutswitch (axis) {// 關于平面x=k平面的反射case 1: // Reflect about the plane x=km11 = -1.0f; m12 = 0.0f; m13 = 0.0f;m21 = 0.0f; m22 = 1.0f; m23 = 0.0f;m31 = 0.0f; m32 = 0.0f; m33 = 1.0f;tx = 2.0f * k;ty = 0.0f;tz = 0.0f;break;// 關于y=k平面的反射case 2: // Reflect about the plane y=km11 = 1.0f; m12 = 0.0f; m13 = 0.0f;m21 = 0.0f; m22 = -1.0f; m23 = 0.0f;m31 = 0.0f; m32 = 0.0f; m33 = 1.0f;tx = 0.0f;ty = 2.0f * k;tz = 0.0f;break;// 關于z=k平面的反射case 3: // Reflect about the plane z=km11 = 1.0f; m12 = 0.0f; m13 = 0.0f;m21 = 0.0f; m22 = 1.0f; m23 = 0.0f;m31 = 0.0f; m32 = 0.0f; m33 = -1.0f;tx = 0.0f;ty = 0.0f;tz = 2.0f * k;break;default:// 不存在的軸索引// bogus axis indexassert(false);}}//--------------------------------------------------------------------------- // Matrix4x3::setupReflect // // 設置矩陣執行關于任意通過原點的平面的反射。這個單位向量n垂直于平面。 // Setup the matrix to perform a reflection about an arbitrary plane // through the origin. The unit vector n is perpendicular to the plane. // // 平移部分會被重置。 // The translation portion is reset. // // 查看8.5節來獲得更多的信息。 // See 8.5 for more info.void Matrix4x3::setupReflect(const Vector3 &n) {// 快速清楚檢查確保axis是單位向量// Quick sanity check to make sure they passed in a unit vector// to specify the axisassert(fabs(n*n - 1.0f) < .01f);// 計算公共子表達式// Compute common subexpressionsfloat ax = -2.0f * n.x;float ay = -2.0f * n.y;float az = -2.0f * n.z;// 填充矩陣元素。我們會完成我們的公共子表達式的優化,因為對角相應的矩陣元素是相等的// Fill in the matrix elements. We'll do the common// subexpression optimization ourselves here, since diagonally// opposite matrix elements are equalm11 = 1.0f + ax*n.x;m22 = 1.0f + ay*n.y;m32 = 1.0f + az*n.z;m12 = m21 = ax*n.y;m13 = m31 = ax*n.z;m23 = m32 = ay*n.z;// 重置平移部分。// Reset the translation portiontx = ty = tz = 0.0f; }//--------------------------------------------------------------------------- // Vector * Matrix4x3 // // 變換頂點。這會使得向量類看起來和線性代數紙上記號是一致的。 // Transform the point. This makes using the vector class look like it // does with linear algebra notation on paper. // // 我們也會提供*=操作,作為C語言的習慣約定。 // We also provide a *= operator, as per C convention. // // 參見7.1.7節 // See 7.1.7Vector3 operator*(const Vector3 &p, const Matrix4x3 &m) {// 通過線性代數磨合// Grind through the linear algebra.return Vector3(p.x*m.m11 + p.y*m.m21 + p.z*m.m31 + m.tx,p.x*m.m12 + p.y*m.m22 + p.z*m.m32 + m.ty,p.x*m.m13 + p.y*m.m23 + p.z*m.m33 + m.tz); }Vector3 &operator*=(Vector3 &p, const Matrix4x3 &m) {p = p * m;return p; }//--------------------------------------------------------------------------- // Matrix4x3 * Matrix4x3 // // 矩陣連接。這會使得矩陣類看起來和線性代數紙上記號是一致的。 // Matrix concatenation. This makes using the vector class look like it // does with linear algebra notation on paper. // // 我們也會提供*=操作,作為C語言的習慣約定。 // We also provide a *= operator, as per C convention. // // 參見7.1.6節 // See 7.1.6Matrix4x3 operator*(const Matrix4x3 &a, const Matrix4x3 &b) {Matrix4x3 r;// 計算上面3x3(線性變換)部分// Compute the upper 3x3 (linear transformation) portionr.m11 = a.m11*b.m11 + a.m12*b.m21 + a.m13*b.m31;r.m12 = a.m11*b.m12 + a.m12*b.m22 + a.m13*b.m32;r.m13 = a.m11*b.m13 + a.m12*b.m23 + a.m13*b.m33;r.m21 = a.m21*b.m11 + a.m22*b.m21 + a.m23*b.m31;r.m22 = a.m21*b.m12 + a.m22*b.m22 + a.m23*b.m32;r.m23 = a.m21*b.m13 + a.m22*b.m23 + a.m23*b.m33;r.m31 = a.m31*b.m11 + a.m32*b.m21 + a.m33*b.m31;r.m32 = a.m31*b.m12 + a.m32*b.m22 + a.m33*b.m32;r.m33 = a.m31*b.m13 + a.m32*b.m23 + a.m33*b.m33;// 計算平移部分// Compute the translation portionr.tx = a.tx*b.m11 + a.ty*b.m21 + a.tz*b.m31 + b.tx;r.ty = a.tx*b.m12 + a.ty*b.m22 + a.tz*b.m32 + b.ty;r.tz = a.tx*b.m13 + a.ty*b.m23 + a.tz*b.m33 + b.tz;// 返回它。哎呀 - 會調用了構造函數。如果速度是至關重要的,我們可能需要// 一個不同的函數在我們想要的地方放置它...// Return it. Ouch - involves a copy constructor call. If speed// is critical, we may need a seperate function which places the// result where we want it...return r; }Matrix4x3 &operator*=(Matrix4x3 &a, const Matrix4x3 &b) {a = a * b;return a; }//--------------------------------------------------------------------------- // determinant // // 計算3x3部分的矩陣行列式 // Compute the determinant of the 3x3 portion of the matrix. // // 參見9.1.1節獲得更多信息。 // See 9.1.1 for more info.float determinant(const Matrix4x3 &m) {returnm.m11 * (m.m22*m.m33 - m.m23*m.m32)+ m.m12 * (m.m23*m.m31 - m.m21*m.m33)+ m.m13 * (m.m21*m.m32 - m.m22*m.m31); }//--------------------------------------------------------------------------- // inverse // // 計算矩陣的逆。我們使用傳統的用伴隨矩陣除以行列式來的方法計算。 // Compute the inverse of a matrix. We use the classical adjoint divided // by the determinant method. // // 參見9.2.1來獲得更多信息。 // See 9.2.1 for more info.Matrix4x3 inverse(const Matrix4x3 &m) {// 計算行列式// Compute the determinantfloat det = determinant(m);// 如果是奇異矩陣,行列式是零,并且沒有逆矩陣// If we're singular, then the determinant is zero and there's// no inverseassert(fabs(det) > 0.000001f);// 計算一除以行列式,所以我們只需要除一次,然后乘去每一個元素。// Compute one over the determinant, so we divide once and// can *multiply* per elementfloat oneOverDet = 1.0f / det;// 計算3x3部分的逆矩陣,通過伴隨矩陣除以行列式。// Compute the 3x3 portion of the inverse, by// dividing the adjoint by the determinantMatrix4x3 r;r.m11 = (m.m22*m.m33 - m.m23*m.m32) * oneOverDet;r.m12 = (m.m13*m.m32 - m.m12*m.m33) * oneOverDet;r.m13 = (m.m12*m.m23 - m.m13*m.m22) * oneOverDet;r.m21 = (m.m23*m.m31 - m.m21*m.m33) * oneOverDet;r.m22 = (m.m11*m.m33 - m.m13*m.m31) * oneOverDet;r.m23 = (m.m13*m.m21 - m.m11*m.m23) * oneOverDet;r.m31 = (m.m21*m.m32 - m.m22*m.m31) * oneOverDet;r.m32 = (m.m12*m.m31 - m.m11*m.m32) * oneOverDet;r.m33 = (m.m11*m.m22 - m.m12*m.m21) * oneOverDet;// 計算逆矩陣的平移部分// Compute the translation portion of the inverser.tx = -(m.tx*r.m11 + m.ty*r.m21 + m.tz*r.m31);r.ty = -(m.tx*r.m12 + m.ty*r.m22 + m.tz*r.m32);r.tz = -(m.tx*r.m13 + m.ty*r.m23 + m.tz*r.m33);// 返回它。哎呀 - 會調用了構造函數。如果速度是至關重要的,我們可能需要// 一個不同的函數在我們想要的地方放置它...// Return it. Ouch - involves a copy constructor call. If speed// is critical, we may need a seperate function which places the// result where we want it...return r; }//--------------------------------------------------------------------------- // getTranslation // // 以向量形式返回矩陣的平移部分 // Return the translation row of the matrix in vector formVector3 getTranslation(const Matrix4x3 &m) {return Vector3(m.tx, m.ty, m.tz); }//--------------------------------------------------------------------------- // getPositionFromParentToLocalMatrix // // 提取從父空間->局部空間變換矩陣的平移部分(就像世界坐標系->物體坐標系矩陣) // Extract the position of an object given a parent -> local transformation // matrix (such as a world -> object matrix) // // 我們假定矩陣呈現的是堅固的變換。(沒有縮放、傾斜、或者鏡像) // We assume that the matrix represents a rigid transformation. (No scale, // skew, or mirroring)Vector3 getPositionFromParentToLocalMatrix(const Matrix4x3 &m) {// 通過轉置3x3部分乘以負平移值。通過矩陣的轉置,我們假定矩陣是正交的。(這個函數對于非堅固變換的變換是沒有意義的)// Multiply negative translation value by the// transpose of the 3x3 portion. By using the transpose,// we assume that the matrix is orthogonal. (This function// doesn't really make sense for non-rigid transformations...)return Vector3(-(m.tx*m.m11 + m.ty*m.m12 + m.tz*m.m13),-(m.tx*m.m21 + m.ty*m.m22 + m.tz*m.m23),-(m.tx*m.m31 + m.ty*m.m32 + m.tz*m.m33)); }//--------------------------------------------------------------------------- // getPositionFromLocalToParentMatrix // // 提取給定局部坐標系->父坐標系的位置變換矩陣(例如物體坐標系->世界坐標系矩陣) // Extract the position of an object given a local -> parent transformation // matrix (such as an object -> world matrix)Vector3 getPositionFromLocalToParentMatrix(const Matrix4x3 &m) {// 位置簡明地是平移部分// Position is simply the translation portionreturn Vector3(m.tx, m.ty, m.tz); }總結
以上是生活随笔為你收集整理的3D数学基础:Matrix4*3类代码清单的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言智能家居安防系统,智能家居之安防智
- 下一篇: 运维人员常用到的 11 款服务器监控工具