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で使用している固定パイプラインベースのソリューションを提案しないでください。