如果您发现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)。 –