所以我一直在编写自己的物理引擎一段时间,我最近开始在使用OpenGL进行渲染时设置DirectX渲染而不是硬编码。现在,在最后,我遇到了一些我无法弄清楚的非常奇怪的行为。
为了将矩阵传递到着色器以绘制内容,您调用一个采用const float*
的函数,并且执行此操作的典型方法是将D3DXMATRIX
强制转换为{{1} }。 float*
和转换运算符声明为:
D3DXMATRIX
和typedef struct D3DXMATRIX : public D3DMATRIX
{
...
operator FLOAT* ();
operator CONST FLOAT* () const;
....
} D3DXMATRIX, *LPD3DMATRIX;
声明为:
D3DMATRIX
两个转换运算符在不同的文件(D3DX10math.inl)中定义为:
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;
D3DX10INLINE
D3DXMATRIX::operator FLOAT* ()
{
return (FLOAT *) &_11;
}
D3DX10INLINE
D3DXMATRIX::operator CONST FLOAT* () const
{
return (CONST FLOAT *) &_11;
}
和CONST
关键字在FLOAT
中定义,minwindef.h
在D3DX10.h中定义为:
D3DX10INLINE
对我所描述的功能的调用很简单:
#ifndef CONST
#define CONST const
#endif
....
typedef float FLOAT;
....
#define D3DX10INLINE __forceline
在我的引擎中,我一直使用自己的D3DXMATRIX m;
foo->SetMatrix((float*)&m);
类,当我尝试将其传递给上面的函数而不是Matrix
时,它会发送不正确的数据。我的D3DXMATRIX
类(貌似)以与Matrix
相同的方式定义,但拒绝以相同的方式运行。这是我的矩阵类(或相关部分):
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];
}
};
我尝试在CPP文件中,在头文件中,在类定义中定义运算符,所有运算符都包含__forceinline
Matrix::operator float* ()
{
return (float *) &_00;
}
__forceinline
Matrix::operator const float* () const
{
return (const float *) &_00;
}
和inline
,但没有任何东西可以使它工作。我想我可以将每个矩阵中的所有数据复制到__forceinline
,但这会浪费大量时间/操作,应该无关紧要。最大的问题是我不能为我的生活弄清楚为什么一切都这样。我不太明白为什么。
为了确保传递给DirectX函数的数据,我设置了一个测试函数,以便我可以调试它并查看传递的确切值:
D3DXMATRIX
例如,如果我为16个浮点数中的每一个传递值为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];
}
}
的{{1}}作为第一个参数,其中一个矩阵的值与D3DXMATRIX
相同,那么{ {1}}将使用值1-16
填充,但b
将= aa
所以......任何人都有任何想法为什么这段代码会这样做?
答案 0 :(得分:1)
您实际上错误地使用了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);