沿 X 轴和 Z 轴实现相机旋转时出现问题
Issue while implementing camera rotation along X and Z axis
我正在实现一个响应鼠标位置变化的相机。这是一个数学问题而不是编码问题,但我也想知道如何使用它。
我有一个 Camera 对象,当鼠标改变其 X 位置时,它会沿 Y 轴旋转。这按预期工作,我可以围绕我正在绘制的立方体旋转。现在我想实现由鼠标垂直变化触发的向上和向下看,但是 X 轴和 Z 轴是相对于相机对象的,所以我不能只沿着 X 轴旋转,而是必须结合 X 轴和 Z 轴以流畅的动作执行此操作。
public class Camera {
public float moveSpeed = 0.05f;
private Vector3f position, rotation;
private float oldMouseX, oldMouseY, newMouseX, newMouseY, mouseSensitivity;
public Camera () {
position = new Vector3f(0f, 0f, 0f);
rotation = new Vector3f(0f, 0f, 0f);
mouseSensitivity = 0.1f;
oldMouseX = 0.0f;
oldMouseY = 0.0f;
newMouseX = 0.0f;
newMouseY = 0.0f;
}
public Camera (Vector3f pos, Vector3f rot) {
this.position = pos;
this.rotation = rot;
mouseSensitivity = 0.1f;
oldMouseX = 0.0f;
oldMouseY = 0.0f;
newMouseX = 0.0f;
newMouseY = 0.0f;
}
public void setCursor (int x, int y) {
oldMouseX = x;
oldMouseY = y;
newMouseX = x;
newMouseY = y;
}
public Matrix4f getViewMatrix () {
Matrix4f rotateX = new Matrix4f().rotate(rotation.x * (float)Math.PI / 180f, new Vector3f(1f, 0f, 0f));
Matrix4f rotateY = new Matrix4f().rotate(rotation.y * (float)Math.PI / 180f, new Vector3f(0f, 1f, 0f));
Matrix4f rotateZ = new Matrix4f().rotate(rotation.z * (float)Math.PI / 180f, new Vector3f(0f, 0f, 1f));
Matrix4f rotation = MatrixMath.mul(rotateX, MatrixMath.mul(rotateZ, rotateY));
Vector3f negPosition = new Vector3f(-position.x, -position.y, -position.z);
Matrix4f translation = new Matrix4f().translate(negPosition);
return MatrixMath.mul(translation, rotation);
}
public Vector3f getPosition() {
return position;
}
public Vector3f getRotation() {
return rotation;
}
public void update (Window window) {
if (window.isKeyDown(GLFW.GLFW_KEY_W)) {
position.x += Math.sin(Math.PI * rotation.y / 180) * -moveSpeed;
position.z += Math.cos(Math.PI * rotation.y / 180) * moveSpeed;
}
if (window.isKeyDown(GLFW.GLFW_KEY_S)) {
position.x -= Math.sin(Math.PI * rotation.y / 180) * -moveSpeed;
position.z -= Math.cos(Math.PI * rotation.y / 180) * moveSpeed;
}
if (window.isKeyDown(GLFW.GLFW_KEY_D)) {
position.x += Math.sin(Math.PI * (rotation.y - 90) / 180) * -moveSpeed;
position.z += Math.cos(Math.PI * (rotation.y - 90) / 180) * moveSpeed;
}
if (window.isKeyDown(GLFW.GLFW_KEY_A)) {
position.x -= Math.sin(Math.PI * (rotation.y - 90) / 180) * -moveSpeed;
position.z -= Math.cos(Math.PI * (rotation.y - 90) / 180) * moveSpeed;
}
if (window.isKeyDown(GLFW.GLFW_KEY_SPACE)) {
addPosition(0f, moveSpeed, 0f);
}
if (window.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) {
addPosition(0f, -moveSpeed, 0f);
}
newMouseX = (float)window.getMouseX();
newMouseY = (float)window.getMouseY();
float dx = newMouseX - oldMouseX;
float dy = newMouseY - oldMouseY;
if (window.isMouseButtonDown(GLFW.GLFW_MOUSE_BUTTON_LEFT)) {
rotation.y += dx * mouseSensitivity;
}
//unPos = unPos.rotateAxis(dy * mouseSensitivity, (float)Math.cos(Math.PI * rotation.y / 180), 0f, (float)Math.sin(Math.PI * rotation.y / 180));
// rotation.x += (float)Math.cos(rotation.y * Math.PI / 180) * (dy * mouseSensitivity);
// rotation.z += (float)Math.sin(rotation.y * Math.PI / 180) * (dy * mouseSensitivity);
oldMouseX = newMouseX;
oldMouseY = newMouseY;
}
}
我认为没有必要向您展示我的 Window class,因为这些功能是不言自明的。如您所见,我在底部注释掉的部分是我解决问题的方法,起初它似乎有效,但旋转略有偏差。
我希望流畅的上下运动(即相对于相机),但收到奇怪的滚动运动。
非常感谢任何帮助!
我解决了我的问题。这很奇怪,但我必须将 Y 旋转矩阵乘以 X 旋转矩阵。这对我来说没有意义,但它有效。感谢您的帮助!
我正在实现一个响应鼠标位置变化的相机。这是一个数学问题而不是编码问题,但我也想知道如何使用它。
我有一个 Camera 对象,当鼠标改变其 X 位置时,它会沿 Y 轴旋转。这按预期工作,我可以围绕我正在绘制的立方体旋转。现在我想实现由鼠标垂直变化触发的向上和向下看,但是 X 轴和 Z 轴是相对于相机对象的,所以我不能只沿着 X 轴旋转,而是必须结合 X 轴和 Z 轴以流畅的动作执行此操作。
public class Camera {
public float moveSpeed = 0.05f;
private Vector3f position, rotation;
private float oldMouseX, oldMouseY, newMouseX, newMouseY, mouseSensitivity;
public Camera () {
position = new Vector3f(0f, 0f, 0f);
rotation = new Vector3f(0f, 0f, 0f);
mouseSensitivity = 0.1f;
oldMouseX = 0.0f;
oldMouseY = 0.0f;
newMouseX = 0.0f;
newMouseY = 0.0f;
}
public Camera (Vector3f pos, Vector3f rot) {
this.position = pos;
this.rotation = rot;
mouseSensitivity = 0.1f;
oldMouseX = 0.0f;
oldMouseY = 0.0f;
newMouseX = 0.0f;
newMouseY = 0.0f;
}
public void setCursor (int x, int y) {
oldMouseX = x;
oldMouseY = y;
newMouseX = x;
newMouseY = y;
}
public Matrix4f getViewMatrix () {
Matrix4f rotateX = new Matrix4f().rotate(rotation.x * (float)Math.PI / 180f, new Vector3f(1f, 0f, 0f));
Matrix4f rotateY = new Matrix4f().rotate(rotation.y * (float)Math.PI / 180f, new Vector3f(0f, 1f, 0f));
Matrix4f rotateZ = new Matrix4f().rotate(rotation.z * (float)Math.PI / 180f, new Vector3f(0f, 0f, 1f));
Matrix4f rotation = MatrixMath.mul(rotateX, MatrixMath.mul(rotateZ, rotateY));
Vector3f negPosition = new Vector3f(-position.x, -position.y, -position.z);
Matrix4f translation = new Matrix4f().translate(negPosition);
return MatrixMath.mul(translation, rotation);
}
public Vector3f getPosition() {
return position;
}
public Vector3f getRotation() {
return rotation;
}
public void update (Window window) {
if (window.isKeyDown(GLFW.GLFW_KEY_W)) {
position.x += Math.sin(Math.PI * rotation.y / 180) * -moveSpeed;
position.z += Math.cos(Math.PI * rotation.y / 180) * moveSpeed;
}
if (window.isKeyDown(GLFW.GLFW_KEY_S)) {
position.x -= Math.sin(Math.PI * rotation.y / 180) * -moveSpeed;
position.z -= Math.cos(Math.PI * rotation.y / 180) * moveSpeed;
}
if (window.isKeyDown(GLFW.GLFW_KEY_D)) {
position.x += Math.sin(Math.PI * (rotation.y - 90) / 180) * -moveSpeed;
position.z += Math.cos(Math.PI * (rotation.y - 90) / 180) * moveSpeed;
}
if (window.isKeyDown(GLFW.GLFW_KEY_A)) {
position.x -= Math.sin(Math.PI * (rotation.y - 90) / 180) * -moveSpeed;
position.z -= Math.cos(Math.PI * (rotation.y - 90) / 180) * moveSpeed;
}
if (window.isKeyDown(GLFW.GLFW_KEY_SPACE)) {
addPosition(0f, moveSpeed, 0f);
}
if (window.isKeyDown(GLFW.GLFW_KEY_LEFT_SHIFT)) {
addPosition(0f, -moveSpeed, 0f);
}
newMouseX = (float)window.getMouseX();
newMouseY = (float)window.getMouseY();
float dx = newMouseX - oldMouseX;
float dy = newMouseY - oldMouseY;
if (window.isMouseButtonDown(GLFW.GLFW_MOUSE_BUTTON_LEFT)) {
rotation.y += dx * mouseSensitivity;
}
//unPos = unPos.rotateAxis(dy * mouseSensitivity, (float)Math.cos(Math.PI * rotation.y / 180), 0f, (float)Math.sin(Math.PI * rotation.y / 180));
// rotation.x += (float)Math.cos(rotation.y * Math.PI / 180) * (dy * mouseSensitivity);
// rotation.z += (float)Math.sin(rotation.y * Math.PI / 180) * (dy * mouseSensitivity);
oldMouseX = newMouseX;
oldMouseY = newMouseY;
}
}
我认为没有必要向您展示我的 Window class,因为这些功能是不言自明的。如您所见,我在底部注释掉的部分是我解决问题的方法,起初它似乎有效,但旋转略有偏差。
我希望流畅的上下运动(即相对于相机),但收到奇怪的滚动运动。
非常感谢任何帮助!
我解决了我的问题。这很奇怪,但我必须将 Y 旋转矩阵乘以 X 旋转矩阵。这对我来说没有意义,但它有效。感谢您的帮助!