2016-03-25 40 views
2

因此,我一直在編寫自己的物理引擎,現在我開始設置DirectX渲染,而不是在使用OpenGL渲染時進行硬編碼。現在,在最後,我遇到了似乎是一些我無法想象的非常奇怪的行爲。將自定義矩陣投入浮動*

爲了矩陣傳遞給着色畫的東西,你調用了一個const float*的功能,並做到這一點的典型方式是在一個D3DXMATRIX鑄傳遞給float*D3DXMATRIX和轉換運算符被聲明爲:

D3DX10INLINE 
D3DXMATRIX::operator FLOAT*() 
{ 
    return (FLOAT *) &_11; 
} 

D3DX10INLINE 
D3DXMATRIX::operator CONST FLOAT*() const 
{ 
    return (CONST FLOAT *) &_11; 
} 

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)定義:

typedef struct D3DXMATRIX : public D3DMATRIX 
{ 
    ... 
    operator FLOAT*(); 
    operator CONST FLOAT*() const; 
    .... 
} D3DXMATRIX, *LPD3DMATRIX; 

D3DMATRIX作爲被聲明

CONSTFLOAT關鍵字在minwindef.hD3DX10INLINE在D3DX10.h定義爲:

#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]; 
     } 
}; 

和功能定義爲:

__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]; 
    } 
} 

例如,如果我通過在與所述值的D3DXMATRIX1-16每個浮筒16作爲第一個參數的我的矩陣與作爲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}

所以...任何人有任何想法,爲什麼這個代碼的行爲是這樣嗎?

+0

你在'Matrix'任何其他成員變量? –

+0

@AntonSavin不,就是這樣。 – ArcRaizen

回答

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); 
+0

我的Matrix類中沒有其他數據成員,並且foo-> SetMatrix((float *)&m),foo-> SetMatrix((float *)m)和foo-> SetMatrix(m)之間絕對沒有功能差異。在所有。 – ArcRaizen

+0

@ArcRaizen你可以試試'static_assert > :: value'? –

+0

回到真實 – ArcRaizen