2.8 XNA 矩阵
为了变换点和向量,我们使用1x4的行向量和4x4的矩阵,原因将在在下章中介绍。下面我们重点来看下表示4x4矩阵的类型。
2.8.1矩阵类型
为了在XNA数学库中表示4x4的矩阵,我们使用XMMATRIX类,它被定义在xnamath.h头文件中,示例如下:(其中我们添加了额外的注释)
// Matrix type: Sixteen 32 bitfloating point components aligned on a
// 16 byte boundary and mapped to four hardware vector registers
//16个32位浮点型分量组成一个16字节宽,映射到4个硬件寄存器。
#if (defined(_XM_X86_) || defined(_XM_X64_)) && defined(_XM_NO_INTRINSICS_) typedef struct _XMMATRIX
#else
typedef _DECLSPEC_ALIGN_16_ struct _XMMATRIX #endif
{
union
{
// Use 4 XMVECTORs to represent the matrix for SIMD. XMVECTORr[4];
struct
{
FLOAT _11, _12, _13, _14;
FLOAT _21, _22, _23, _24;
FLOAT _31, _32, _33, _34;
FLOAT _41, _42, _43, _44;
};
FLOAT m[4][4];
};
#ifdef __cplusplus
_XMMATRIX() {};
// Initialize matrix by specifying 4 row vectors.
_XMMATRIX(FXMVECTOR R0, FXMVECTOR R1, FXMVECTOR R2, CXMVECTOR R3); // Initialize matrix by specifying the 16 elements.
_XMMATRIX(FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m03,
FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m13,
FLOAT m20, FLOAT m21, FLOAT m22, FLOAT m23,
FLOAT m30, FLOAT m31, FLOAT m32, FLOAT m33);
// Pass array of sixteen floats to construct matrix.
_XMMATRIX(CONST FLOAT *pArray);
FLOAT operator() (UINT Row, UINT Column) CONST { return m[Row][Column]; } FLOAT& operator() (UINT Row, UINT Column) { return m[Row][Column]; }
_XMMATRIX& operator= (CONST _XMMATRIX& M);
#ifndef XM_NO_OPERATOR_OVERLOADS
_XMMATRIX& operator*= (CONST _XMMATRIX& M);
_XMMATRIX operator* (CONST _XMMATRIX& M) CONST; #endif // !XM_NO_OPERATOR_OVERLOADS
#endif // __cplusplus
} XMMATRIX;
通过这些代码,我们可以看到XMMATRIX使用了4个XMVECTOR实例,以便使用SIMD。此外,XMMATRIX提供了重载运算符用于多行矩阵;提供插入成员操作的重载,用来访问或者修改指定的行或列的元素分量。
除了使用多种构造函数,也可以使用XMMatrixSet来创建XMMATRIX实例:
XMMATRIX XMMatrixSet(FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m03, FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m13,
FLOAT m20, FLOAT m21, FLOAT m22, FLOAT m23,
FLOAT m30, FLOAT m31, FLOAT m32, FLOAT m33);
正如我们使用XMFLOAT2 (2D), XMFLOAT3 (3D),和XMFLOAT4 (4D)在类中存储向量那样,XNA数学库的帮助文档建议使用XMFLOAT4x4类型来存储矩阵数据作为类的成员变量。
// 4x4Matrix: 32 bit floating point components typedef struct _XMFLOAT4X4
{
union
{
struct
{
FLOAT _11, _12, _13, _14;
FLOAT _21, _22, _23, _24;
FLOAT _31, _32, _33, _34;
FLOAT _41, _42, _43, _44;
};
FLOAT m[4][4];
};
#ifdef __cplusplus
_XMFLOAT4X4() {};
_XMFLOAT4X4(FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m03, FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m13,
FLOAT m20, FLOAT m21, FLOAT m22, FLOAT m23,
FLOAT m30, FLOAT m31, FLOAT m32, FLOAT m33);
_XMFLOAT4X4(CONST FLOAT *pArray);
FLOAT operator() (UINT Row, UINT Column) CONST { return m[Row][Column]; } FLOAT& operator() (UINT Row, UINT Column) { return m[Row][Column]; }
_XMFLOAT4X4& operator= (CONST _XMFLOAT4X4& Float4x4);
#endif // __cplusplus
} XMFLOAT4X4;
2.8.2 矩阵函数
XNA数学库包含如下使用的矩阵方法:
XMMATRIXXMMatrixIdentity(); // 返回单位矩阵I
BOOL XMMatrixIsIdentity( // 返回真假,若M为单位矩阵,返回真……
matrix CXMMATRIX M); // Input M
XMMATRIX XMMatrixMultiply( // 返回AB
CXMMATRIX A, // Input A
CXMMATRIX B); // Input B
XMMATRIX XMMatrixTranspose(//返回MT
CXMMATRIX M); // Input M
XMVECTOR XMMatrixDeterminant( // 返回 (det M,det M,det M,det
M) CXMMATRIX M); // Input M
XMMATRIXXMMatrixInverse( // Returns M-1
XMVECTOR* pDeterminant, // Input (det M,det M,det M,det M) CXMMATRIX M); // Input M
注意:XMMATRIX的参数必须为CXMMATRIX,这样可以确保XMMATRIX参数在XBOX360和windows平台上正确的运行
// Fix-up for XMMATRIXparameters to pass in-register on Xbox 360, // by reference otherwise
#ifdefined(_XM_VMX128_INTRINSICS_)
typedef const XMMATRIXCXMMATRIX;
#elif defined(__cplusplus)
typedef const XMMATRIX& CXMMATRIX;
2.8.3 XNA矩阵示例程序
下列代码演示了如何使用XMMATRIX类及前一节中提到的大多数函数
#include
#include
using namespace std;
// 重载"<<"运算符,这样我们可以用它输出XMVECTOR 和 XMMATRIX 对象
ostream& operator<<(ostream& os,
FXMVECTOR v)
{
XMFLOAT4 dest;
XMStoreFloat4(&dest, v);
os << "(" << dest.x << ", " << dest.y << ", " << dest.z << ", " << dest.w << ")";
return os;
}
ostream& operator<<(ostream& os, CXMMATRIX m)
{
for(int i = 0; i < 4; ++i)
{
for(int j = 0; j < 4; ++j)
os << m(i, j) << "\t";
os << endl;
}
return os;
}
int main()
{
// Check support for SSE2 (Pentium4, AMD K8, and above). if( !XMVerifyCPUSupport() )
{
cout << "xna math not supported" << endl; return 0;
}
XMMATRIX A(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 2.0f, 0.0f, 0.0f,
0.0f, 0.0f, 4.0f, 0.0f,
1.0f, 2.0f, 3.0f, 1.0f);
XMMATRIX B = XMMatrixIdentity();
XMMATRIX C = A * B;
XMMATRIX D = XMMatrixTranspose(A);
XMVECTOR det = XMMatrixDeterminant(A); XMMATRIX E = XMMatrixInverse(&det, A); XMMATRIX F = A * E;
cout << "A = " << endl << A << endl;
cout << "B = " << endl << B << endl;
cout << "C = A*B = " << endl << C << endl;
cout << "D = transpose(A) = " << endl << D << endl;
cout << "det = determinant(A) = " << det << endl << endl; cout << "E = inverse(A) = " << endl << E << endl;
cout << "F = A*E = " << endl << F << endl;
return 0;
}
2.9 小结
2.10 练习