1

OpenGLレンダラーにカメラオブジェクトがあります。正常に動作します。ただし、Adobe AfterEffects with Null Objectで行われるように、親がカメラを操作できるように、親ノードに親にする必要があります。AEに慣れていない場合は、次のように機能します。Nullオブジェクトは空のコンテナです。カメラがその親になっていて、オブジェクト自体がターゲット位置にある場合、ターゲットに関心のあるポイント(別名lookAt)を持つカメラは、nullオブジェクトが回転したときにターゲットの周りを向きます。これが問題の核心です。私の実装では、カメラを子としてターゲットの位置に配置されている親を回転させると、カメラは親の位置にロックされたままになりませんが、lookAtの方向も変わります。これが問題を描いたスクリーンショットです: ここに画像の説明を入力してください

左側のスクリーンショットは間違った動作です。カメラの親は中央にありますが、カメラの方向はカメラではなく回転しています。右のスクリーンショットは、AEでの動作と動作を示しています。ヌルオブジェクトを回転させると、カメラがヌルオブジェクトの中心軸を中心に回転します。私はここでいくつかの愚かな間違ったマトリックス順序のことをしていると確信しています。だからここに私がコードで行う方法があります:

カメラのlookAtマトリックスを次のように計算します。

 public void lookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, Vec3 upPt) {

    _eye.set(eyeX, eyeY, eyeZ);
    _center.set(centerX, centerY, centerZ);
    _up = upPt;

    _direction = Vec3.sub(_center, _eye).normalize();

    _viewMatr = Glm.lookAt(_eye, _center, _up);

    _transform.setModel(Mat4.mul(rotMat, _viewMatr));
///rotMat is rotation matrix cached from rotation method call.

 }

Glm:lookAtは、C ++ GLM math libからの移植であり、次のようになります。

 public static Mat4 lookAt(Vec3 eye, Vec3 center, Vec3 up) {
    Vec3 f = normalize(Vec3.sub(center, eye));
    Vec3 u = normalize(up);
    Vec3 s = normalize(cross(f, u));
    u = cross(s, f);

    Mat4 result = new Mat4(1.0f);
    result.set(0, 0, s.x);
    result.set(1, 0, s.y);
    result.set(2, 0, s.z);
    result.set(0, 1, u.x);
    result.set(1, 1, u.y);
    result.set(2, 1, u.z);
    result.set(0, 2, -f.x);
    result.set(1, 2, -f.y);
    result.set(2, 2, -f.z);

    return translate(result, new Vec3(-eye.x,-eye.y,-eye.z));
  }

これが最初の部分で、カメラの「モデル」マトリックスを作成します。Nexステップは、カメラの親ノードを考慮してワールドマトリックスを作成することです。

  Mat4 world=   Mat4.mul( this.getTransform().parentMatr, this.getTransform().getModel());


    this.getTransform().setView(world);

パイプラインの後半で、カメラのビューマトリックス(setViewで設定したもの)に、レンダリングされる各ジオメトリオブジェクトからアクセスし、モデル、ビュー、プロジェクションマトリックスを計算して、頂点シェーダーに送信します。

奇妙なことに、setView()メソッドに渡す前にワールドマトリックスを反転し、GLMで目のベクトルを否定しないと、機能します!しかし、そのような場合、カメラがペアレント化されていないモードでは機能しません。私がOpenGL4.0Coreで使用している固定パイプラインベースのソリューションを提案しないでください。

4

1 に答える 1

1

数学については、以下をお読みください。より実用的なアプローチについては、最後まで進んでください。

あなたが直面している問題は、アフィン変換行列が別のデカルト座標系内のデカルト座標系を効果的に記述することです。したがって、それらを連鎖させることにより、常に親に対して相対的に作業します。ここで、「カメラ」(もちろん OpenGL にはカメラがありませんが、このテキストのために a がカメラであると仮定しlookAtます) を何らかの座標系にペアレント化すると、すべての変換はこの座標系に対して相対的になります。したがって、 AlookAtはこのローカル座標系のフレームで動作します。

これを数学的に分解してみましょう。

世界と呼ばれるグローバルな座標空間があります。ワールドは一種の中心ピボット ポイントであるため、ワールド空間の座標に変換は適用されません。つまり、変換は恒等、つまり単に I です。

「カメラ」は、全世界を別の位置に移動することによって実装されます。OpenGL にはカメラはありませんが、視点は常に原点にあり= (0,0,0)ます。これは、視点が原点に到達するように、全世界をある位置に変換することとして説明できます。V^-1 がワールドの原点にあるカメラの目的の位置への変換を表しているとしましょう。V^-1 の逆、つまり

V^-1^-1 = V

ビュー変換です。ここで、相対変換 L を持つカメラは、他のオブジェクトの親であり、その変換は F としましょう。したがって、ビュー全体の変換は、

V^-1 = F・L

L はまさにその変換lookAtが生成するものの逆です。ここで問題があります:lookAt空間 F 内で動作します。これは、渡されるすべてのベクトルが F に対して相対的でなければならないことを意味します。したがって、これが機能するために実際には F も反転させているので、

V^-1 = (L^-1 · F^-1)^-1

ここで、M のスコープ外に別のオブジェクトがあり、それを確認したいとします。それは、世界に対するGとしましょう。このオブジェクトを見るには、F に対する位置を知る必要があります。簡単です。最初に G からワールドに「順方向」に移動し、次に G に「逆方向」に移動します。つまり、(F^-1)^-1 · G = F · G

オブジェクト G が原点の中心にあると仮定すると、F · G · (0,0,0,1) を評価する必要があります。これは、G の 4 番目の列を F で変換することになります。結果は、次のように使用する必要があります。の目標位置lookAt。それが、オブジェクトマトリックスをそこに入れるという意味です。


ただし、このアプローチ全体は、複雑な変換チェーンで壊れる可能性があります。もっと単純なことを提案します。カメラとターゲット オブジェクトの位置をワールド座標に変換lookAtし、ワールド空間に を適用するだけです。

于 2012-12-26T18:09:32.317 に答える