访问 CXMMatrix 的浮点数 - () 运算符不起作用

Access floats of CXMMatrix - () operator not working

我正在尝试在 directX11 上使用 "Frank Luna" 书中的更新代码,其中我使用 VS2017 和 WindowsSDK10。我从 Frank 那里读到了一些关于迁移的笔记,并做了他在下面 link 中所说的一切: http://www.d3dcoder.net/Data/Book4/d3d11Win10.htm

但卡在了这里。我知道@poncho 也有同样的问题并且回答得很好: Access floats of XMMatrix - () operator not working

但是我在输入 CXMMATRIX 而不是 XMMATRIX 时遇到了问题,我无法通过为他提供的解决方案获得结果。

所以我必须访问 CXMMATRIX 的行和列:

void ExtractFrustumPlanes(XMFLOAT4 planes[6], CXMMATRIX M)
{
    //
    // Left
    //
    planes[0].x = M(0,3) + M(0,0);
    planes[0].y = M(1,3) + M(1,0);
    planes[0].z = M(2,3) + M(2,0);
    planes[0].w = M(3,3) + M(3,0);
...

但我得到:

call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type

term does not evaluate to a function taking 2 arguments

它指向 CXMMATRIX 类型的参数 M,在 DirectXMath.h 中定义如下:

// Fix-up for (2nd+) XMMATRIX parameters to pass by reference
typedef const XMMATRIX& CXMMATRIX; 

关于 !?

的所有这些错误是什么?

Frank Luna 的书总体上是对 Direct 11 API 的精彩介绍,但不幸的是,它大量使用了旧版 DirectX SDK,根据 MSDN 已弃用。其中一个方面是他实际上使用的是 xnamath 库(a.k.a.xboxmath 版本 2)而不是 DirectXMath 库(a.k.a.xboxmath 版本 3)

Book Recommendations and Introducing DirectXMath

我在将库重新设计为 DirectXMath 时进行了一些更改。首先,这些类型实际上位于 C++ 命名空间中,而不是全局命名空间中。在你的 headers 中,你应该使用全名规范:

#include <DirectXMath.h>

void MyFunction(..., DirectX::CXMMATRIX M);

在你的 cpp 源文件中你应该使用:

#include <DirectXMath.h>

using namespace DirectX;

另一个变化是强烈反对对 XMVECTORXMMATRIX 数据类型使用 'per-element' 访问。正如 DirectXMath Programmers Guide 中所讨论的,这些类型是设计为无法直接访问的 SIMD 寄存器类型的代理 by-element。相反,您转换为允许 per-element 访问的 XMFLOAT4X4 表示,因为这是一个标量结构。

您可以通过以下事实看到这一点:您尝试使用的运算符仅为 'no-intrinsics' 模式定义(即当使用标量而不是 SSE、ARM-NEON 等 SIMD 操作时。 ):

#ifdef _XM_NO_INTRINSICS_
    float operator() (size_t Row, size_t Column) const { return m[Row][Column]; }
    float& operator() (size_t Row, size_t Column) { return m[Row][Column]; }
#endif

同样,根据设计,此过程有点 'verbose' 因为它让您知道它不是免费的。有些人发现 DirectXMath 的这一方面使用起来有点令人沮丧,尤其是在他们刚开始使用时。在那种情况下,我建议您看一下 SimpleMath wrapper in the DirectX Tool Kit。您可以使用 Vector3Vector4Matrix 等类型,它们可以根据需要自由转换(通过 C++ 运算符和构造函数)为 XMVECTORXMMATRIX .它的效率不高,但使用起来更加宽容。

你写的具体函数也有点问题。首先,混合 XMFLOAT4XMMATRIX 参数有点奇怪。对于 'in-register, SIMD-friendly' 调用约定,您将使用:

void XM_CALLCONV ExtractFrustumPlanes(XMVECTOR planes[6], FXMMATRIX M)

有关原因的详细信息,请参阅 MSDN

如果您只想进行纯标量数学运算,请使用 non-SIMD 类型:

void ExtractFrustumPlanes(XMFLOAT4 planes[6], const XMFLOAT4X4& M)

或更好的是使用 SimpleMath,这样您就可以避免编写显式转换 to/from XMVECTORXMMATRIX

using DirectX::SimpleMath;

void ExtractFrustumPlanes(Vector4 planes[6], const Matrix& M)

Note that the latest version of DirectXMath is on GitHub and NuGet.