我正在用 C++11/VC11 编写另一个游戏引擎,它目前使用 DirectX/Direct3D11 作为渲染后端。为了从公共接口中隐藏 DirectX 类型(以及以后可能实现的 OpenGL 后端),我自己推出了一个线性代数库,但它暂时仍然在内部使用 DirectX Math。DirectX Math 或多或少是围绕 C++ SIMD 内在函数(__m128 等)的一堆类型定义。为了将间接级别保持在较低水平并尽可能将内容设为“原子”和内联,我更喜欢直接从 DirectX 数学类型(在本例中为 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 想象成一个寄存器——而不是一个内存位置。