问题
I am trying to make a game/demo with Java/LWJGL and having troubles with the first person camera:
I use the WASD to move the eye
vector around, however strange things are happening:
- When I move the eye away or to me, the right resp. left parts of the view get blocked for my view.
- When I move the eye to the right or left of me, then the top resp. bottom parts of the view get blocked for my view.
I have implemented mouse movement (to look around) with success, the relevant pieces of code now:
(Note: The Matrix4f class works in column-major order)
Matrix4f viewMatrix = new Matrix4f();
private void checkKeys() {
if (isKeyCurrentlyDown(Keyboard.KEY_W)) {
eye.updateTranslate(1.0f, 0.0f, 0.0f);
updateView();
}
else if (isKeyCurrentlyDown(Keyboard.KEY_S)) {
eye.updateTranslate(-1.0f, 0.0f, 0.0f);
updateView();
}
else if (isKeyCurrentlyDown(Keyboard.KEY_A)) {
eye.updateTranslate(0.0f, -1.0f, 0.0f);
updateView();
}
else if (isKeyCurrentlyDown(Keyboard.KEY_D)) {
eye.updateTranslate(0.0f, 1.0f, 0.0f);
updateView();
}
}
private void updateView() {
System.out.println("eye = " + eye);
viewMatrix.identity().viewFPS(eye, roll, yaw, pitch);
System.out.println("viewMatrix = " + viewMatrix);
Uniforms.setUniformMatrix4(UNIFORM_VIEW_MATRIX, false, viewMatrix);
}
@Override
protected void render(final double msDelta) {
super.render(msDelta);
glClearColor(0.0f, 0.25f, 0.0f, 1.0f);
glClearDepthf(1f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
program.use();
for (int i = 0; i < 24; i++) {
float fVar = i + currentTime / 1000f * 0.3f;
modelviewMatrix.identity()
.translate(0.0f, 0.0f, -8.0f)
.rotate(currentTime / 1000f * 45.0f, 0.0f, 1.0f, 0.0f)
.rotate(currentTime / 1000f * 21.0f, 1.0f, 0.0f, 0.0f)
.translate(
(float)Math.sin(2.1f * fVar) * 2.0f,
(float)Math.cos(1.7f * fVar) * 2.0f,
(float)Math.sin(1.3f * fVar) * (float)Math.cos(1.5f * fVar) * 2.0f
);
Uniforms.setUniformMatrix4(UNIFORM_MODEL_MATRIX, false, modelviewMatrix.writeToFloatBuffer(modelViewMatrixBuffer));
program.drawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
}
}
#version 440 core
layout(location = 0) in vec4 position;
out VS_OUT {
vec4 color;
} vs_out;
layout(location = 0) uniform mat4 model_matrix;
layout(location = 1) uniform mat4 view_matrix;
layout(location = 2) uniform mat4 proj_matrix;
void main() {
gl_Position = proj_matrix * view_matrix * model_matrix * position;
vs_out.color = position * 2.0 + vec4(0.5, 0.5, 0.5, 0.0);
}
public enum UniformLocation {
UNIFORM_MODEL_MATRIX(0),
UNIFORM_VIEW_MATRIX(1),
UNIFORM_PROJECTION_MATRIX(2)
;
private final int location;
private UniformLocation(final int location) {
this.location = location;
}
public int getLocation() {
return this.location;
}
}
//Column-major order
public Matrix4f viewFPS(final Vector3f eye, final float rollAngle, final float yawAngle, final float pitchAngle) {
//roll = rolling your head, Q&E
//yaw = looking left/right, mouseY
//pitch = looking up/down, mouseX
float sinRoll = (float)Math.sin(Math.toRadians(rollAngle));
float cosRoll = (float)Math.cos(Math.toRadians(rollAngle));
float sinYaw = (float)Math.sin(Math.toRadians(yawAngle));
float cosYaw = (float)Math.cos(Math.toRadians(yawAngle));
float sinPitch = (float)Math.sin(Math.toRadians(pitchAngle));
float cosPitch = (float)Math.cos(Math.toRadians(pitchAngle));
Vector3f xAxis = new Vector3f(
cosYaw * cosPitch,
sinYaw * cosPitch,
-sinPitch
);
Vector3f yAxis = new Vector3f(
cosYaw * sinPitch * sinRoll - sinYaw * cosRoll,
sinYaw * sinPitch * sinRoll + cosYaw * cosRoll,
cosPitch * sinRoll
);
Vector3f zAxis = new Vector3f(
cosYaw * sinPitch * cosRoll + sinYaw * sinRoll,
sinYaw * sinPitch * cosRoll - cosYaw * sinRoll,
cosPitch * cosRoll
);
return multiply(
xAxis.getX(), xAxis.getY(), xAxis.getZ(), -xAxis.dot(eye), //X column
yAxis.getX(), yAxis.getY(), yAxis.getZ(), -yAxis.dot(eye), //Y column
zAxis.getX(), zAxis.getY(), zAxis.getZ(), -zAxis.dot(eye), //Z column
0.0f, 0.0f, 0.0f, 1.0f //W column
);
}
I really have no clue why the camera is behaving so weirdly, and what it even means?
How can parts of the picture suddenly become not visible anymore?
Update: It might have to do with the viewFPS()
method, as the translations look slightly odd there, could someone confirm?
回答1:
Noticed that in viewFPS
you combine rotation and translation in one matrix multiplication.
I am not familiar with the way you build the matrix, but I can tell you what works for me.
- Create 3 matrices, one for X rotation, Y rotation and Z rotation values.
- Multiply those matrices in the order you want. (I use Z, Y then X)
- Multiply the result with your translation matrix. (i.e Position of your eye)
- The resulting matrix is your view matrix.
This might be less efficient than the method you are using, but it's great to get it working then optimize from there? Splitting up the rotation axies also gives the benefit of being able to debug 1 axis at a time.
Rotation matrices I use:



Where , (phi), and (psi) are the rotations around the X, Y and Z axes.(http://www.fastgraph.com/makegames/3drotation/)
来源:https://stackoverflow.com/questions/21235494/first-person-camera-weird-behaviour-on-moving-the-eye