Как правильно использовать переменную-член XMVECTOR - PullRequest
1 голос
/ 25 июля 2011

У меня есть простой класс IRenderable, в котором есть члены для положения, масштабирования и вращения:

XMFLOAT3 _position;
XMFLOAT3 _scaling;
XMVECTOR _rotation;

Я пытаюсь установить их с помощью конструктора. Первый метод здесь дает нарушение прав доступа 0x00000000 при попытке установить _rotation (_position и _scaling оба установлены отлично):

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

Вместо этого, сделав _rotation XMVECTOR * и используя _rotation (new XMVECTOR ()) в конструкторе, он устанавливает пустой XMVECTOR, но затем выдает нарушение прав доступа при попытке установить идентичность

*_rotation = XMQuaternionIdentity();

Использование адреса XMQuaternionIdentity в конструкторе прекрасно работает при создании объекта,

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

но тогда сам кватернион содержит данные мусора к тому времени, когда его нужно использовать для рендеринга. И _position, и _scaling работают нормально во всех этих ситуациях.

Каков правильный способ использования XMVECTOR в этой ситуации?

Ответы [ 2 ]

7 голосов
/ 28 ноября 2011

В общем, вам следует избегать использования XMVECTOR в структуре. Классы XMFLOAT # являются классами хранения и должны использоваться для общего хранения. Однако вы можете использовать XMVECTOR, если объявите структуру как выровненную.

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

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

но я считаю, что если вы сделаете это, то каждая структура, в которой есть буква A, также должна быть выровнена на 16 байтов (или 32, 48 и т. Д.). В общем, гораздо проще и понятнее использовать классы хранения, и просто конвертировать в XMVECTOR или XMMATRIX, когда вы собираетесь выполнить какой-то расчет (XMLoadFloat4) и сохранить обратно в XMFLOAT # (XMStoreFloat4) или когда вы берете в значения для функций (обязательно прочитайте http://msdn.microsoft.com/en-us/library/windows/desktop/ee418728(v=vs.85).aspx) или возврат значений из функций.

2 голосов
/ 25 июля 2011

Чтобы обойти упомянутую ошибку Эйтена, я просто создал структуру AxisAngle:

struct AxisAngle {
    XMFLOAT3 Axis;
    float Angle;

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

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

Используя это вместо XMVECTOR для вращения, а затем во время рендеринга просто используя следующее, чтобы получить матрицу вращения:

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

Очевидно, что это всего лишь обходной путь, и реальное решение необходимо исправить в компиляторе, чтобы разрешить 16-битные границы в куче для XMVECTOR.

...