我正在使用具有偏航,俯仰和滚动的相机。当偏航== 0时,摄像机向下看-z轴(偏航== 90是正x),当俯仰= = 270时,摄像机正在向上看(俯仰== 0正在看直),当滚动== 180时相机颠倒了。
相机的偏航,俯仰和滚转值永远不会小于零或大于360(当任何值超过0或360时,当它超过该数量时,它会自动移动到“另一侧”)。
我已经实现了3DoF,它运行得很好;然而,当我实现6DoF时,一切似乎都工作,直到滚动大约是90或270,然后向上和向右的向量发生奇怪的事情(向前总是似乎工作,因为滚动围绕该轴旋转?)
我渲染的场景只是一堆块(在我的世界风格的块中),我总是能够前进/后退并使用前向矢量来定位一个块,所以我知道前向矢量已完成。
这是我的initGL:
public void initGL() {
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL11.glClearDepth(1.0);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_LEQUAL);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluPerspective(fov, ((float) Display.getWidth()) / ((float) Display.getHeight() != 0 ? Display.getHeight() : 1), 0.1f, 100.0f);//fov is 45.0f
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
}
这是我旋转并转换到相机视图的地方:
public final void lookThrough() {
GL11.glRotatef(this.roll, 0.0f, 0.0f, 1.0f);
GL11.glRotatef(this.pitch, 1.0f, 0.0f, 0.0f);
GL11.glRotatef(this.yaw, 0.0f, 1.0f, 0.0f);
GL11.glTranslatef(-this.position.x, -this.position.y, -this.position.z);
}
这是我的六个自由度计算:
public static final double zeroRad = Math.toRadians(0);
public static final double ninetyRad = Math.toRadians(90);
public static final double oneEightyRad = Math.toRadians(180);
public static final double twoSeventyRad = Math.toRadians(270);
public static final strictfp void updateLookVectorsIn6DoF(Vector3f yawPitchAndRoll, Vector3f forward, Vector3f up, Vector3f right) {
final double yaw = Math.toRadians(yawPitchAndRoll.getX());
final double pitch = Math.toRadians(yawPitchAndRoll.getY());
final double roll = Math.toRadians(yawPitchAndRoll.getZ());
final float sinYaw = ((float) Math.sin(yaw));
final float cosYaw = ((float) Math.cos(yaw));
final float sinYaw90 = ((float) Math.sin(yaw + ninetyRad));
//final float sinYaw180 = ((float) Math.sin(yaw + oneEightyRad));
final float cosYaw270 = ((float) Math.cos(yaw - ninetyRad));
final float sinRoll = ((float) Math.sin(roll));
final float cosRoll = ((float) Math.cos(roll));
//final float sinRoll180 = ((float) Math.sin(roll + oneEightyRad));
final float cosPitch90 = ((float) Math.cos(pitch + ninetyRad));
//final float cosPitch270 = ((float) Math.cos(pitch + twoSeventyRad));
final float sinPitch90 = ((float) Math.sin(pitch + ninetyRad));
final float sinPitch270 = ((float) Math.sin(pitch - ninetyRad));
//Forward:(No roll because roll goes around the Z axis and forward movement is in that axis.)
float x = sinYaw * ((float) Math.cos(pitch));
float y = -((float) Math.sin(pitch));
float z = cosYaw * ((float) Math.cos(pitch - oneEightyRad));
forward.set(x, y, z);
//cos(90) = 0, cos(180) = -1, cos(270) = 0, cos(0) = 1
//sin(90) = 1, sin(180) = 0, sin(270) = -1, sin(0) = 0
//Up: Strange things occur when roll is near 90 or 270 and yaw is near 0 or 180
x = -(sinYaw * cosPitch90) * cosRoll - (sinRoll * sinYaw90);
y = -sinPitch270 * cosRoll;
z = (cosYaw * cosPitch90) * cosRoll + (sinRoll * cosYaw270);
up.set(x, y, z);
//Right: Strange things occur when roll is near 90 or 270 and pitch is near 90 or 270
x = (cosRoll * sinYaw90) - (sinRoll * (sinYaw * cosPitch90));
y = 0 - (sinRoll * sinPitch90);//This axis works fine
z = (cosRoll * cosYaw270) + (sinRoll * (sinYaw * cosPitch90));
right.set(x, y, z);
}
我确实在这里找到了一个非常相似的问题,但是它使用了矩阵和四元数,我不想这样做,除非我绝对不得不这样做(并且我小心翼翼地试图在正确的情况下将音高和偏航相乘)订单):LWJGL - Problems implementing 'roll' in a 6DOF Camera using quaternions and a translation matrix
答案 0 :(得分:0)
所以我终于掌握了cos和罪的含义(但不要让我教它)并且能够让它工作!
以下是新的和改进的代码:
public static final double zeroRad = Math.toRadians(0);
public static final double ninetyRad = Math.toRadians(90);
public static final double oneEightyRad = Math.toRadians(180);
public static final double twoSeventyRad = Math.toRadians(270);
public static final strictfp void updateLookVectorsIn6DoF(Vector3f yawPitchAndRoll, Vector3f forward, Vector3f up, Vector3f right) {
final double yaw = Math.toRadians(yawPitchAndRoll.getX());
final double pitch = Math.toRadians(yawPitchAndRoll.getY());
final double roll = Math.toRadians(yawPitchAndRoll.getZ());
final float sinYaw = ((float) Math.sin(yaw));
final float cosYaw = ((float) Math.cos(yaw));
final float sinYaw90 = ((float) Math.sin(yaw + ninetyRad));
final float sinYaw270 = ((float) Math.sin(yaw - ninetyRad));//+ twoSeventyRad));
final float cosYaw90 = ((float) Math.cos(yaw + ninetyRad));
final float cosYaw180 = ((float) Math.cos(yaw + oneEightyRad));
final float cosYaw270 = ((float) Math.cos(yaw - ninetyRad));//+ twoSeventyRad));
final float sinRoll = ((float) Math.sin(roll));
final float cosRoll = ((float) Math.cos(roll));
final float cosRoll180 = ((float) Math.cos(roll + oneEightyRad));
final float cosPitch90 = ((float) Math.cos(pitch + ninetyRad));
final float sinPitch90 = ((float) Math.sin(pitch + ninetyRad));
final float sinPitch270 = ((float) Math.sin(pitch - ninetyRad));
//Forward:(No roll because roll goes around the Z axis and forward movement is in that axis.)
float x = sinYaw * ((float) Math.cos(pitch));
float y = -((float) Math.sin(pitch));
float z = cosYaw * ((float) Math.cos(pitch - oneEightyRad));
forward.set(x, y, z);
//Multiply in this order: roll, pitch, yaw
//cos(90) = 0, cos(180) = -1, cos(270) = 0, cos(0) = 1
//sin(90) = 1, sin(180) = 0, sin(270) = -1, sin(0) = 0
//hmm... gimbal lock, eh? No!
//Up://
x = (cosRoll180 * cosPitch90 * sinYaw) - (sinRoll * cosYaw180);
y = -sinPitch270 * cosRoll;
z = (cosRoll * cosPitch90 * cosYaw) + (sinRoll * sinYaw);
up.set(x, y, z);
//Right:
x = (cosRoll * sinYaw90) - (sinRoll * cosPitch90 * cosYaw90);
y = 0 - (sinRoll * sinPitch90);//This axis works fine
z = (cosRoll * cosYaw270) + (sinRoll * cosPitch90 * sinYaw270);
right.set(x, y, z);
}