回到D3DXMath,我们有能力乘以,加或减偶数除法矢量类型,即D3DXVECTOR2,D3DXVECTOR3,D3DXVECTOR4结构...... 现在在DirectXMath版本中我们有XMFLOAT2,XMFLOAT3,XMFLOAT4和XMVECTOR。如果我想做任何数学运算,我必须从XMFLOAT转换为XMVECTOR,无论是哪种方式,Visual Studio都会抛出错误“没有 用户定义的转换“。为什么会这样?实际上,在新版本(Windows 8.1,10)的DirectX数学库中,向量操作稍有改变。我做错了什么........... ?!
P.S。对于矩阵来说还有另外一个问题,但是现在我们只讨论向量。这些变化正在推动第三方开发人员创建他们自己的数学库,他们已经完成了...... :)
答案 0 :(得分:1)
实际上,MSDN上的DirectXMath Programmer's Guide详细解释了这一点:
XMVECTOR和XMMATRIX类型是DirectXMath库的工作马。每个操作都会消耗或生成这些类型的数据。使用它们是使用该库的关键。但是,由于DirectXMath使用SIMD指令集,因此这些数据类型受到许多限制。如果要充分利用DirectXMath函数,了解这些限制至关重要。
您应该将XMVECTOR视为SIMD硬件寄存器的代理,并将XMMATRIX视为四个SIMD硬件寄存器的逻辑分组的代理。注释这些类型表示它们需要16字节对齐才能正常工作。当它们用作局部变量时,编译器会自动将它们正确地放在堆栈上,或者当它们用作全局变量时,将它们放在数据段中。通过适当的约定,它们也可以作为参数安全地传递给函数(有关详细信息,请参阅调用约定)。
然而,堆中的分配更复杂。因此,每当您使用XMVECTOR或XMMATRIX作为要从堆分配的类或结构的成员时,您都需要小心。在Windows x64上,所有堆分配都是16字节对齐的,但对于Windows x86,它们只是8字节对齐。可以选择从堆中分配16字节对齐的结构(请参阅正确对齐分配)。对于C ++程序,您可以使用operator new / delete / new [] / delete []重载(全局或特定于类)来强制执行最佳对齐(如果需要)。
但是,通常更容易和更紧凑,以避免直接在类或结构中使用XMVECTOR或XMMATRIX。相反,请使用XMFLOAT3,XMFLOAT4,XMFLOAT4X3,XMFLOAT4X4等作为结构的成员。此外,您可以使用向量加载和向量存储功能将数据有效地移动到XMVECTOR或XMMATRIX局部变量中,执行计算并存储结果。还有流函数(XMVector3TransformStream,XMVector4TransformStream等)可直接在这些数据类型的数组上高效运行。
根据设计,DirectXMath鼓励您编写高效且易于使用SIMD的代码。加载或存储向量是昂贵的,因此您应该尝试在“流”模型中工作,在该模型中加载数据,在寄存器中使用它,然后编写结果。
也就是说,我完全认为对于刚接触SIMD数学或DirectX的人来说,这种用法有点复杂,即使对于专业开发人员来说也有点冗长。这就是为什么我还为DirectXMath写了SimpleMath包装器,这使得它更像是你正在寻找使用XNA Game Studio的经典数学库,如Vector2
,Vector3
,Matrix
“C ++魔法”的类可以覆盖所有显式负载和商店。 SimpleMath类型与DirectXMath完全互操作,因此您可以根据需要进行混合和匹配。
同时查看this blog post和GitHub。
DirectXMath故意是一个'内联'库,意思是在优化的代码中,你不应该传递很多变量而只是计算你的大函数里面的值。 deprecated
D3DX9
,D3DX10
,D3DX11
库中的D3DXMath库更加老旧,它依赖于函数指针表,并且受到调用约定的严重性能限制开销。这些当然代表了不同的工程权衡。 D3DXMath能够在运行时对专用处理器代码路径进行更多替换,但是通过调用约定和间接开销来支付这种灵活性。另一方面,DirectXMath假定SSE / SSE2(或Xbox One上的AVX)的SIMD基线,因此您无需运行时检测或间接,而是积极地利用内联。