我想在游戏中实施ray-picking 我按照this指南来实施它。
要计算实际光线,我缺少lookAt
和up
矢量。
我使用glRotate
和glTranslate
代替gluLookAt(eye,target,up)
来旋转和移动相机。
如何从旋转和平移/矩阵中计算lookAt
和up
?
使用键盘移动相机
if (game.keys[Keyboard.KEY_W]) {
position.x -= (float) (Math.sin(-rotation.y * Math.PI / 180) * speed);
position.z -= (float) (Math.cos(-rotation.y * Math.PI / 180) * speed);
}
if (game.keys[Keyboard.KEY_S]) {
position.x += (float) (Math.sin(-rotation.y * Math.PI / 180) * speed);
position.z += (float) (Math.cos(-rotation.y * Math.PI / 180) * speed);
}
if (game.keys[Keyboard.KEY_A]) {
position.x += (float) (Math.sin((-rotation.y - 90) * Math.PI / 180) * speed);
position.z += (float) (Math.cos((-rotation.y - 90) * Math.PI / 180) * speed);
}
if (game.keys[Keyboard.KEY_D]) {
position.x += (float) (Math.sin((-rotation.y + 90) * Math.PI / 180) * speed);
position.z += (float) (Math.cos((-rotation.y + 90) * Math.PI / 180) * speed);
}
使用鼠标旋转相机
if (Mouse.isGrabbed()) {
float mouseDX = Mouse.getDX() * 0.8f * 0.16f;
float mouseDY = Mouse.getDY() * 0.8f * 0.16f;
if (rotation.y + mouseDX >= 360) {
rotation.y = rotation.y + mouseDX - 360;
} else if (rotation.y + mouseDX < 0) {
rotation.y = 360 - rotation.y + mouseDX;
} else {
rotation.y += mouseDX;
}
if (rotation.x - mouseDY >= -89 && rotation.x - mouseDY <= 89) {
rotation.x += -mouseDY;
} else if (rotation.x - mouseDY < -89) {
rotation.x = -89;
} else if (rotation.x - mouseDY > 89) {
rotation.x = 89;
}
}
更新相机
glRotatef(rotation.x, 1, 0, 0);
glRotatef(rotation.y, 0, 1, 0);
glRotatef(rotation.z, 0, 0, 1);
glTranslatef(-position.x + zoom, -position.y - 7 + zoom * -1.05f, -position.z);
相机
private void updateCamera() {
DoubleBuffer m = createDoubleBuffer(16);
glGetDouble(GL_MODELVIEW_MATRIX, m);
vUp.x = (float) m.get(1);
vUp.y = (float) m.get(5);
vUp.z = (float) m.get(9);
vPos.x = (float) -(m.get(0) * m.get(12) + m.get(1) * m.get(13) + m.get(2) * m.get(14));
vPos.y = (float) -(m.get(4) * m.get(12) + m.get(5) * m.get(13) + m.get(6) * m.get(14));
vPos.z = (float) -(m.get(8) * m.get(12) + m.get(9) * m.get(13) + m.get(10) * m.get(14));
vBack.x = (float) m.get(2);
vBack.y = (float) m.get(6);
vBack.z = (float) m.get(10);
glRotatef(rotation.x, 1, 0, 0);
glRotatef(rotation.y, 0, 1, 0);
glRotatef(rotation.z, 0, 0, 1);
glTranslatef(-position.x + zoom, -position.y, -position.z);
}
采摘
public void picking(float screenX, float screenY, PickingRay pickingRay) {
helper.Vector3f view = camera.vBack;
view.x *= -1;
view.y *= -1;
view.z *= -1;
helper.Vector3f screenHorizontally = new helper.Vector3f(0, 0, 0);
helper.Vector3f screenVertically = new helper.Vector3f(0, 0, 0);
float viewAngle = 150; // fovy 150
float nearClippingPlaneDistance = 1; // was mus hier rein?
int viewportWidth = width; // 1200
int viewportHeight = height; // 900
screenHorizontally.crossAndAssign(view, camera.vUp).normalize();
screenVertically.crossAndAssign(screenHorizontally, view).normalize();
final float radians = (float) (viewAngle * Math.PI / 180f);
float halfHeight = (float) (Math.tan(radians / 2) * nearClippingPlaneDistance);
float halfScaledAspectRatio = halfHeight * getViewportAspectRatio();
screenVertically.scale(halfHeight);
screenHorizontally.scale(halfScaledAspectRatio);
pickingRay.getClickPosInWorld().set(camera.vPos);
pickingRay.getClickPosInWorld().add(view);
screenX -= (float) viewportWidth / 2f;
screenY -= (float) viewportHeight / 2f;
screenX /= ((float) viewportWidth / 2f);
screenY /= ((float) viewportHeight / 2f);
pickingRay.getClickPosInWorld().x += screenHorizontally.x * screenX + screenVertically.x * screenY;
pickingRay.getClickPosInWorld().y += screenHorizontally.y * screenX + screenVertically.y * screenY;
pickingRay.getClickPosInWorld().z += screenHorizontally.z * screenX + screenVertically.z * screenY;
pickingRay.getDirection().set(pickingRay.getClickPosInWorld());
// pickingRay.getDirection().sub(cpos); // cpos is always [0,0,0]
System.out.println("x: " + pickingRay.getClickPosInWorld().x + " y: " + pickingRay.getClickPosInWorld().y + " z: " + pickingRay.getClickPosInWorld().z); // ends in [0, -3.7, 0] to [0, 3.7, 0]
}
答案 0 :(得分:2)
您可以从OpenGL的模型视图矩阵中获取它。
检索矩阵(在设置视图之后但在应用任何对象转换之前),如下所示:
GLfloat m[16];
glGetFloatv(GL_MODELVIEW_MATRIX, m);
然后,向上矢量的X,Y和Z分量位于m[1]
,m[5]
,m[9]
。
&#39;权利&#39;和&#39;返回&#39; vector是int m[0]
,m[4]
,m[8]
和m[2]
,m[6]
,m[10]
。
有关详细信息,请参阅this link。
要获取相机位置,您必须按here所述使用m[12]
,m[13]
和m[14]
。例如:
camX = -(m[0] * m[12] + m[1] * m[13] + m[2] * m[14]);
camY = -(m[4] * m[12] + m[5] * m[13] + m[6] * m[14]);
camZ = -(m[8] * m[12] + m[9] * m[13] + m[10] * m[14]);