一人称で、2つのモードのいずれかにできるカメラを作成できるようにしたいと思います。特定の場所を見て固定されている(そして標準の「wasd」の動きがそのポイントの周りを移動する)か、フリールックで、動きがポイントの周りを旋回するように制限されず、マウスを使用してどこでも見ることができます。(ただし、6自由度のカメラを降下させたくないので、真っ直ぐ上下にしか見えないように固定されています)これは、現在、ロールを使用したくないことを意味します。
誰かが私にこの種のことを実装するために必要な基本を教えてもらえますか?私は現在LWJGLを使用しているので、それらが提供するVector*クラスとMatrix*クラス、およびLWJGLが提供しないいくつかのことを実行する独自のQuaternionクラスにアクセスできます。また、OpenGLのgluLookAt(eyex、eyey、...、upy、upz)とまったく同じ座標が与えられるメソッドlookAtがあると仮定します。これは、マトリックス/行列を作成したい場所です。また、結果のマトリックス/マトリックスがバージョン330シェーダーで使用されると仮定します。
layout(location = 0) in vec4 position;
uniform mat4 camera;
uniform mat4 projection;
uniform mat4 model;
// ...
gl_Position = projection * camera * model * (position);
コードの一部です。現在の操作の順序を維持しますか、それとも正しいgl_Positionを取得するために何らかの方法で変更する必要がありますか?
クォータニオンコード:
public class Quaternion {
public float x, y, z, w;
public Quaternion() {
this.x = 0.0f;
this.y = 0.0f;
this.z = 0.0f;
this.w = 1.0f;
}
public Quaternion(Vector3f v, float w) {
this.x = v.x;
this.y = v.y;
this.z = v.z;
this.w = w;
}
public Quaternion(float x, float y, float z, float w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public Quaternion(Quaternion other) {
this.x = other.x;
this.y = other.y;
this.z = other.z;
this.w = other.w;
}
public float length() {
return (float)Math.sqrt(x * x + y * y + z * z + w * w);
}
public Quaternion normalize() {
return Quaternion.normalize(new Quaternion(this));
}
public Quaternion conjugate() {
return Quaternion.conjugate(new Quaternion(this));
}
public Quaternion mult(Quaternion other) {
return Quaternion.mult(this, other, new Quaternion());
}
public static Quaternion fromAxisAngle(Quaternion q, Vector3f axis, float angle) {
float sinAngle2 = (float)Math.sin(angle / 2.0);
q.x = axis.x * sinAngle2;
q.y = axis.y * sinAngle2;
q.y = axis.y * sinAngle2;
q.w = (float)Math.cos(angle / 2.0);
return q;
}
public static Matrix4f toMatrixUnit(Quaternion q) {
Matrix4f ret = new Matrix4f();
ret.m00 = 1 - 2 * q.y * q.y - 2 * q.z * q.z;
ret.m01 = 2 * q.x * q.y - 2 * q.w * q.z;
ret.m02 = 2 * q.x * q.z + 2 * q.w + q.y;
ret.m03 = 0;
ret.m10 = 2 * q.x * q.y + 2 * q.w * q.z;
ret.m11 = 1 - 2 * q.x * q.x - 2 * q.z * q.z;
ret.m12 = 2 * q.y * q.z + 2 * q.w * q.x;
ret.m13 = 0;
ret.m20 = 2 * q.x * q.z - 2 * q.w * q.z;
ret.m21 = 2 * q.y * q.z - 2 * q.w * q.x;
ret.m22 = 1 - 2 * q.x * q.x - 2 * q.y * q.y;
ret.m23 = 0;
ret.m30 = 0;
ret.m31 = 0;
ret.m32 = 0;
ret.m33 = 1;
return ret;
}
public static Matrix4f toMatrix(Quaternion q) {
throw new UnsupportedOperationException("Use toMatrixUnit");
// Matrix4f ret = new Matrix4f();
// return ret;
}
public static Quaternion mult(Quaternion A, Quaternion B, Quaternion C) {
C.x = A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y;
C.y = A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x;
C.z = A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w;
C.w = A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z;
return C;
}
public static Quaternion normalize(Quaternion q) {
float len = q.length();
q.x = q.x / len;
q.y = q.y / len;
q.z = q.y / len;
q.w = q.w / len;
return q;
}
public static Quaternion conjugate(Quaternion q) {
q.x = -q.x;
q.y = -q.y;
q.z = -q.z;
return q;
}