I'm writing another game engine in C++11/VC11 which presently uses DirectX/Direct3D11 as rendering backend. In order to hide DirectX types from the public interface (and a possible later implementation of an OpenGL backend), I'm rolling a linear algebra library on my own, which - however - still uses DirectX Math internally for the time being. DirectX Math is more or less a bunch of typedefs around the C++ SIMD intrinsics (__m128 etc.). In order to keep the levels of indirection low and have the stuff as "atomic" and inlined as possible, I prefer to inherit from the DirectX Math types directly (XMVECTORF32 in this case) - i.e. I don't want to use it as a member variable:
struct vector4 : private DirectX::XMVECTORF32
MSDN gives following example for the correct initialization of the XMVECTORF32 structure:
XMVECTOR data;
XMVECTORF32 floatingVector = { 0.f, 0.f, 0.1f, 1.f };
data = floatingVector;
However, my attempts to initialize the XMVECTORF32 as a base structure are not understood by the compiler.
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
{
}
};
Am I missing something? How to correctly perform the base initialization I am intending to do? Is there maybe some new C++11 initialization sugar to help me out?
------------ EDIT -----------
For some reasons, I was not seeing the obvious. After examining the definition of XMVECTORF32, it was clear that the underlying union-float-array "f" was accessible for me, so the initialization looks like this.
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;
}
};
No casts, no unions, no c arrays. With inlining, performance should be near optimum.
------------ EDIT 2 -----------
XMVECTORF32 is not meant for storing data. Therefore the vector must inherit from XMFLOAT4. Otherwise, this gives non-reproducible access violation exceptions, especially with optimizations turned on. Here is more background: http://www.asawicki.info/news_1429_xna_math_and_access_violation.html
My final code looks like this:
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; }
};
The vector data must be loaded into an XMVECTOR using XMLoadFloat4 prior SIMD calculations - no way around it. Think of XMVECTOR like a register - not a memory location.
Provided that DirectX::XMVECTORF32 is an aggregate class, your code is fine in C++11 (see a live example which demonstrates its use).
However, the compiler you are using does not support uniform initialization (as clarified by this Q&A on StackOverflow), and in C++03 you cannot initialize a base aggregate class as you would copy-initialize a variable.
Therefore, you will have to initialize the member of your base class explicitly in the initialization list, or call something like SetVector() in the body of your vector4 constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With