一個向量表明的是一個擁有大小和方向的量。相似力(擁有力的大小和方向)、位移(移動的方向和距離)、速度(速度的大小和方向)等,例以下圖(圖 1.1):
繪製向量的位置和向量自己無關,因此當且僅當兩個向量的大小和方形相等時,兩個向量相等;因此上圖中a和b中的向量u和向量v相等。ios
咱們如今能夠定義各類向量幾何運算來解決對應的問題,可是由於計算機沒法直接經過幾何學計算向量,因此咱們須要用數字來描述向量;
考慮到下圖中的狀況(圖1.4),同一個向量在不一樣座標系中會有不一樣的座標變現:
在計算機3D圖形學中咱們須要使用多個座標系,咱們要知道當前在哪個座標系下,而且熟悉座標系之間的轉換。windows
Direct3D 使用的是左手座標系:若是你使用你的左手指向 X軸正方向,而後向Y軸正方向彎曲你的手指,此時你的大拇指指向的就是Z軸正方向,如圖1.5 所示(右手座標系相似,只不過替換爲右手)
markdown
咱們也能夠在座標系中使用繪製的方法來表示:
函數
向量長度計算公式:
單位向量計算公式:
爲了證實單位向量計算公式,咱們能夠計算單位向量的長度:
性能
向量的點積是一種結果爲數量值的乘法形式,其定義和計算公式爲:
向量的點積的定義並無提出明顯的幾何定義,利用餘弦定理,咱們能夠找到幾何關係:
如圖1.9,θ是向量v和u的夾角,再根據上面的公式,咱們能夠得出向量點積的一些有用的幾何屬性:學習
如圖1.10
給出向量v和單位向量n,使用點積公式求出向量p:
向量p也能夠表示爲:p=projn(v)p = proj_n(v)p=projn(v),那麼向量w = v - p
因此向量v就能夠分解爲:v=p+w=projn(v)+perpn(v)v = p + w = proj_n(v) + perp_n(v)v=p+w=projn(v)+perpn(v)
若是向量n不是單位向量,那麼能夠提早把n標準化:
優化
當一組向量相互之間都垂直,而且都是單位向量時,咱們稱他們爲標準正交。在3D計算機圖形學中,咱們剛開始可能會有一組標準正交的向量,可是因爲變量精度的問題,這些向量會在進行一系列計算後開始變得相互不垂直。因此咱們的目標就是主要考慮在3D和2D狀況下手動正交化。
咱們先從2D開始,假設擁有向量v0v_0v0和v1v_1v1,咱們要將他們正交化爲標準正交集w0w_0w0和w1w_1w1;首先咱們使w0=v0w_0=v_0w0=v0,而後修改v1v_1v1讓它垂直於w0w_0w0:
在3D狀況下,咱們繼續而後修改v2v_2v2讓它同時垂直於w0w_0w0和w1w_1w1:
最後一步是標準化每個向量爲單位向量。
這套正交化流程咱們統一稱之爲 施密特正交化(Gram-Schmidt Orthogonalization)。
this
兩個向量的叉積(叉積不支持2D)結果爲另一個同時垂直於他倆的向量,叉積的運算公式爲:
叉積不支持交換律,其交換後的結果是相反的,即:u * v = - v * u。atom
在2D狀況下,若是已知u=(ux,uy)u = (u_x, u_y)u=(ux,uy),找出垂直於u的向量v=(−uy,ux)v = (-u_y, u_x)v=(−uy,ux),該公式的證實以下:
spa
使用叉積正交化會形成一些偏差
點在3D圖形學中要來表示位置,在座標系中,一個向量能夠表示一個位置。
一方面,咱們對向量的運算不能應用到點上(好比兩個點相加是沒有意義的);另外一方面,咱們能夠把這些運算擴展到點上。
Direct Math是Direct3D應用中的一個數學庫,而且已經內置到了Window 8以上的操做系統。
該數學庫使用 SSE2(Streaming SIMD Extensions 2) 系統指令,支持128位的 SIMD(single instruction multiple data) 寄存器。SIMD 指令能夠在一條指令中運算4個32位的浮點數和整數。這對於向量的計算很是有用。
好比作4D向量的相加,咱們不須要使用4條標量相加指令,而是1條SIMD指令便可,對於2D和3D向量也可使用SIMD,咱們能夠無視不使用的座標系。
若是想要了解DirectX Math的所有細節,推薦閱讀DirectX Math的在線文檔;
若是想要知道SIMD向量庫如何優化開發,或者瞭解它爲什麼如此設計,推薦閱讀文章:Designing Fast Cross-Platform SIMD Vector Libraries by [Oliveira2010]。
使用DirectX Math時,須要的全部頭文件:
#include <DirectXMath.h> // namespace: DirectX DirectX 數學庫 #include <DirectXPackedVector.h> // namespace: DirectX::PackedVector 一些額外附加數據類型
對於X86系統,須要開啓SSE2(Project Properties > Configuration Properties > C/C++ > Code Generation > Enable Enhanced Instruction Set);
對於全部系統,還須要開啓快速浮點數模式**(Project Properties > Configuration Properties > C/C++ > Code Generation > Floating Point Model**);
對於64位系統不須要開啓SSE2,由於全部64位CPU都支持SSE2(http://en.wikipedia.org/wiki/SSE2)。
DirectX Math 的核心類型是映射到SIMD硬件寄存器的 XMVECTOR,它是一個128位,可使用單個指令計算4個32位浮點數的類型。對於X86和64位系統中,它的定義以下:
typedef __m128 XMVECTOR;
__m128是SIMD專用的類型。當咱們計算的時候,向量必須聲明位該類型才能利用SIMD的優勢。
XMVECTOR的局部和所有變量會自動被16位對其;對於類的成員變量,使用XMFLOAT2 (2D),XMFLOAT3 (3D),和XMFLOAT4 (4D) 來替換;
struct XMFLOAT2 { float x; float y; XMFLOAT2() {} XMFLOAT2(float _x, float _y) : x(_x), y(_y) {} explicit XMFLOAT2(_In_reads_(2) const float *pArray) : x(pArray[0]), y(pArray[1]) {} XMFLOAT2& operator= (const XMFLOAT2& Float2) { x = Float2.x; y = Float2.y; return *this; } }; struct XMFLOAT3 { float x; float y; float z; XMFLOAT3() {} XMFLOAT3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} explicit XMFLOAT3(_In_reads_(3) const float *pArray) : x(pArray[0]), y(pArray[1]), z(pArray[2]) {} XMFLOAT3& operator= (const XMFLOAT3& Float3) { x = Float3.x; y = Float3.y; z = Float3.z; return *this; } }; struct XMFLOAT4 { float x; float y; float z; float w; XMFLOAT4() {} XMFLOAT4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) {} explicit XMFLOAT4(_In_reads_(4) const float *pArray) : x(pArray[0]), y(pArray[1]), z(pArray[2]), w(pArray[3]) {} XMFLOAT4& operator= (const XMFLOAT4& Float4) { x = Float4.x; y = Float4.y; z = Float4.z; w = Float4.w; return *this; } };
若是直接利用這些類型進行計算,就沒法利用SIMD的優勢,因此咱們須要進行類型的轉換;DirectX Math中提供了Loading函數能夠將XMFLOATn類型數據加載到XMVECTOR;Storage函數能夠將XMVECTOR類型數據保存到XMFLOATn。
總結以下:
將數據從XMFLOATn加載到XMVECTOR的Loading方法以下:
// Loads XMFLOAT2 into XMVECTOR XMVECTOR XM_CALLCONV XMLoadFloat2(const XMFLOAT2 *pSource); // Loads XMFLOAT3 into XMVECTOR XMVECTOR XM_CALLCONV XMLoadFloat3(const XMFLOAT3 *pSource); // Loads XMFLOAT4 into XMVECTOR XMVECTOR XM_CALLCONV XMLoadFloat4(const XMFLOAT4 *pSource);
將數據從XMVECTOR保存到XMFLOATn的Storage方法以下:
// Loads XMVECTOR into XMFLOAT2 void XM_CALLCONV XMStoreFloat2(XMFLOAT2 *pDestination, FXMVECTOR V); // Loads XMVECTOR into XMFLOAT3 void XM_CALLCONV XMStoreFloat3(XMFLOAT3 *pDestination, FXMVECTOR V); // Loads XMVECTOR into XMFLOAT4 void XM_CALLCONV XMStoreFloat4(XMFLOAT4 *pDestination, FXMVECTOR V);
有時咱們只想修改或者獲取XMVECTOR中的某一個值,可使用下面的函數很容易實現:
float XM_CALLCONV XMVectorGetX(FXMVECTOR V); float XM_CALLCONV XMVectorGetY(FXMVECTOR V); float XM_CALLCONV XMVectorGetZ(FXMVECTOR V); float XM_CALLCONV XMVectorGetW(FXMVECTOR V); XMVECTOR XM_CALLCONV XMVectorSetX(FXMVECTOR V, float x); XMVECTOR XM_CALLCONV XMVectorSetY(FXMVECTOR V, float y); XMVECTOR XM_CALLCONV XMVectorSetZ(FXMVECTOR V, float z); XMVECTOR XM_CALLCONV XMVectorSetW(FXMVECTOR V, float w);
爲了優化性能爲目的,XMVECTOR能夠做爲函數參數直接傳遞到SSE/SSE2寄存器中(而不是堆棧內存),參數傳遞的數量依賴於平臺(例如:32/64位 Windows,Windows RT)和編譯器。因此根據不一樣平臺/編譯器,咱們使用FXMVECTOR,GXMVECTOR,HXMVECTOR 和 CXMVECTOR類型來傳遞XMVECTOR參數;此外,在函數名前要指明調用註釋XM_CALLCONV
XMVECTOR類型參數傳遞規則以下:
在32爲Windows下,支持__fastcall調用約定和支持更新的__vectorcall調用約定編譯中,參數定義以下:
// 32-bit Windows __fastcall passes first 3 XMVECTOR arguments // via registers, the remaining on the stack. typedef const XMVECTOR FXMVECTOR; typedef const XMVECTOR& GXMVECTOR; typedef const XMVECTOR& HXMVECTOR; typedef const XMVECTOR& CXMVECTOR; // 32-bit Windows __vectorcall passes first 6 XMVECTOR arguments // via registers, the remaining on the stack. typedef const XMVECTOR FXMVECTOR; typedef const XMVECTOR GXMVECTOR; typedef const XMVECTOR HXMVECTOR; typedef const XMVECTOR& CXMVECTOR;
想了解在其餘平臺定義的更多細節,能夠閱讀DirectX Math的文檔,「Library Internals」 下的 「Calling Conventions」 ;
在構造函數中,這些規則是例外:文檔推薦前三個參數使用FXMVECTOR,其餘參數使用CXMVECTOR,而且不要爲構造函數添加XM_CALLCONV;
inline XMMATRIX XM_CALLCONV XMMatrixTransformation( FXMVECTOR ScalingOrigin, FXMVECTOR ScalingOrientationQuaternion, . FXMVECTOR Scaling, GXMVECTOR RotationOrigin, HXMVECTOR RotationQuaternion, HXMVECTOR Translation);
函數調用時也能夠添加非XMVECTOR類型參數,XMVECTOR參數定義規則相同,非XMVECTOR類型參數不計數:
inline XMMATRIX XM_CALLCONV XMMatrixTransformation2D( FXMVECTOR ScalingOrigin, float ScalingOrientation, FXMVECTOR Scaling, FXMVECTOR RotationOrigin, float Rotation, GXMVECTOR Translation);
這些規則只使用於輸入參數,輸出參數不使用SSE/SSE2寄存器,因此會被對待爲和非XMVECTOR類型參數同樣。
常量向量的實例須要使用XMVECTORF32類型,下面是一些在DirectX SDK裏CascadedShadowMaps11 Demo 下的例子:
static const XMVECTORF32 g_vHalfVector = { 0.5f, 0.5f, 0.5f, 0.5f }; static const XMVECTORF32 g_vZero = { 0.0f, 0.0f, 0.0f, 0.0f }; XMVECTORF32 vRightTop = { vViewFrust.RightSlope, vViewFrust.TopSlope, 1.0f,1.0f }; XMVECTORF32 vLeftBottom = { vViewFrust.LeftSlope, vViewFrust.BottomSlope, 1.0f,1.0f };
其實全部相似的初始化操做均可以使用XMVECTORF32類型,它是一個16位對齊並帶有XMVECTOR轉換的結構體,它的定義以下:
// Conversion types for constants __declspec(align(16)) struct XMVECTORF32 { union { float f[4]; XMVECTOR v; }; inline operator XMVECTOR() const { return v; } inline operator const float*() const { return f; } #if !defined(_XM_NO_INTRINSICS_) && defined(_XM_SSE_INTRINSICS_) inline operator __m128i() const { return _mm_castps_si128(v); } inline operator __m128d() const { return _mm_castps_pd(v); } #endif };
你也可使用XMVECTORU32建立XMVECTOR整形常量:
static const XMVECTORU32 vGrabY = { 0x00000000,0xFFFFFFFF,0x00000000,0x00000000 };
XMVECTOR有幾個重載運算符來計算向量的加減和量乘法:
XMVECTOR XM_CALLCONV operator+ (FXMVECTOR V); XMVECTOR XM_CALLCONV operator- (FXMVECTOR V); XMVECTOR& XM_CALLCONV operator+= (XMVECTOR& V1, FXMVECTOR V2); XMVECTOR& XM_CALLCONV operator-= (XMVECTOR& V1, FXMVECTOR V2); XMVECTOR& XM_CALLCONV operator*= (XMVECTOR& V1, FXMVECTOR V2); XMVECTOR& XM_CALLCONV operator/= (XMVECTOR& V1, FXMVECTOR V2); XMVECTOR& operator*= (XMVECTOR& V, float S); XMVECTOR& operator/= (XMVECTOR& V, float S); XMVECTOR XM_CALLCONV operator+ (FXMVECTOR V1, FXMVECTOR V2); XMVECTOR XM_CALLCONV operator- (FXMVECTOR V1, FXMVECTOR V2); XMVECTOR XM_CALLCONV operator* (FXMVECTOR V1, FXMVECTOR V2); XMVECTOR XM_CALLCONV operator/ (FXMVECTOR V1, FXMVECTOR V2); XMVECTOR XM_CALLCONV operator* (FXMVECTOR V, float S); XMVECTOR XM_CALLCONV operator* (float S, FXMVECTOR V); XMVECTOR XM_CALLCONV operator/ (FXMVECTOR V, float S);
DirectX Math定義了一些有用的常量來近似的表現和 π 相關的值:
const float XM_PI = 3.141592654f; const float XM_2PI = 6.283185307f; const float XM_1DIVPI = 0.318309886f; const float XM_1DIV2PI = 0.159154943f; const float XM_PIDIV2 = 1.570796327f; const float XM_PIDIV4 = 0.785398163f;
另外,還定義了下面的內斂函數用以在轉換角度和弧度:
inline float XMConvertToRadians(float fDegrees) { return fDegrees * (XM_PI / 180.0f); } inline float XMConvertToDegrees(float fRadians) { return fRadians * (180.0f / XM_PI); }
還定義了min/max函數:
template<class T> inline T XMMin(T a, T b) { return (a < b) ? a : b; } template<class T> inline T XMMax(T a, T b) { return (a > b) ? a : b; }
DirectX Math提供了下面函數用來修改XMVECTOR的值:
// Returns the zero vector 0 XMVECTOR XM_CALLCONV XMVectorZero(); // Returns the vector (1, 1, 1, 1) XMVECTOR XM_CALLCONV XMVectorSplatOne(); // Returns the vector (x, y, z, w) XMVECTOR XM_CALLCONV XMVectorSet(float x, float y, float z, float w); // Returns the vector (s, s, s, s) XMVECTOR XM_CALLCONV XMVectorReplicate(float Value); // Returns the vector (vx, vx, vx, vx) XMVECTOR XM_CALLCONV XMVectorSplatX(FXMVECTOR V); // Returns the vector (vy, vy, vy, vy) XMVECTOR XM_CALLCONV XMVectorSplatY(FXMVECTOR V); // Returns the vector (vz, vz, vz, vz) XMVECTOR XM_CALLCONV XMVectorSplatZ(FXMVECTOR V);
下面的代碼解釋了大部分函數的使用:
#include <windows.h> // for XMVerifyCPUSupport #include <DirectXMath.h> #include <DirectXPackedVector.h> using namespace std; using namespace DirectX; using namespace DirectX::PackedVector; // Overload the "<<" operators so that we can use cout to // output XMVECTOR objects. ostream& XM_CALLCONV operator<<(ostream& os, FXMVECTOR v) { XMFLOAT3 dest; XMStoreFloat3(&dest, v); os << "(" << dest.x << ", " << dest.y << ", " << dest.z << ")"; return os; } int main() { cout.setf(ios_base::boolalpha); // Check support for SSE2 (Pentium4, AMD K8, and above). if (!XMVerifyCPUSupport()) { cout << "directx math not supported" << endl; return 0; } XMVECTOR p = XMVectorZero(); XMVECTOR q = XMVectorSplatOne(); XMVECTOR u = XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f); XMVECTOR v = XMVectorReplicate(-2.0f); XMVECTOR w = XMVectorSplatZ(u); cout << "p = " << p << endl; cout << "q = " << q << endl; cout << "u = " << u << endl; cout << "v = " << v << endl; cout << "w = " << w << endl; return 0; }
DirectX Math提供了下面的函數來處理各類向量運算,這裏介紹3D版本,2D和4D版本於3D相似:
(有些能夠直接返回值的函數依然返回的是XMVECTOR,好比向量的點積,這樣作是爲了儘量減小SIMD和其它值的混合,從而提升性能)
XMVECTOR XM_CALLCONV XMVector3Length( // Returns ||v|| FXMVECTOR V); // Input v XMVECTOR XM_CALLCONV XMVector3LengthSq( // Returns ||v||2 FXMVECTOR V); // Input v XMVECTOR XM_CALLCONV XMVector3Dot( // Returns v1·v2 FXMVECTOR V1, // Input v1 FXMVECTOR V2); // Input v2 XMVECTOR XM_CALLCONV XMVector3Cross( // Returns v1 × v2 FXMVECTOR V1, // Input v1 FXMVECTOR V2); // Input v2 XMVECTOR XM_CALLCONV XMVector3Normalize( // Returns v/||v|| FXMVECTOR V); // Input v XMVECTOR XM_CALLCONV XMVector3Orthogonal( // Returns a vector orthogonal to v FXMVECTOR V); // Input v XMVECTOR XM_CALLCONV XMVector3AngleBetweenVectors( // Returns the angle between v1 and v2 FXMVECTOR V1, // Input v1 FXMVECTOR V2); // Input v2 void XM_CALLCONV XMVector3ComponentsFromNormal( XMVECTOR* pParallel, // Returns projn(v) XMVECTOR* pPerpendicular, // Returns perpn(v) FXMVECTOR V, // Input v FXMVECTOR Normal); // Input n bool XM_CALLCONV XMVector3Equal( // Returns v1 = v2 FXMVECTOR V1, // Input v1 FXMVECTOR V2); // Input v2 bool XM_CALLCONV XMVector3NotEqual( // Returns v1 ≠ v2 FXMVECTOR V1, // Input v1 FXMVECTOR V2); // Input v2
下面的示例程序展現了大部分函數和一些重載雲算符的用法:
#include <windows.h> // for XMVerifyCPUSupport #include <DirectXMath.h> #include <DirectXPackedVector.h> #include <iostream> using namespace std; using namespace DirectX; using namespace DirectX::PackedVector; // Overload the "<<" operators so that we can use cout to // output XMVECTOR objects. ostream& XM_CALLCONV operator<<(ostream& os, FXMVECTOR v) { XMFLOAT3 dest; XMStoreFloat3(&dest, v); os << "(" << dest.x << ", " << dest.y << ", " << dest.z << ")"; return os; } int main() { cout.setf(ios_base::boolalpha); // Check support for SSE2 (Pentium4, AMD K8, and above). if (!XMVerifyCPUSupport()) { cout << "directx math not supported" << endl; return 0; } XMVECTOR n = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f); XMVECTOR u = XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f); XMVECTOR v = XMVectorSet(-2.0f, 1.0f, -3.0f, 0.0f); XMVECTOR w = XMVectorSet(0.707f, 0.707f, 0.0f, 0.0f); // Vector addition: XMVECTOR operator + XMVECTOR a = u + v; // Vector subtraction: XMVECTOR operator - XMVECTOR b = u - v; // Scalar multiplication: XMVECTOR operator * XMVECTOR c = 10.0f*u; // ||u|| XMVECTOR L = XMVector3Length(u); // d = u / ||u|| XMVECTOR d = XMVector3Normalize(u); // s = u dot v XMVECTOR s = XMVector3Dot(u, v); // e = u x v XMVECTOR e = XMVector3Cross(u, v); // Find proj_n(w) and perp_n(w) XMVECTOR projW; XMVECTOR perpW; XMVector3ComponentsFromNormal(&projW, &perpW, w, n); // Does projW + perpW == w? bool equal = XMVector3Equal(projW + perpW, w) != 0; bool notEqual = XMVector3NotEqual(projW + perpW, w) != 0; // The angle between projW and perpW should be 90 degrees. XMVECTOR angleVec = XMVector3AngleBetweenVectors(projW, perpW); float angleRadians = XMVectorGetX(angleVec); float angleDegrees = XMConvertToDegrees(angleRadians); cout << "u = " << u << endl; cout << "v = " << v << endl; cout << "w = " << w << endl; cout << "n = " << n << endl; cout << "a = u + v = " << a << endl; cout << "b = u - v = " << b << endl; cout << "c = 10 * u = " << c << endl; cout << "d = u / ||u|| = " << d << endl; cout << "e = u x v = " << e << endl; cout << "L = ||u|| = " << L << endl; cout << "s = u.v = " << s << endl; cout << "projW = " << projW << endl; cout << "perpW = " << perpW << endl; cout << "projW + perpW == w = " << equal << endl; cout << "projW + perpW != w = " << notEqual << endl; cout << "angle = " << angleDegrees << endl; return 0; }
DirectX Math還包含一些求近似值的函數,它們準確度較低,可是更快;若是你願意犧牲準確度去追求速度,能夠考慮使用它們,下面是其中的2個例子:
XMVECTOR XM_CALLCONV XMVector3LengthEst( // Returns estimated ||v|| FXMVECTOR V); // Input v XMVECTOR XM_CALLCONV XMVector3NormalizeEst( // Returns estimated v/||v|| FXMVECTOR V); // Input v
DirectX Math庫提供了一個函數XMVector3NearEqual用以判斷兩個向量在可容許的偏差下是否相等:
// Returns // abs(U.x – V.x) <= Epsilon.x && // abs(U.y – V.y) <= Epsilon.y && // abs(U.z – V.z) <= Epsilon.z XMFINLINE bool XM_CALLCONV XMVector3NearEqual( FXMVECTOR U, FXMVECTOR V, FXMVECTOR Epsilon);
XMVECTOR XM_CALLCONV XMVector3Length(FXMVECTOR V); XMVECTOR XM_CALLCONV XMVector3LengthSq(FXMVECTOR V); XMVECTOR XM_CALLCONV XMVector3Dot(FXMVECTOR V1, FXMVECTOR V2); XMVECTOR XM_CALLCONV XMVector3Cross(FXMVECTOR V1, FXMVECTOR V2); XMVECTOR XM_CALLCONV XMVector3Normalize(FXMVECTOR V);
#include <windows.h> // for XMVerifyCPUSupport #include <DirectXMath.h> #include <DirectXPackedVector.h> #include <iostream> using namespace std; using namespace DirectX; using namespace DirectX::PackedVector; // Overload the "<<" operators so that we can use cout to // output XMVECTOR objects. ostream& XM_CALLCONV operator<<(ostream& os, FXMVECTOR v) { XMFLOAT4 dest; XMStoreFloat4(&dest, v); os << "(" << dest.x << ", " << dest.y << ", " << dest.z << ", " << dest.w << ")"; return os; } int main() { cout.setf(ios_base::boolalpha); // Check support for SSE2 (Pentium4, AMD K8, and above). if (!XMVerifyCPUSupport()) { cout << "directx math not supported" << endl; return 0; } XMVECTOR p = XMVectorSet(2.0f, 2.0f, 1.0f, 0.0f); XMVECTOR q = XMVectorSet(2.0f, -0.5f, 0.5f, 0.1f); XMVECTOR u = XMVectorSet(1.0f, 2.0f, 4.0f, 8.0f); XMVECTOR v = XMVectorSet(-2.0f, 1.0f, -3.0f, 2.5f); XMVECTOR w = XMVectorSet(0.0f, XM_PIDIV4, XM_PIDIV2, XM_PI); cout << "XMVectorAbs(v) = " << XMVectorAbs(v) << endl; // 對每個份量求絕對值 cout << "XMVectorCos(w) = " << XMVectorCos(w) << endl; // 對每個份量求arccosine值 cout << "XMVectorLog(u) = " << XMVectorLog(u) << endl; // 對每個份量求log2的值 cout << "XMVectorExp(p) = " << XMVectorExp(p) << endl; // 對每個份量乘2的值 cout << "XMVectorPow(u, p) = " << XMVectorPow(u, p) << endl; // 對u的每個份量作p對應份量的平方 cout << "XMVectorSqrt(u) = " << XMVectorSqrt(u) << endl; // 對每個份量開平方 cout << "XMVectorSwizzle(u, 2, 2, 1, 3) = " << XMVectorSwizzle(u, 2, 2, 1, 3) << endl; // XMVectorSwizzle 沒看懂 - -! cout << "XMVectorSwizzle(u, 2, 1, 0, 3) = " << XMVectorSwizzle(u, 2, 1, 0, 3) << endl; // XMVectorSwizzle 沒看懂 - -! cout << "XMVectorMultiply(u, v) = " << XMVectorMultiply(u, v) << endl; // 對每個對應份量相乘 cout << "XMVectorSaturate(q) = " << XMVectorSaturate(q) << endl; // 把每個份量修改成0~1的值 cout << "XMVectorMin(p, v = " << XMVectorMin(p, v) << endl; // 對每個份量求 最小/最大 的值 cout << "XMVectorMax(p, v) = " << XMVectorMax(p, v) << endl; // 對每個份量求 最小/最大 的值 system("pause"); return 0; }