Directx11學習筆記【五】 基本的數學知識----向量篇


本文參考dx11龍書 Chapter1 vector algebra(向量代數)

 

要想學好游戲編程,扎實的數學知識是尤為重要的,下面將對dx11龍書中有關向量的數學知識做一下總結。

在數學中,幾何向量(也稱為歐幾里得向量,通常簡稱向量、矢量),指具有大小(magnitude)和方向(direction)的幾何對象,可以形象化地表示為帶箭頭的線段,箭頭所指:代表向量的方向、線段長度:代表向量的大小。

向量的表示方式一般有3種:

  1.代數表示:一般印刷用黑體小寫字母α、β、γ…或a、b、c… 等來表示,手寫用在a、b、c…等字母上加一箭頭表示

  2.幾何表示:用有向線段表示

  3.坐標表示

(注:directx使用的是左手系,下面不作說明均以左手系為准)

向量的一些基本操作(部分摘自百度百科)

1.向量的模,即向量的長度。

向量a的模記作|a|。向量的模是非負實數,是可以比較大小的。因為方向不能比較大小,所以向量也就不能比較大小。對於向量來說“大於”和“小於”的概念是沒有意義的。例如,“向量AB>向量CD”是沒有意義的。

2.單位向量
長度為一個單位(即模為1)的向量,叫做單位向。與向量a同向,且長度為單位1的向量,叫做a方向上的單位向量,記作a0,a0=a/|a|。
3.向量的加減法
向量的加法滿足平行四邊形法則和三角形法則。OB+OA=OC。
a+0=0+a=a。
向量加法的運算律:
交換律:a+b=b+a;
結合律:(a+b)+c=a+(b+c)。
減法與加法類似
4.數量積(點積)
定義:已知兩個非零向量a,b。作OA=a,OB=b,則角AOB稱作向量a和向量b的夾角,記作〈a,b〉並規定0≤〈a,b〉≤π
定義:兩個向量的數量積(內積、點積)是一個數量(沒有方向),記作a·b。若a、b不共線,則a·b=|a|·|b|·cos〈a,b〉(依定義有:cos〈a,b〉=a·b / |a|·|b|);若a、b共線,則a·b=±∣a∣∣b∣。
向量的數量積的坐標表示:a·b=x·x'+y·y'。
向量的數量積的運算律
a·b=b·a(交換律)
(λa)·b=λ(a·b)(關於數乘法的結合律)
(a+b)·c=a·c+b·c(分配律)
向量的數量積的性質
a·a=|a|的平方。
a⊥b〈=〉a·b=0。
|a·b|≤|a|·|b|。
5.向量積(叉積)
定義:兩個向量a和b的向量積
(外積、叉積)是一個向量,記作a×b(這里“×”並不是乘號,只是一種表示方法,與“·”不同,也可記做“∧”)。若a、b不共線,則a×b的模是:∣a×b∣=|a|·|b|·sin〈a,b〉;a×b的方向是:垂直於a和b,且a、b和a×b按這個次序構成右手系。若a、b垂直,則∣a×b∣=|a|*|b|(此處與數量積不同,請注意),若a×b=0,則a、b平行。向量積即兩個不共線非零向量所在平面的一組法向量。
運算法則:運用三階行列式
設a,b,c分別為沿x,y,z軸的單位向量
A=(x1,y1,z1)B=(x2,y2,z2)則A*B=
a b c
x1 y1 z1
x2 y2 z2
向量的向量積性質:
∣a×b∣是以a和b為邊的平行四邊形面積。
a×a=0。
a平行b〈=〉a×b=0
向量的向量積運算律
a×b=-b×a
(λa)×b=λ(a×b)=a×(λb)
a×(b+c)=a×b+a×c.
(a+b)×c=a×c+b×c.
6.向量投影

給定一個向量u和v,求u在v上的投影向量,如下圖。

假設u在v上的投影向量是u’,且向量u和v的夾角為theta。一個向量有兩個屬性,大小和方向,我們先確定u’的大小(即長度,或者模),從u的末端做v的垂線,那么d就是u’的長度。而u’和v的方向是相同的,v的方向v/|v|也就是u’的方向。所以有

                          (1)

再求d的長度。

                      (2)

最后求cos(theta)

                   (3)

聯合求解方程(1)(2)(3)得到

這就是最終的投影向量。

而這個向量的長度d是

============================

以下是舊的推導,也保留。

XNA MathVectors

下面介紹一些xna math庫中常用的向量結構及方法

 

1.向量類型

有XMVECTOR,XMFLOAT2,XMFLOAT3,XMFLOAT4等幾種類型,具體可以看dx11龍書1.6.1節

在這一章中作者給出使用向量類型應注意的5點:

(1)、 對局部變量和全局變量,使用XMVECTOR類型;

(2)、 對類的數據成員,使用XMFLOAT2, XMFLOAT3和XMFLOAT4數據成員;

(3)、 在進行計算之前,使用載入函數(loading functions)來將XMFLOAT*類型轉換成XMVECTOR類型;

(4)、 用XMVECTOR的實例進行計算;

(5)、 使用存儲函數(storage functions)來將XMVECTOR轉換成XMFLOAT*類型

 

2.Loading and Storage Methods(載入和存儲函數)

我們用下面的方法來加載數據,從XMFLOAT*到XMVECTOR

XMVECTOR XMLoadFloat3(CONST XMFLOAT3 *pSource);

XMVECTOR XMLoadInt3(CONST UINT* pSource);

XMVECTOR XMLoadColor(CONST XMCOLOR *pSource);

用下面的方法存儲數據,從XMVECTOR到XMFLOAT*

VOID XMStoreFloat3(XMFLOAT3 *pDestination,FXMVECTOR V);

......

3.Parameter Passing參數傳遞

龍書中主要介紹了CXMVECTOR 和FXMVECTOR 這兩種參數類型,並告訴了我們在定義函數時,參數類型的注意事項:

函數的前三個XMVECTOR類型必須是FXMVECTOR,而后面的都是CXMVECTOR。

 

4.Constant Vectors常向量

需要初始化的XMVECTOR常量應該定義為XMVECTORF32類型(用於存儲浮點向量)或XMVECTORU32類型(用於存儲整數向量).

 

5.Vector Functions一些向量運算有關的函數

XMVECTOR XMVectorZero();//返回零向量

XMVECTOR XMVectorSplatOne();//返回(1,1,1,1)

XMVECTOR XMVectorSet(FLOAT x,FLOAT y,FLOAT z,FLOAT w);//返回(x,y,z,w)

XMVECTOR XMVectorReplicate(FLOAT s);//返回(s,s,s,s)

XMVECTOR XMVectorSplatX(FXMVECTOR V);//返回(vx,vx,vx,vx)

 

XMVECTOR XMVector3Length(FXMVECTOR V);//返回向量v的模所構成的新的向量,例如向量v模為2,則返回(2,2,2)

XMVECTOR XMVector3LengthSq(FXMVECTOR V);//模的平方

XMVECTOR XMVector3Dot(FXMVECTOR V1,FXMVECTOR V2);//點積

XMVECTOR XMVector3Cross(FXMVECTOR V1,FXMVECTOR V2);//叉積

XMVECTOR XMVector3Normalize(FXMVECTOR V);//單位化

XMVECTOR XMVector3Orthogonal(FXMVECTOR V);//得到一個與其垂直的向量

XMVECTOR XMVector3AngleBetweenVectors(FXMVECTOR V1,FXMVECTOR V2);//兩個向量的夾角

VOID XMVector3ComponentsFromNormal(XMVECTOR* pParallel,XMVECTOR* pPerpendicular,FXMVECTOR V,FXMVECTOR Normal);//向量的投影

BOOL XMVector3Equal(FXMVECTOR V1,FXMVECTOR V2);//判斷兩個向量是否相等

 

6.Floating-Point Error浮點數計算誤差

用浮點數進行計算(甚至單純地表示)時,會出現誤差,所以等判斷相等時,需要定義一個容許誤差。

 

 

 

附:dx11龍書測試的源碼及測試結果

1.

 1 #include <windows.h>
 2 #include <xnamath.h>
 3 #include <iostream>
 4 using namespace std;
 5 
 6 //重載<<操作符
 7 ostream& operator<<(ostream &os, FXMVECTOR v)
 8 {
 9     XMFLOAT3 dest;
10     XMStoreFloat3(&dest, v);
11     os << "(" << dest.x << "," << dest.y << "," << dest.z << ")";
12     return os;
13 }
14 
15 int main()
16 {
17     cout.setf(ios_base::boolalpha);//cout格式化 輸入輸出bool值可以為true和false
18 
19     //檢查是否支持SSE2
20     if (!XMVerifyCPUSupport())
21     {
22         cout << "xna math not supported" << endl;
23         return 0;
24     }
25     XMVECTOR p = XMVectorZero();
26     XMVECTOR q = XMVectorSplatOne();
27     XMVECTOR u = XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f);
28     XMVECTOR v = XMVectorSplatX(u);
29     XMVECTOR w = XMVectorReplicate(-3.5f);
30 
31     cout << "p = " << p << endl;
32     cout << "q = " << q << endl;
33     cout << "u = " << u << endl;
34     cout << "v = " << v << endl;
35     cout << "w = " << w << endl;
36 
37     return 0;
38 }

 

2.

 1 #include <windows.h>
 2 #include <xnamath.h>
 3 #include <iostream>
 4 using namespace std;
 5 
 6 ostream& operator<<(ostream &os, FXMVECTOR v)
 7 {
 8     XMFLOAT3 dest;
 9     XMStoreFloat3(&dest, v);
10     os << "(" << dest.x << "," << dest.y << "," << dest.z << ")";
11     return os;
12 }
13 
14 int main()
15 {
16     cout.setf(ios_base::boolalpha);
17     if (!XMVerifyCPUSupport())
18     {
19         cout << "xna math not supported" << endl;
20         return 0;
21     }
22     XMVECTOR n = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f);
23     XMVECTOR u = XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f);
24     XMVECTOR v = XMVectorSet(-2.0f, 1.0f, -3.0f, 0.0f);
25     XMVECTOR w = XMVectorSet(0.707f, 0.707f, 0.0f, 0.0f);
26 
27     XMVECTOR a = u + v;
28     XMVECTOR b = u - v;
29     XMVECTOR c = 10.0f * u;
30     XMVECTOR L = XMVector3Length(u);
31     XMVECTOR d = XMVector3Normalize(u);
32     XMVECTOR s = XMVector3Dot(u, v);
33     XMVECTOR e = XMVector3Cross(u, v);
34 
35     XMVECTOR projW;
36     XMVECTOR perpW;
37     XMVector3ComponentsFromNormal(&projW, &perpW, w, n);
38 
39     bool equal = XMVector3Equal(projW + perpW, w) != 0;
40     bool notEqual = XMVector3NotEqual(projW + perpW, w) != 0;
41     XMVECTOR angelVec = XMVector3AngleBetweenVectors(projW, perpW);
42     float angleRadians = XMVectorGetX(angelVec);
43     float angleDegrees = XMConvertToDegrees(angleRadians);
44 
45     cout << "u                   = " << u << endl;
46     cout << "v                   = " << v << endl;
47     cout << "w                   = " << w << endl;
48     cout << "n                   = " << n << endl;
49     cout << "a = u + v           = " << a << endl;
50     cout << "b = u - v           = " << b << endl;
51     cout << "c = 10 * u          = " << c << endl;
52     cout << "d = u / ||u||       = " << d << endl;
53     cout << "e = u x v           = " << e << endl;
54     cout << "L  = ||u||          = " << L << endl;
55     cout << "s = u.v             = " << s << endl;
56     cout << "projW               = " << projW << endl;
57     cout << "perpW               = " << perpW << endl;
58     cout << "projW + perpW == w  = " << equal << endl;
59     cout << "projW + perpW != w  = " << notEqual << endl;
60     cout << "angle               = " << angleDegrees << endl;
61 
62     return 0;
63 }

 

3.

 1 #include <windows.h> // for FLOAT definition
 2 #include <xnamath.h>
 3 #include <iostream>
 4 using namespace std;
 5 
 6 int main()
 7 {
 8 cout.precision(8);
 9 
10 // Check support for SSE2 (Pentium4, AMD K8, and above).
11 if( !XMVerifyCPUSupport() )
12 {
13 cout << "xna math not supported" << endl;
14 return 0;
15 }
16 
17 XMVECTOR u = XMVectorSet(1.0f, 1.0f, 1.0f, 0.0f);
18 XMVECTOR n = XMVector3Normalize(u);
19 
20 float LU = XMVectorGetX(XMVector3Length(n));
21 
22 // Mathematically, the length should be 1.  Is it numerically?
23 cout << LU << endl;
24 if( LU == 1.0f )
25 cout << "Length 1" << endl;
26 else
27 cout << "Length not 1" << endl;
28 
29 // Raising 1 to any power should still be 1.  Is it?
30 float powLU = powf(LU, 1.0e6f);
31 cout << "LU^(10^6) = " << powLU << endl;
32 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM