所以我断断续续地编写自己的物理引擎有一段时间了,最近我开始设置 DirectX 渲染,而不是在使用 OpenGL 的渲染中进行硬编码。现在,在最后,我遇到了一些我无法弄清楚的似乎非常奇怪的行为。
为了将矩阵传递给着色器来绘制东西,您调用一个函数,该函数接受 const float*
。执行此操作的典型方法是传入 D3DXMATRIX
转换为 float*
. D3DXMATRIX
并且转换运算符声明为:
typedef struct D3DXMATRIX : public D3DMATRIX
{
...
operator FLOAT* ();
operator CONST FLOAT* () const;
....
} D3DXMATRIX, *LPD3DMATRIX;
和D3DMATRIX
声明为:
typedef struct _D3DMATRIX {
union {
struct {
float __11, _12, _13, _14;
float __21, _22, _23, _24;
float __31, _32, _33, _34;
float __41, _42, _43, _44;
};
float m[4][4];
};
} D3DMATRIX;
这两个转换运算符在不同的文件 (D3DX10math.inl) 中定义为:
D3DX10INLINE
D3DXMATRIX::operator FLOAT* ()
{
return (FLOAT *) &_11;
}
D3DX10INLINE
D3DXMATRIX::operator CONST FLOAT* () const
{
return (CONST FLOAT *) &_11;
}
CONST
和 FLOAT
关键字在 minwindef.h
中定义和 D3DX10INLINE
在 D3DX10.h 中定义为:
#ifndef CONST
#define CONST const
#endif
....
typedef float FLOAT;
....
#define D3DX10INLINE __forceline
对我描述的函数的调用很简单:
D3DXMATRIX m;
foo->SetMatrix((float*)&m);
在我的整个引擎中,我一直在使用自己的 Matrix
类,当我试图将它传递给上面的函数而不是 D3DXMATRIX
时,它发送不正确的数据。我的Matrix
class 的定义方式(表面上)与 D3DXMATRIX
相同,但拒绝以同样的方式运作。这是我的矩阵类(或相关部分):
class Matrix {
public:
....
operator float* ();
operator const float* () const;
....
private:
union {
struct {
float _00, _01, _02, _03;
float _10, _11, _12, _13;
float _20, _21, _22, _23;
float _30, _31, _32, _33;
};
float m[4][4];
}
};
函数定义为:
__forceinline
Matrix::operator float* ()
{
return (float *) &_00;
}
__forceinline
Matrix::operator const float* () const
{
return (const float *) &_00;
}
我试过在 CPP 文件、头文件、类定义中定义运算符,无论是否使用 inline
。和 __forceinline
,但没有什么能让它发挥作用。我想我可以将每个矩阵中的所有数据复制到 D3DXMATRIX
,但这会浪费大量时间/操作,而且应该是无关紧要的。最大的问题是我终其一生都无法弄清楚为什么一切都会这样。我不明白为什么。
为了确保数据被传递到 DirectX 函数中,我设置了一个测试函数,这样我就可以调试它并查看传入的确切值是什么:
void Test(const float *a, const float *b)
{
bool result[16] = {false};
float aa[16], bb[16];
for(unsigned int i = 0; i < 16; ++i)
{
result[i] = a[i] == b[i];
aa[i] = a[i];
bb[i] = b[i];
}
}
例如,如果我传入 D3DXMATRIX
值为 1-16
对于 16 个 float 中的每一个作为我的矩阵的第一个参数,其值与 b
相同然后 aa
将填充值 1-16
很好,但是bb
将 = {0.0, 1.875, 0.0, 2.0, 0.0, 2.125, 0.0, 2.5, 0.0, 2.315, 0.0, 2.375, 0.0, 2.4375, 0.0, 2.5}
那么...有人知道为什么这段代码会这样吗?
最佳答案
您实际上错误地使用了 operator float*
。
D3DXMATRIX m;
foo->SetMatrix((float*)&m);
在这里,您将m
的地址 转换为float*
。这不是调用 operator float
,它只是一个 reinterpret_cast
(编译器应该对此发出警告)。但幸运的是,D3DMATRIX
不包含任何其他成员,开头也没有填充,所以一切正常。
如果 Matrix
在其 _00
之前包含其他数据成员或者不是 standard-layout这种转换可能会产生不确定的结果。
所以底线是,你应该做
foo->SetMatrix((float*)m);
或者只是
foo->SetMatrix(m);
关于c++ - 将自定义矩阵转换为 float *,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36215199/