2013-03-09 96 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