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?
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.
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.
精彩评论