1

I have a simple IRenderable class that has members for position, scaling, and rotation:

XMFLOAT3 _position;
XMFLOAT3 _scaling;
XMVECTOR _rotation;

I am attempting to set them with the constructor. The first method here gives an access violation 0x00000000 trying to set _rotation (_position and _scaling are both set fine):

IRenderable() : _position(XMFLOAT3(0, 0, 0)), _scaling(XMFLOAT3(1, 1, 1)), _rotation(XMQuaternionIdentity()) { }

Making _rotation an XMVECTOR* instead and using _rotation(new XMVECTOR()) in the constructor sets it to an empty XMVECTOR, but then throws an access violation later when trying to set the identity Quaternion:

*_rotation = XMQuaternionIdentity();

Using the address of the XMQuaternionIdentity in the constructor works fine when creating the object,

IRenderable() : _position(new XMFLOAT3(0, 0, 0)), _scaling(new XMFLOAT3(1, 1, 1)), _rotation(&XMQuaternionIdentity()) { }

but then the quaternion itself contains garbage data by the time it needs to be used to render with. Both _position and _scaling are working fine in all of these situations.

What is the correct way to use XMVECTOR in this situation?

mikeschuld
  • 943
  • 1
  • 11
  • 25

2 Answers2

7

In general you should avoid using XMVECTOR in a struct. The XMFLOAT# classes are the storage classes, and should be used for general storage. You can however use the XMVECTOR if you declare the structure as aligned.

http://msdn.microsoft.com/en-us/library/83ythb65.aspx

__declspec(align(16)) struct A{ XMVECTOR a, b, c, d, e; };

but I believe that if you do this then every structure that has an A in it, must also be 16 byte aligned (or 32, 48 etc). In general, it is much easier and clearer to use the storage classes, and just convert to the XMVECTOR or XMMATRIX when you are going to do some calculation (XMLoadFloat4) and storing back into an XMFLOAT# (XMStoreFloat4), or when you take in values for functions (be sure to read http://msdn.microsoft.com/en-us/library/windows/desktop/ee418728(v=vs.85).aspx ), or returning values from functions.

Michael
  • 3,604
  • 3
  • 19
  • 12
  • XMVECTOR is not being used in a struct – mikeschuld Nov 30 '11 at 02:54
  • Right, but you are using it in a member variable if I am reading it correctly. You should just store it as a XMFLOAT4. You don't need anything additional. Just do XMStoreFloat4(&_rotation, XMQuaternionIdentity()) and have _rotation be an XMFLOAT4 – Michael Dec 05 '11 at 01:23
2

To work around the bug Eitenne mentioned, I simply made an AxisAngle struct:

struct AxisAngle {
    XMFLOAT3 Axis;
    float Angle;

    AxisAngle() : Axis(XMFLOAT3(0, 0, 0)), Angle(0) { }

    AxisAngle(XMFLOAT3 axis, float angle) {
        Axis = axis;
        Angle = angle;
    }
};

Using this in place of the XMVECTOR for rotation and then at render time just using the following to get the rotation matrix:

XMMATRIX rotation = XMMatrixRotationNormal(XMLoadFloat3(&_rotation->Axis), _rotation->Angle);

Obviously this is only a workaround and the real solution needs to be fixed in the compiler to allow the 16 bit boundaries on the heap for XMVECTOR.

mikeschuld
  • 943
  • 1
  • 11
  • 25