-1

私は自分が制御しているオブジェクトを前方に移動しようとしましたが、これは問題なく実行できますが、向きを変える機能を実装したいと思うとすぐに、どのような試みもできないように見えますオブジェクトを適切に回転させるようです。いつも起こっているのは、それが向きを変え始め、それからちょうど自分自身に向きを変えて、予測できない方向に行くということです. やりたいことは、前進キーを押しながら右ターンキーを押したままにすると、円を描いて移動します。

私が試したことは次のとおりです

前進する(私がターンをまったく行わない場合、うまく機能します)。_13、_23、および _33 は、マトリックスの前方ベクトルです。

float x = transform->getLocalTransform()._13 * (fowardmovement * elapsedtime);
float y = transform->getLocalTransform()._23 * (fowardmovement * elapsedtime);
float z = transform->getLocalTransform()._33 * (fowardmovement * elapsedtime);

// apply the movement as an impulse to the rigid body for the object
objectrigidbody->addImpulseForce(x, y, z); 

逆方向にも同じことを行いますが、backwardmovement 変数を使用します。

回転のために私がやろうとしたことは、オブジェクトの Y 軸に直接回転を適用することです。

// the function rotate applies the rotation directly to the object, with no return value
objectrigidbody->rotate(0.0, turnmovement * elapsedtime, 0.0); 

前方と右折キーを押したままにすると、オブジェクトが円を描くように移動できるようにする方法を知っている人はいますか?

4

4 に答える 4

1

他のコメントが述べたように、移動値をマトリックスに突っ込むだけでワールド空間を移動しています。これは、オブジェクトのローカルの向きを尊重するように移動値を変更する作業を行う必要があることを意味します。このように機能するものが必要です(誰もが指摘しているように、APIが何であるかがわからないため、メソッド名は作成されています)

// apply the rotation.
// I'm assuming this is in local space, if there were a 'rotateLocal' function you should
// use that
objectrigidbody->rotate(0.0, turnmovement * elapsedtime, 0.0); 

// with made-up but probably available function
Vec3 forward = objectrigidbody.getForwardVector();
// most api's give you a method or property to get the worldspace vector that
// corresponds to 'forward' in your coordinate system.  Use that.


// scale that vector (I'm assuming it's a unit vector: they usually are)
// by speed:
forward *= fowardmovement * elapsedtime;

// apply the impulse:
objectrigidbody->addImpulseForce(forward.x, forward.y, forward.z);

ここでも、あなたが望むものを得ているかどうかわからないことに注意してください。小惑星スタイルのナビゲーションを行っていない限り、ここで一定の力が必要になると思います.

于 2013-06-23T19:48:18.033 に答える
1

あなたは次の形式の行列を扱っていると思います

[ side_x up_x forward_x position_x ]
[ side_y up_y forward_y position_y ]
[ side_z up_z forward_z position_z ]
[      0    0         0          1 ]

したがって、ローカル アップ ベクトルaラジアンを中心に回転するには、ローカル変換行列に、Y ベクトルを中心に回転する回転行列を掛けます。つまり、

[ side_x up_x forward_x position_x ]     [ cos(a) 0 -sin(a) 0 ]
[ side_y up_y forward_y position_y ] *=  [      0 1       0 0 ]
[ side_z up_z forward_z position_z ]     [ sin(a) 0  cos(a) 0 ]
[      0    0         0          1 ]     [      0 0       0 1 ]

それがどうなるか教えてください。

大きな編集

ここにいくつかの詳細情報があります。

定義 (フレーム)

フレームF は、4 つの同次座標 x_F、y_F、z_F、o_F の集合であり、x_F、y_F、z_F の 4 番目の座標はゼロであり、o_F の 4 番目の座標は 1 であり、x_F、y_F、z_F はペアワイズ直交 (直交性)実際には必要ありませが、ここではこのように定義しています)。o_F はフレームの原点と呼ばれます。頂点の集合は、それらの座標が F に対して表現されている場合、フレーム F に対して相対的であると言われます。

例 1

Blender または Maya で作成されたメッシュの頂点は、モデルのフレームに対して相対的に表現されます。

定義(フレーム変換行列)

2 つのフレーム F と G が与えられた場合、フレーム変換行列M は、次のような 4x4 行列 M です。

  1. M * x_F = x_G
  2. M * y_F = y_G
  3. M * z_F = z_G
  4. M * o_F = o_G

別の書き方をすると、これを M * [x_F, y_F, z_F, o_F] = [x_G, y_G, z_G, o_G] と表すことができます。ここで、[ ... ] はそれぞれ列にまたがる行列を意味します。ここでも別の書き方をしますが、可逆性は問題ではないと仮定すると、次のように書くことができます。

M = [x_G y_G z_G o_G] * [x_F y_F z_F o_F]^{-1}

例 2

ワールド空間からビュー (または目) 空間に変換する必要があるとします。ワールド空間座標は単なる標準の基底ベクトルであると仮定し、ビュー空間のカメラは o_V を中心としており、ベクトル x_V、y_V、および z_V を取得するように回転が適用されていると仮定します。その場合、M は次のようになります。

M = [x_V y_V z_V o_V] * I^{-1} = [x_V y_V z_V o_V]

例 3

モデルからの頂点に対するバッチがあり、頂点の座標がモデル空間で表現されているとします。モデルはワールド空間のどこかに配置され、向きがあります。したがって、モデルには原点 o_M といくつかの回転 x_M、y_m、z_M があります。頂点をモデル空間からワールド空間に変換する行列は、次のようになります。

M = I * [x_M y_M z_M o_M]^{-1} = [x_M y_M z_M o_M]^{-1}

行列を反転する必要があることに注意してください。

例 4

モデル空間からビュー空間に直接行きたいとしましょう。model -> world と world -> view の行列を既に推定しているので、これは簡単です。したがって

M = [x_V y_V z_V o_V] * [x_M y_M z_M o_M]^{-1}

誰も気にしない?

フレームは、必要な効果を実装するための便利なツールです。私たちの世界のすべてのオブジェクトがposition、 a 、forwardおよびupベクトルを持っているとします。私たちが見ている私たちのカメラも世界のオブジェクトです。したがって、 a position、 a 、forwardおよびupベクトルもあります。Frameクラスの最初のバージョンは

struct Frame { // version 1
    vec3 position;
    vec3 forward;
    vec3 up;
};

Frameしかし、私たちは便利なことをしたいと考えています。したがって、メンバー関数を追加できます。

struct Frame { // version 2
    vec3 position;
    vec3 forward;
    vec3 up;
    mat4 getLocalToWorldTransform() const;
    mat4 getWorldToLocalTransform() const;
}

メンバー関数は次のmat4 Frame::getWorldToLocalTransform() constようになります。

mat4 Frame::getWorldToLocalTransform() const {
    vec3 side = crossProduct(forward, up);
    //          [x_F  y_F    z_F       o_F  ] (!!)
    return mat4(side, up, -forward, position); // +forward or -forward depending on the graphics API
}

気がついたら、問題があるかもしれません。常に直交しているupことを保証するのは誰ですか? forwardあなたはそれを自分で処理する必要があります。たとえば、ベクトルが常に直交するようforwardに、ベクトルを中心に方向のみを回転させることができます。up実装の詳細はお任せmat4 Frame::getLocalToWorldTransform() constします。

今、私たちFrameは世界を動き回れるようにしたいと考えています。メンバー関数をさらに追加できます

struct Frame { // version 3
    vec3 position;
    vec3 forward;
    vec3 up;
    mat4 getLocalToWorldTransform() const;
    mat4 getWorldToLocalTransform() const;
    void moveForward(const float steps);
    void moveBackward(const float steps);
    void rotateClockwiseAroundUp(const float radians);
    void rotateCounterClockwiseAroundUp(const float radians);
}

の実装は次のvoid Frame::rotateCounterClockwiseAroundUp(const float radians)ようになります。

void Frame::rotateCounterClockwiseAroundUp(const float radians) {
    direction = mat3::rotationFromAngleAndAxis(radians, up) * direction;
}

したがって、カメラは独自のFrameクラスを維持する必要があります。カメラを回転するには、メンバー関数rotateCounterClockwiseAroundUpと を使用しrotateClockwiseAroundUpます。カメラを前後に移動するには、メンバー関数moveForwardと を使用しmoveBackwardます。変換行列を取得するには、メンバー関数を使用しますgetWorldToLocalTransform。これは、ワールド -> ビュー空間から移動する必要があるためです。

于 2013-06-23T01:31:00.177 に答える