dx12 龙书第二章学习笔记 -- 矩阵代数

24 篇文章 10 订阅

1.矩阵及其运算

矩阵的运算:①加②减③标量乘法

④矩阵乘法:

A_{m*n} * B_{n*p}=C_{m*p}

矩阵乘法要有意义的条件是矩阵A的列数和矩阵B的行数必须相同,所以一般不满足交换律

\\(A+B)C=AC+BC\\ (AB)C=A(BC)

⑤转置矩阵:

\\(A+B)^T=A^T+B^T\\ (cA)^T=cA^T\\ (AB)^T=B^TA^T\\(A^T)^T=A\\(A^{-1})^T=(A^T)^{-1}

⑥矩阵行列式:det A

学习行列式的主要目的是:利用它推导出求逆矩阵的公式

方阵A是可逆的,当且仅当det A ≠ 0

余子阵:去除第i行和第j行得到的(n-1)*(n-1)矩阵0

detA=\sum_{j=1}^{n}A_{1j}(-1)^{1+j}det\overline{A_{1j}}

矩阵的行列式是一种递归定义,detA的A当是二维方阵时,行列式的值就是\begin{vmatrix} a & b\\ c &d \end{vmatrix}=ad-bc

元素Aij的代数余子阵:

C_{ij}=(-1)^{i+j}det\overline{A_{ij}}   如果为矩阵A中每个元素分别计算出Cij,并将其置于矩阵C_A中第i行、第j列的相应位置,那么将获得矩阵A的代数余子式矩阵

伴随矩阵A^*=C_A^T  代数余子阵的转置

⑦逆矩阵:

可逆矩阵的逆矩阵是唯一的 MM^{-1}=M^{-1}M=I

A^{-1}=\frac{A^*}{detA}

矩阵不存在除法的概念,但提供逆矩阵可以求解某些方程:比如p'=pM 求解p

(AB)^{-1}=A^{-1}B^{-1}

2.用DirectXMath库处理矩阵:

XMMATRIX : 由4个XMVECTOR组成,借此使用SIMD技术 --  4x4的矩阵

// XMMATRIX类表示4×4矩阵

// 内部用r来存储4个行向量
XMVECTOR r[4]; 

// 构造方法:
// 4个行向量
XMVECTOR(FXMVECTOR R0,FXMVECTOR R1,FXMVECTOR R2,CXMVECTOR R3); 

// 16个浮点数
XMMATRIX(float m00,float m01,...); 

// 16个浮点数元素数组
explicit XMMATRIX(_in_reads_(16) const float *pArray); 

// 拷贝构造函数
XMMATRIX& operator=(const XMMATRIX& M);

XMMATRIX运算:

1.两个XMMATRIX矩阵:

+ - += -=

* *=

2.XMMATRIX和浮点数:

/ * /= *=

XMMATRIX创建实例的其他方法:

XMMATRIX XM_CALLCONV 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,    
);

DirectXMath文档也建议我们用XMFLOAT4X4来存储类中的矩阵类型数据成员:

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];
    // 初始化方式和XMMATRIX类似 -- 1.16个浮点数2.浮点数数组
    // 还可以指定(行数,列数),或=从另一个实例复制
    float operator() (size_t Row, size_t Column)const{return m[Row][Column];}
};

①加载方法:

inline XMMATRIX XM_CALLCONV XMLoadFloat4x4(const XMFLOAT4X4* pSource);

②存储方法:

inline void XM_CALLCONV XMStoreFloat4x4(XMFLOAT4X4* pDestination, FXMMATRIX M);

矩阵函数:直接用于创建特定矩阵

// 返回单位矩阵I
XMMatrixIdentity() 

// bool 判断是否为单位矩阵
XMMatrixIsIdentity(FXMMATRIX M); 

// 返回乘积AB
XMMatrixMultiply(FXMMATRIX A,CXMMATRIX B); 

// 返回转置矩阵
XMMatrixTranspose(FXMMATRIX M); 

// 返回(det M,det M,det M,det M) -- XMVECTOR类型
XMMatrixDeterminant(FXMMATRIX M); 

// 输入:pDeterminant是(det M,det M,det M,det M) 返回M的逆矩阵
XMMatrixInverse(XMVECTOR* pDeterminant, FXMMATRIX M); 

假设传入函数的XMVECTOR参数不超过两个,则第一个XMMATRIX参数应当为FXMMATRIX类型,其余的XMMATRIX参数均应当为CXMMATRIX类型

在32位Windows操作系统上的__fastcall调用约定中,XMMATRIX类型的参数是不能传至SSE/SSE2寄存器的,因为这些寄存器只支持3个XMVECTOR参数传入(XMMATRIX视为4个XMVECTOR),所以只能通过堆栈来加以引用 

// 32位
typedef const XMMATRIX& FXMMATRIX;
typedef const XMMATRIX& CXMMATRIX;

// 64位
typedef const XMMATRIX FXMMATRIX;
typedef const XMMATRIX& CXMMATRIX;

代码示例:

#include <windows.h> // XMVerifyCPUSupport()函数
#include <DirectXMath.h>
#include <DirectXPackedVector.h>
#include <iostream>
using namespace DirectX;
using namespace DirectX::PackedVector;
using namespace std;

ostream& XM_CALLCONV operator<<(ostream& os, FXMMATRIX m)
{
	XMFLOAT4X4 dest;
	XMStoreFloat4x4(&dest, m);

	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			os << dest.m[i][j] << " ";
		}
		os << "\n";
	}
	return os;
	// 也可以通过cout遍历打印FXMMATRIX的XMVECTOR数组成员r
}

int main()
{
	cout.setf(ios_base::boolalpha);

	// 检查是否支持SSE2指令集
	if (!XMVerifyCPUSupport())
	{
		cout << "direct math not supported" << endl;
		return 0;
	}

	XMMATRIX m1 = XMMatrixIdentity();
	cout << m1 << endl;

	XMMATRIX m2 = XMMatrixSet(
		1.f, 0.f, 0.f, 0.f,
		0.f, 2.f, 0.f, 0.f,
		0.f, 0.f, 4.f, 0.f,
		1.f, 2.f, 3.f, 1.f
	);
	cout << m2 << endl;

	XMMATRIX m3 = XMMatrixTranspose(m2);
	cout << m3 << endl;

	cout << m2 * m3 << endl;
	cout << 2 * m1 << endl;
	cout << m3 - m2 << endl;

	XMVECTOR v = XMMatrixDeterminant(m2);
	XMMATRIX m4 = XMMatrixInverse(&v, m2);
	cout << m4 << endl;
	
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值