如果您發現DirectXMath對您的口味有點過於冗長,請在DirectX Tool Kit中查看SimpleMath。尤其是Vector2
類:
struct Vector2 : public XMFLOAT2
{
Vector2() : XMFLOAT2(0.f, 0.f) {}
explicit Vector2(float x) : XMFLOAT2(x, x) {}
Vector2(float _x, float _y) : XMFLOAT2(_x, _y) {}
explicit Vector2(_In_reads_(2) const float *pArray) : XMFLOAT2(pArray) {}
Vector2(FXMVECTOR V) { XMStoreFloat2(this, V); }
Vector2(const XMFLOAT2& V) { this->x = V.x; this->y = V.y; }
explicit Vector2(const XMVECTORF32& F) { this->x = F.f[0]; this->y = F.f[1]; }
operator XMVECTOR() const { return XMLoadFloat2(this); }
// Comparison operators
bool operator == (const Vector2& V) const;
bool operator != (const Vector2& V) const;
// Assignment operators
Vector2& operator= (const Vector2& V) { x = V.x; y = V.y; return *this; }
Vector2& operator= (const XMFLOAT2& V) { x = V.x; y = V.y; return *this; }
Vector2& operator= (const XMVECTORF32& F) { x = F.f[0]; y = F.f[1]; return *this; }
Vector2& operator+= (const Vector2& V);
Vector2& operator-= (const Vector2& V);
Vector2& operator*= (const Vector2& V);
Vector2& operator*= (float S);
Vector2& operator/= (float S);
// Unary operators
Vector2 operator+() const { return *this; }
Vector2 operator-() const { return Vector2(-x, -y); }
// Vector operations
bool InBounds(const Vector2& Bounds) const;
float Length() const;
float LengthSquared() const;
float Dot(const Vector2& V) const;
void Cross(const Vector2& V, Vector2& result) const;
Vector2 Cross(const Vector2& V) const;
void Normalize();
void Normalize(Vector2& result) const;
void Clamp(const Vector2& vmin, const Vector2& vmax);
void Clamp(const Vector2& vmin, const Vector2& vmax, Vector2& result) const;
// Static functions
static float Distance(const Vector2& v1, const Vector2& v2);
static float DistanceSquared(const Vector2& v1, const Vector2& v2);
static void Min(const Vector2& v1, const Vector2& v2, Vector2& result);
static Vector2 Min(const Vector2& v1, const Vector2& v2);
static void Max(const Vector2& v1, const Vector2& v2, Vector2& result);
static Vector2 Max(const Vector2& v1, const Vector2& v2);
static void Lerp(const Vector2& v1, const Vector2& v2, float t, Vector2& result);
static Vector2 Lerp(const Vector2& v1, const Vector2& v2, float t);
static void SmoothStep(const Vector2& v1, const Vector2& v2, float t, Vector2& result);
static Vector2 SmoothStep(const Vector2& v1, const Vector2& v2, float t);
static void Barycentric(const Vector2& v1, const Vector2& v2, const Vector2& v3, float f, float g, Vector2& result);
static Vector2 Barycentric(const Vector2& v1, const Vector2& v2, const Vector2& v3, float f, float g);
static void CatmullRom(const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float t, Vector2& result);
static Vector2 CatmullRom(const Vector2& v1, const Vector2& v2, const Vector2& v3, const Vector2& v4, float t);
static void Hermite(const Vector2& v1, const Vector2& t1, const Vector2& v2, const Vector2& t2, float t, Vector2& result);
static Vector2 Hermite(const Vector2& v1, const Vector2& t1, const Vector2& v2, const Vector2& t2, float t);
static void Reflect(const Vector2& ivec, const Vector2& nvec, Vector2& result);
static Vector2 Reflect(const Vector2& ivec, const Vector2& nvec);
static void Refract(const Vector2& ivec, const Vector2& nvec, float refractionIndex, Vector2& result);
static Vector2 Refract(const Vector2& ivec, const Vector2& nvec, float refractionIndex);
static void Transform(const Vector2& v, const Quaternion& quat, Vector2& result);
static Vector2 Transform(const Vector2& v, const Quaternion& quat);
static void Transform(const Vector2& v, const Matrix& m, Vector2& result);
static Vector2 Transform(const Vector2& v, const Matrix& m);
static void Transform(_In_reads_(count) const Vector2* varray, size_t count, const Matrix& m, _Out_writes_(count) Vector2* resultArray);
static void Transform(const Vector2& v, const Matrix& m, Vector4& result);
static void Transform(_In_reads_(count) const Vector2* varray, size_t count, const Matrix& m, _Out_writes_(count) Vector4* resultArray);
static void TransformNormal(const Vector2& v, const Matrix& m, Vector2& result);
static Vector2 TransformNormal(const Vector2& v, const Matrix& m);
static void TransformNormal(_In_reads_(count) const Vector2* varray, size_t count, const Matrix& m, _Out_writes_(count) Vector2* resultArray);
// Constants
static const Vector2 Zero;
static const Vector2 One;
static const Vector2 UnitX;
static const Vector2 UnitY;
};
// Binary operators
Vector2 operator+ (const Vector2& V1, const Vector2& V2);
Vector2 operator- (const Vector2& V1, const Vector2& V2);
Vector2 operator* (const Vector2& V1, const Vector2& V2);
Vector2 operator* (const Vector2& V, float S);
Vector2 operator/ (const Vector2& V1, const Vector2& V2);
Vector2 operator* (float S, const Vector2& V);
的主要原因DirectXMath是如此冗長首先是要當「溢出到內存」,因爲這往往的性能產生負面影響很清楚地向程序員SIMD代碼。當我從XNAMath轉移到DirectXMath時,我曾考慮過添加類似於「SimpleMath」的隱式轉換,但我想確保任何這樣的「C++魔術」都是選擇加入的,並且對於性能敏感開發商。 SimpleMath也有點像訓練輪,可以更輕鬆地移植現有的不支持對齊的代碼,並隨着時間的推移將其變爲更友好的SIMD。
SimpleMath(和你的包裝器)的實際性能問題是,每個函數的實現都必須做一個明確的加載存儲其他相當少量的SIMD。理想情況下,優化後的代碼將全部合併,但在調試代碼中,它們始終存在。對於SIMD的任何實際性能優勢,您希望在每個加載對之間進行長時間的寄存器內SIMD操作。
另一個含義是傳遞包裝如Vector2
或Vector2F
的參數決不會特別有效。 XMVECTOR
是__m128
的類型定義而不是結構的全部原因,FXMVECTOR
,GXMVECTOR
,HXMVECTOR
和CXMVECTOR
的存在是嘗試優化所有可能的調用約定場景,並在最佳情況下獲取註冊表內傳遞行爲(如果事情不內聯)。見MSDN。真的,Vector2
可以做的最好的是始終通過它const&
,以儘量減少臨時和堆棧副本。
我想你會發現在優化的代碼中,性能損失將爲零。 –
如果沒有使用返回的值,編譯器極有可能優化'return * this;'。這是編譯器很清楚的一個常見習慣用法。 –
您有兩個隱式轉換:1)從XMVECTOR和2)到XMVECTOR。這是模棱兩可的可能性很大。不要這樣做(不要使用Vector2F)。 –