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

时间:2013-07-04 17:53:22

标签: c++ matrix directx directx-11 modern-ui

我正在尝试在DirectX中做一些3D内容(我正在从OpenGL迁移)并且遇到了麻烦。

我想访问XMMATRIX的值并查看Microsoft文档应该有一个()运算符:

    float&  operator ()(
  size_t Row,
  size_t Column
);

所以我试着这样使用:

XMMATRIX i = XMMatrixIdentity();
float j = i(0,0);

但是Intellisense给了我错误:

  

IntelliSense:调用类类型的对象,没有适当的operator()或转换函数到指针到函数类型。

如果我忽略了Intellisense并且仍然编译,我得到编译时错误:

  

错误C2064:术语不评估为采用2个参数的函数

任何人都知道为什么会这样?或者另一种访问Matrix元素的方法?

感谢您的时间。

P.S。我正在为Windows 8创建一个C ++ / DirectX现代UI应用程序,如果这些信息有用的话。

4 个答案:

答案 0 :(得分:4)

检查this MSDN link,您将看到它取决于您拥有的DirectX或XNA数学标头以及当时有效的预处理器定义。默认情况下,出于优化原因,矩阵和向量结构将使用SSE和内在函数实现,这使得提供行/列访问变得困难且昂贵。

尝试在项目属性的C ++条目的预处理器指令中定义_XM_NO_INTRINSICS_,或在#define _XM_NO_INTRINSICS_任何DirectX标头之前#include

我的Windows 8 VS2012系统上DirectXMath.h的摘录显示了您收到此错误的原因:

struct XMMATRIX
{
    // ... code removed for clarity

#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

    // ... code removed for clarity
};

答案 1 :(得分:1)

由于底层的SIMD指令集,XMVECTORXMMATRIX的单个元素访问效率非常低,因此DirectXMath库不通过成员方法支持它。根据您的需要,有很多方法可以实现这一目标。

如果您只需要(0,0)元素,可以使用:

float j = XMVectorGetX( i.r[0] );

如果您要访问XMMATRIX的大部分或全部单个元素,最佳解决方案是将其转储到XMFLOAT4X4

XMFLOAT4X4 tmp;
XMStoreFloat4x4( &tmp, i );
float j = tmp.m[0][0]; // or float j = tmp._11

我将提交一个doc bug,因为MSDN上提到的operator()实际上是" XNAMath",而不是" DirectXMath"。有关背景信息,请参阅this blog post

如果您发现DirectXMath对您的需求有点过于强硬,您可能需要考虑在SimpleMath中使用DirectX Tool Kit

答案 2 :(得分:1)

我发现这个工作正常,我也将我的代码基于相同的光线拾取教程,并且从xnamath转到directxmath。

这将从矩阵中选择正确的值,而无需禁用SSE内在函数。

"投影"是一个XMMATRIX,包含来自摄像机的视图矩阵。

    XMVECTOR xv = projection.r[0];
    XMVECTOR yv = projection.r[1];
    PRVecX =  ((( 2.0f * mouseX) / Window::ClientWidth) - 1 ) / XMVectorGetX(xv);
    PRVecY = -((( 2.0f * mouseY) / Window::ClientHeight) - 1 ) / XMVectorGetY(yv);

使用定义禁用内在函数是一个错误的想法,因为它会极大地降低您的程序速度。如上所述,尽可能转换代码以正确加载和存储内在值。

答案 3 :(得分:0)

您可以尝试:

XMMATRIX i = XMMatrixIdentity();
float j = i.r[0].m128_f32[0];