1. DirectXMath ライブラリのベクトル演算:
(1) ベクトル型:
コア ベクトル型は XMVECTOR で、SIMD ハードウェア レジスタにマップされます。
typedef __m128 XMVECTOR;
ここで __m128 は特殊な SIMD 型です。
XMVECTOR 型のデータは、ローカル変数とグローバル変数に対して自動的に実装される 16 バイトで整列する必要があります。
クラスのデータ メンバーには、代わりに XMFLOAT2、XMFLOAT3、および XMFLOAT4 型を使用することをお勧めします。
SIMD テクノロジの効率的な機能を最大限に活用するには、これらの型のインスタンスを XMVECTOR 型に変換する必要もあります。変換処理は、DirectXMath ライブラリのロード機能によって実現できます。逆に、DirectXMath ライブラリは、XMVECTOR 型を XMFLOATn 型に変換するためのストレージ関数も提供します。
概要:
a. ローカル変数またはグローバル変数には XMVECTOR 型を使用します。
b. クラスのデータ メンバーには、XMFLOAT2、XMFLOAT3、XMFLOAT4 型を使用します。
c. 操作前に、ロード関数を使用して XMFLOATn 型を XMVECTOR 型に変換します。
d. XMVECTOR インスタンスを使用して操作を実行します。
e. ストレージ関数を使用して、XMVECTOR 型を XMFLOATn 型に変換します。
2.ロードと保管方法:
#include <iostream>
#include <DirectXMath.h>
#include <DirectXPackedVector.h>
int main()
{
typedef __m128 XMVECTOR;
typedef const XMVECTOR FXMVECTOR;
//通过下列方法将数据从XMFLOATn类型加载到XMVECTOR类型中
//将数据从XMFLOAT2类型中加载到XMVECTOR类型
XMVECTOR XM_CALLCONV XMFLoadFloat2(const XMFLOAT2 *pSource);
//将数据从XMFLOAT3类型中加载到XMVECTOR类型
XMVECTOR XM_CALLCONV XMFLoadFloat3(const XMFLOAT3 *pSource);
//将数据从XMFLOAT4类型中加载到XMVECTOR类型
XMVECTOR XM_CALLCONV XMFLoadFloat4(const XMFLOAT4 *pSource);
//通过下列方法将数据从XMVECTOR类型加载到XMFLOATn类型中
//将数据从XMVECTOR类型中加载到XMFLOAT2类型
void XM_CALLCONV XMStoreFloat2(XMFLOAT2 *pDestination, FXMVECTOR V);
//将数据从XMVECTOR类型中加载到XMFLOAT3类型
void XM_CALLCONV XMStoreFloat3(XMFLOAT3 * pDestination, FXMVECTOR V);
//将数据从XMVECTOR类型中加载到XMFLOAT4类型
void XM_CALLCONV XMStoreFloat4(XMFLOAT4 * pDestination, FXMVECTOR V);
//从XMVECTOR实例中得到某一个向量分量或将某一向量分量转换为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);
}
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; }
};
通常の開発では、名前空間 DirectX を使用して定数データ型を作成できます。
3. パラメータ転送:
効率を向上させるために、XMVECTOR 型の値を関数のパラメータとして使用し、スタックに格納する代わりに直接 SSE/SSE2 レジスタに転送することができます。
この方法で渡される引数は、ユーザーが使用するプラットフォームとコンパイラによって異なります。したがって、コードをより用途の広いものにし、特定のプラットフォームやコンパイラの影響を受けないようにするために、XMVECTOR 型のパラメーターは、FXMVECTOR、GXMVECTOR、HXMVECTOR、および CXMVECTOR 型を使用して渡されます。
関数名をロードする前に、必ず呼び出し規約に XM_CALLCONV の注釈を付けてください。
XMVECTOR 引き渡しパラメーターの規則:
a. 最初の 3 つの XMVECTOR パラメーターは型 FXMVECTOR を使用する必要があります;
b. 4 番目の XMVECTOR パラメーターは型 GXMVECTOR を使用する必要があります; c
. 5 番目と 6 番目の XMVECTOR パラメーターは型 HXMVECTOR を使用する必要があります;
d. 残りの XMVECTOR パラメーターは型を使用する必要がありますNote: Do not use XM_CALLCONV for constructors . __vectorcall の制限により、C++ コンストラクターには GXMVECTOR または HXMVECTOR を使用しないことをお勧めします
。最初の 3 つの XMVECTOR 値には FXMVECTOR を使用し、残りの値には CXMVECTOR を使用します。XMVECTOR 型のパラメーターの間に、XMVECTOR 型以外の他のパラメーターを混在させることもできます。現時点では、XMVECTOR パラメーターの規則が引き続き適用され、XMVECTOR パラメーターの数をカウントするときに、他の種類のパラメーターは無視されます。
XMVECTOR パラメーターを渡す規則は、「入力」パラメーターにのみ適用されます。「出力」XMVECTOR パラメーター (つまり、XMVECTOR& または XMVECTOR*) は SSE/SSE2 レジスターを占有しないため、非 XMVECTOR タイプのパラメーターと同じように扱われます。