c++ - 将自定义矩阵转换为 float *

标签 c++ matrix directx directx-11

所以我断断续续地编写自己的物理引擎有一段时间了,最​​近我开始设置 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;
}

CONSTFLOAT关键字在 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/

相关文章:

python - 如何在Python中将pandas数据框转换为矩阵格式?

c++ - 如何将 std::vector 插入具有自定义排序功能的 std::set

c++ - 如何在 OpenGL 即时模式下永久绘制东西?

C++ 不显示 cout 信息

c++ - 创建交换链失败

directx - SharpDX:从 D3D10.Texture2D 创建 D3D11.Texture2D?

.net - 没有 WPF 或 XNA 的 HLSL?

c++ - 在另一个类中使用一个类的静态对象

c++ - 带有目标相机的 C++ 3d vector/矩阵库的建议

c++ - 以不同的方式将两个矩阵相乘 - 不知道该怎么做