我希望能够创建一个第一人称的相机,并且可以处于两种模式之一。它要么固定在特定位置(标准的“wasd”移动围绕该点移动),要么具有自由查看,其中移动不受限制在一个点周围盘旋,鼠标可用于查看任何地方。(虽然只能向上/向下看,因为我不想要一个六自由度的相机来下降)这意味着我目前不想滚动。
有人可以指导我完成实现这种事情所需的基础知识吗?我目前正在使用 LWJGL,因此我可以访问它们提供的 Vector* 和 Matrix* 类,以及我自己的 Quaternion 类,它可以做一些 LWJGL 没有做的事情。还假设我有一个方法lookAt,它的坐标与OpenGL的gluLookAt(eyex,eyey,...,upy,upz)完全相同,这就是我想要构建矩阵/矩阵的地方。还假设生成的矩阵/矩阵将在版本 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;
}