19

任意の点を中心とした回転と平行移動

オブジェクトを回転/平行移動 (z 軸のみの回転と xy 平面のみの平行移動) するために、グローバル センター (デバイスの中心) に対してだけでなく、他の任意の点に対しても正しいアルゴリズムを作成しました (私が話し合ったコーダーはそれが正しいと考えています)、実装で望ましくない翻訳を削除するには多くの時間かかります (アルゴリズムは 8 月 4 日に作成され、同じ日に実装されました。それ以来、コードは 15 回改訂されています。 )。

ここに実装があります http://www.pixdip.com/opengles/transform.php#ALGO1

望ましくない翻訳を生成しているコード行は次のとおりです。

private static void updateModel(int upDown, float xAngle, float yAngle, float zAngle) {

および以下にリストされています。

  1. Matrix.multiplyMV(GLES20Renderer._uBodyCentreMatrix, 0, GLES20Renderer._ModelMatrixBody, 0, GLES20Renderer._uBodyCentre, 0);

  2. objX = GLES20Renderer._uBodyCentreMatrix[0];

  3. objY = GLES20Renderer._uBodyCentreMatrix[1];

次の変更を行っても、+Y に沿った望ましくない移動は持続します。

  1. objY = _uBodyCentreMatrix[1] - _uBodyCentre[1];

  2. zAngle = 0;

  3. ds = 0;

Renderer クラスの次のフィールドにより、 を呼び出すたびに値-0.545867fが Y 座標に追加されます。onDrawFrame()

private static final float[] _uBodyCentre = new float[]{-0.019683f, -0.545867f, -0.000409f, 1.0f};

protected static float[] _uBodyCentreMatrix = new float[4];

http://www.pixdip.com/opengles/transform.php#FIELDS

望ましくない変換が発生する理由、変換の正確な問題、または間違っているのはアルゴリズムであるかを理解するための助けが必要です。

ここでジンバルロックが問題になることはありますか?

グローバル z 軸を中心とした回転/平行移動用の Renderer クラスを用意したので、より単純な例を実行/実践するように私に依頼しないでください。私が興味を持っているこの新しいタスクは、updateModel()

(目的の回転は z 軸のみであり、移動は xy 平面のみであることに注意してください)

[API 10->15]

実際の Renderer クラスには、タンク turret(nozzle) と tank body の 2 つのオブジェクトがあります。一方、turret(nozzle) には望ましくない前方移動があり、ボディには望ましくない後方移動があります。

デバイス センターに関する翻訳/回転用の APK (opengles 2.0 で簡単に作成できます): http://www.pixdip.com/opengles/global.php

任意のポイントに関する移動/回転用の APK (+Y に沿って望ましくない移動がある): http://www.pixdip.com/opengles/local.php

updateModel() が 4 回だけ呼び出される任意のポイントに関する変換/回転用の APK: http://www.pixdip.com/opengles/limited.php および必要なコード (これで十分なはずです) は次のとおりです: http:// www.pixdip.com/opengles/code.php

オブジェクトのパーツ (ノズル/タレット、ボディ) は現在、オブジェクトの中心 (_playerCentre) ではなく、独自の中心を中心に回転しています。後で修正します。

私はロジックを実証しようとしましたhttp://www.pixdip.com/opengles/images.php

4

4 に答える 4

5

問題は次のとおりです。

Matrix.multiplyMV(GLES20Renderer._uBodyCentreMatrix, 0, GLES20Renderer._ModelMatrixBody, 0, GLES20Renderer._uBodyCentre, 0);

Matrix.multiplyMV は、4 要素ベクトルを 4x4 行列で乗算し、結果を 4 要素列ベクトルに格納するメソッドです。行列表記: 結果 = lhs x rhs。resultVector 要素が lhsMatrix または rhsVector 要素のいずれかとオーバーラップする場合、resultVector 要素の値は未定義です。

すべてのコードを投稿したとは思わないので確認できませんが、「_uBodyCentreMatrix」という名前から判断すると、4 要素の列ベクトルではないため、エラーが発生している可能性があります。

「_ModelMatrixBody」は 4x4 マトリックスで、「_uBodyCentre」は 4 要素のベクトルであると想定しています。そうでない場合、これらも問題になる可能性があります。

于 2012-08-24T07:05:26.150 に答える
4

[解決済み] Java 浮動小数点エラーが唯一の原因でした

M = T * I * T[inv]

恒等行列にならなかったため、Matrix.MultiplyMM を使用する代わりに

行列間のすべての乗算を入力します

于 2012-11-25T10:31:14.877 に答える
3

次のような方法を使用できます。

public void rotateToAbritrary(float[] arbitraryPoint, float xAngle, float yAngle, float zAngle) {
    Matrix.translateM(modelMatrix, 0, arbitraryPoint[0], arbitraryPoint[1], arbitraryPoint[2]);
    float max = Math.max(xAngle, Math.max(yAngle, zAngle));
    if(max != 0.0f) Matrix.rotateM(modelMatrix, 0, max, xAngle / max, yAngle / max, zAngle / max);
    Matrix.translateM(modelMatrix, 0, -arbitraryPoint[0], -arbitraryPoint[1], -arbitraryPoint[2]);
}

それが私がそれをどのように見ているか、少なくとも、私はあなたに実装を任せます. あなたのコードはジンバルロックに苦しんでいないと思います。

于 2012-08-22T17:30:35.117 に答える
3

http://tutorialrandom.blogspot.com/2012/08/how-to-rotate-in-3d-using-opengl-proper.html

これは、ジンバル ロックや奇妙な移動を行わずに回転を行う最も簡単な方法だと思います。これは iOS の例ですが、Android にも簡単に適用できると確信しています。また、3D 回転用ですが、軸の 1 つを中心に回転しないだけで、2D に簡単に適用できます。

于 2012-08-23T15:07:09.860 に答える