2013-03-09 73 views
2

我正在用C++ 11/VC11編寫另一個遊戲引擎,它目前使用DirectX/Direct3D11作爲渲染後端。爲了從公共接口中隱藏DirectX類型(以及稍後可能實現的OpenGL後端),我自己開發了一個線性代數庫,然而,它仍然在內部使用DirectX Math。 DirectX Math或多或少是圍繞C++ SIMD內在函數(__m128等)的一系列typedef。 爲了保持間接水平低並且儘可能地將內容作爲「原子」並內聯,我寧願直接繼承DirectX Math類型(在這種情況下爲XMVECTORF32) - 即我不想將它用作一個成員變量:C++ 11 DirectX Math:XMVECTORF32作爲基礎結構初始化

struct vector4 : private DirectX::XMVECTORF32 

MSDN給出下面的示例用於XMVECTORF32結構的正確初始化:

XMVECTOR data; 
XMVECTORF32 floatingVector = { 0.f, 0.f, 0.1f, 1.f }; 
data = floatingVector; 

然而,我試圖初始化XMVECTORF32作爲基礎結構不被編譯器理解。

struct vector4 : private DirectX::XMVECTORF32 // not XMFLOAT4 due to possible conversation overhead 
{ 
    friend class matrix44; 

    inline vector4(scalar v0, scalar v1, scalar v2, scalar v3) 
     : DirectX::XMVECTORF32{v0, v1, v2, v3} // ERROR: ';' expected 
    { 
    } 
}; 

我錯過了什麼嗎?如何正確執行我打算執行的基本初始化?是否有一些新的C++ 11初始化糖可以幫助我?

------------ 編輯 -----------

由於種種原因,我沒有看到明顯。在檢查了XMVECTORF32的定義之後,很明顯我可以訪問底層的union-float-array「f」,所以初始化看起來像這樣。

struct vector4 : private DirectX::XMVECTORF32 
{ 
    friend struct matrix44; 

    inline vector4(scalar v0, scalar v1, scalar v2, scalar v3) 
    { 
     f[0] = v0; 
     f[1] = v1; 
     f[2] = v2; 
     f[3] = v3; 
    } 
}; 

沒有廣播,沒有工會,沒有C數組。通過內聯,性能應該接近最佳。

------------ 編輯2 -----------

XMVECTORF32並不意味着用於存儲數據。因此,該向量必須從XMFLOAT4繼承。否則,這會導致不可重複的訪問衝突異常,特別是在優化打開的情況下。下面是更多的背景:http://www.asawicki.info/news_1429_xna_math_and_access_violation.html

我最後的代碼如下所示:

struct vector4 : private DirectX::XMFLOAT4 
{ 
    friend struct matrix44; 

    inline vector4(scalar v0, scalar v1, scalar v2, scalar v3) 
     : DirectX::XMFLOAT4(v0, v1, v2, v3) 
    { 
    } 

    inline scalar& v0() { return x; } 
    inline scalar& v1() { return y; } 
    inline scalar& v2() { return z; } 
    inline scalar& v3() { return w; } 
}; 

矢量數據必須被加載到使用XMLoadFloat4之前SIMD計算的XMVECTOR - 沒有辦法繞過它。把XMVECTOR想象成一個寄存器 - 而不是內存位置。

+0

您使用的是哪種版本的VC編譯器? – 2013-03-09 14:09:51

+0

你試過GLM了嗎?它的名字中有GL,但它在DX中應該可以正常工作。 – Cubic 2013-03-09 14:10:40

+0

@AndyProwl Visual Studio Express 2012版本11.0.51106.01更新1 – 2013-03-09 14:12:39

回答

1

假設DirectX::XMVECTORF32是一個聚合類,你的代碼在C++ 11中是很好的(參見live example,它演示了它的用法)。

然而,要使用的編譯器支持均勻的初始化(由this Q&A on StackOverflow作爲澄清),並在C++ 03不能初始化的基聚合類,你會複製初始化的變量。

因此,您必須在初始化列表中明確初始化您的基類的成員,或者在vector4構造函數的主體中調用類似SetVector()的東西。

+0

謝謝,這是有道理的。在GCC中使用C++ 11的方式更好,但由於這個新的「metro應用程序」和Windows Store需求,我堅持使用MSVC。 最終溶液: \t \t內嵌的Vector4(標量V0,標量V1,V2的標量,標量V3) \t \t { \t \t \t F [0] = V0; \t \t \t f [1] = v1; \t \t \t f [2] = v2; \t \t \t f [3] = v3; \t \t} – 2013-03-09 14:44:09