1

位置、スケーリング、および回転のメンバーを持つ単純な IRenderable クラスがあります。

XMFLOAT3 _position;
XMFLOAT3 _scaling;
XMVECTOR _rotation;

コンストラクターでそれらを設定しようとしています。最初の方法では、_rotation を設定しようとしてアクセス違反 0x00000000 が発生します (_position と _scaling はどちらも適切に設定されています)。

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

代わりに _rotation を XMVECTOR* にし、コンストラクターで _rotation(new XMVECTOR()) を使用すると、空の XMVECTOR に設定されますが、後で ID クォータニオンを設定しようとすると、アクセス違反がスローされます。

*_rotation = XMQuaternionIdentity();

コンストラクターで XMQuaternionIdentity のアドレスを使用すると、オブジェクトの作成時に問題なく動作します。

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

しかし、クォータニオン自体には、レンダリングに使用する必要があるまでにガベージ データが含まれます。これらすべての状況で、_position と _scaling の両方が正常に機能しています。

この状況で XMVECTOR を使用する正しい方法は何ですか?

4

2 に答える 2

7

一般に、構造体で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など)する必要があると思います。一般に、ストレージクラスを使用する方がはるかに簡単で明確であり、計算(XMLoadFloat4)を実行してXMFLOAT#(XMStoreFloat4)に格納するとき、または取り込むときにXMVECTORまたはXMMATRIXに変換するだけです。関数の値( http://msdn.microsoft.com/en-us/library/windows/desktop/ee418728(v=vs.85).aspxを必ずお読みください)、または関数から値を返します。

于 2011-11-28T18:57:24.420 に答える
2

Eitenne が言及したバグを回避するために、単純に 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);

明らかに、これは単なる回避策であり、XMVECTOR のヒープで 16 ビット境界を許可するために、実際の解決策をコンパイラで修正する必要があります。

于 2011-07-24T20:56:50.523 に答える