将自定义矩阵转换为浮动*

时间:2016-03-25 06:36:05

标签: c++ matrix directx directx-11

所以我一直在编写自己的物理引擎一段时间,我最近开始在使用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

所以......任何人都有任何想法为什么这段代码会这样做?

1 个答案:

答案 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);