3D数学 4x3矩阵类源代码(附中文注释)

来源:互联网 发布:centos安装intellij 编辑:程序博客网 时间:2024/06/01 09:11

4x3矩阵类

///////////////////////////////////////////////////////////////////////////////// 3D数学基础:游戏与图形开发// 3D Math Primer for Games and Graphics Development//// Matrix4x3.h - Matrix4x3类声明// Matrix4x3.h - Declarations for class Matrix4x3//// 登录gamemath.com以获得该文件的最新版本// Visit gamemath.com for the latest version of this file.//// 更多细节,请看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 identity    void    identity();    // 直接使用矩阵平移部分    // Access the translation portion of the matrix directly    void    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 matrix    void    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 axis    void    setupRotate(int axis, float theta);    // 构建关于任意轴的旋转矩阵。    // Setup the matrix to perform a rotation about an arbitrary axis    void    setupRotate(const Vector3 &axis, float theta);    // 构建矩阵来执行旋转,给定一个四元数形式的角位移。    // Setup the matrix to perform a rotation, given    // the angular displacement in quaternion form    void    fromQuaternion(const Quaternion &q);    // 构建矩阵来执行每根轴上的缩放。使用向量形式的Vector3(k,k,k)来统一缩放k倍。    // Setup the matrix to perform scale on each axis    void    setupScale(const Vector3 &s);    // 构建矩阵来执行沿着任意轴的缩放。    // Setup the matrix to perform scale along an arbitrary axis    void    setupScaleAlongAxis(const Vector3 &axis, float k);    // 构建矩阵来执行切变    // Setup the matrix to perform a shear    void    setupShear(int axis, float s, float t);    // 构建矩阵来执行投影到一个通过原点的平面。    // Setup the matrix to perform a projection onto a plane passing    // through the origin    void    setupProject(const Vector3 &n);    // 构建矩阵关于一个平行于基本平面的反射。    // Setup the matrix to perform a reflection about a plane parallel    // to a cardinal plane    void    setupReflect(int axis, float k = 0.0f);    // 设置矩阵执行关于任意通过原点的平面的反射。    // Setup the matrix to perform a reflection about an arbitrary plane    // through the origin    void    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__
///////////////////////////////////////////////////////////////////////////////// 3D数学基础:游戏与图形开发// 3D Math Primer for Games and Graphics Development//// Matrix4x3.cpp - Matrix4x3实现// Matrix4x3.cpp - Implementation of class Matrix4x3//// 登录gamemath.com以获得该文件的最新版本// Visit gamemath.com for the latest version of this file.//// 更多细节请看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 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;    // 设置平移部分    // Set the translation portion    tx = 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 copying    m11 = 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 directly    tx = 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.cpp    m11 = 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 TR    tx = -(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 angle    float   s, c;    sinCos(&s, &c, theta);    // 检查关于哪根轴旋转    // Check which axis they are rotating about    switch (axis) {                // 关于x轴旋转        case 1: // Rotate about the x-axis            m11 = 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-axis            m11 = 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-axis            m11 = 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 index            assert(false);    }    // 重设平移部分    // Reset the translation portion    tx = 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 axis    assert(fabs(axis*axis - 1.0f) < .01f);    // 获得旋转角的sin和cos值    // Get sin and cosine of rotation angle    float   s, c;    sinCos(&s, &c, theta);    // 计算1 - cos(theta) 和一些公共的子表达式    // Compute 1 - cos(theta) and some common subexpressions    float   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 portion    tx = 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 subexpressions    float   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 portion    tx = 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 straightforward    m11 = 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 portion    tx = 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 axis    assert(fabs(axis*axis - 1.0f) < .01f);    // 计算k-1和一些公共子表达式    // Compute k-1 and some common subexpressions    float   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 equal    m11 = 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 portion    tx = 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 want    switch (axis) {                // 使用x切变y和z        case 1: // Shear y and z using x            m11 = 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和z        case 2: // Shear x and z using y            m11 = 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和y        case 3: // Shear x and y using z            m11 = 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 index            assert(false);    }    // 重设平移部分    // Reset the translation portion    tx = 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 axis    assert(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 equal    m11 = 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 portion    tx = 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 about    switch (axis) {                // 关于平面x=k平面的反射        case 1: // Reflect about the plane x=k            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 = 2.0f * k;            ty = 0.0f;            tz = 0.0f;            break;                // 关于y=k平面的反射        case 2: // Reflect about the plane y=k            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 = 2.0f * k;            tz = 0.0f;            break;                // 关于z=k平面的反射        case 3: // Reflect about the plane z=k            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 = 2.0f * k;            break;        default:            // 不存在的轴索引            // bogus axis index            assert(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 axis    assert(fabs(n*n - 1.0f) < .01f);    // 计算公共子表达式    // Compute common subexpressions    float   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 equal    m11 = 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 portion    tx = 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) portion    r.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 portion    r.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) {    return          m.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 determinant    float   det = determinant(m);    // 如果是奇异矩阵,行列式是零,并且没有逆矩阵    // If we're singular, then the determinant is zero and there's    // no inverse    assert(fabs(det) > 0.000001f);    // 计算一除以行列式,所以我们只需要除一次,然后乘去每一个元素。    // Compute one over the determinant, so we divide once and    // can *multiply* per element    float   oneOverDet = 1.0f / det;    // 计算3x3部分的逆矩阵,通过伴随矩阵除以行列式。    // Compute the 3x3 portion of the inverse, by    // dividing the adjoint by the determinant    Matrix4x3   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 inverse    r.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 portion    return Vector3(m.tx, m.ty, m.tz);}
0 0
原创粉丝点击