我正在使用 Jogl2(更准确地说是 2.0-b58-20120620)和 Java7(第 9 版)。我想做一些挑选:我有一个带有 3 个彩色立方体的框架(透视投影)。
所以我试图从鼠标点击位置构建一条射线:但是当我调用 gluUnproject 时,我总是得到点(O,O,O)。
不幸的是,这个已经存在的帖子对我没有帮助。而这个似乎不适合我的情况。
这是我的 AppLauncher.java
package com.gmail.bernabe.laurent.java_opengl.picking_test;
import com.gmail.bernabe.laurent.java_opengl.picking_test.views.MainFrame;
public class AppLauncher {
public static void main(String[] args) {
new MainFrame().setVisible(true);
}
}
MainFrame.java
package com.gmail.bernabe.laurent.java_opengl.picking_test.views;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.awt.GLCanvas;
import javax.swing.JFrame;
import com.jogamp.opengl.util.FPSAnimator;
public class MainFrame extends JFrame {
public MainFrame(){
setTitle("A jogl picking test");
setSize(new Dimension(640, 510));
setLocationRelativeTo(null);
GLCanvas glCanvas = new GLCanvas();
add(glCanvas);
TheGLEventListener glListener = new TheGLEventListener();
glCanvas.addGLEventListener(glListener);
glCanvas.addMouseListener(glListener);
final FPSAnimator animator = new FPSAnimator(glCanvas, 120);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
animator.stop();
System.exit(0);
}
});
animator.start();
}
private static final long serialVersionUID = 4972092015545764168L;
}
TheGLEventListener.java
package com.gmail.bernabe.laurent.java_opengl.picking_test.views;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.gl2.GLUgl2;
import com.gmail.bernabe.laurent.java_opengl.picking_test.logic.GLLittleCube;
import com.gmail.bernabe.laurent.java_opengl.picking_test.logic.Ray;
public class TheGLEventListener implements GLEventListener,MouseListener {
@Override
public void init(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glClearColor(0.67f, 0.16f, 0.51f, 0.0f);
}
@Override
public void dispose(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
}
@Override
public void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
if (pendingEvent != null){
if (pendingEvent.getId() == MouseEvent.MOUSE_CLICKED) {
Ray.fromMouseCoords(pendingEvent.getX(), pendingEvent.getY(), gl);
pendingEvent = null;
}
}
glu.gluLookAt(
0.0f, 0.0f, 9.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f
);
drawScene(gl);
}
private void drawScene(GL2 gl) {
gl.glPushMatrix();
gl.glTranslatef(-3.0f, +1.0f, +2.0f);
GLLittleCube.draw(gl);
gl.glPopMatrix();
gl.glPushMatrix();
gl.glTranslatef(-2.0f, +3.0f, -4.0f);
GLLittleCube.draw(gl);
gl.glPopMatrix();
gl.glPushMatrix();
gl.glTranslatef(+1.0f, -2.0f, +3.0f);
GLLittleCube.draw(gl);
gl.glPopMatrix();
}
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width,
int height) {
GL2 gl = drawable.getGL().getGL2();
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(60.0, width * 1.0f / height, 0.1, 20);
gl.glMatrixMode(GL2.GL_MODELVIEW);
}
private GLU glu = new GLUgl2();
@Override
public void mouseClicked(MouseEvent e) {
pendingEvent = e;
}
@Override
public void mousePressed(MouseEvent e) {
// Not used
}
@Override
public void mouseReleased(MouseEvent e) {
// Not used
}
@Override
public void mouseEntered(MouseEvent e) {
// Not used
}
@Override
public void mouseExited(MouseEvent e) {
// Not used
}
private MouseEvent pendingEvent;
}
GLLittleCube.java
package com.gmail.bernabe.laurent.java_opengl.picking_test.logic;
import javax.media.opengl.GL2;
public class GLLittleCube {
public static void draw(GL2 gl){
gl.glBegin(GL2.GL_QUADS);
//FRONT face (BLUE)
gl.glColor3f(0.0f, 0.13f, 0.66f);
gl.glVertex3f(-1.0f, -1.0f, +1.0f);
gl.glVertex3f(+1.0f, -1.0f, +1.0f);
gl.glVertex3f(+1.0f, +1.0f, +1.0f);
gl.glVertex3f(-1.0f, +1.0f, +1.0f);
//BACK face (GREEN)
gl.glColor3f(0.07f, 0.43f, 0.0f);
gl.glVertex3f(-1.0f, -1.0f, -1.0f);
gl.glVertex3f(+1.0f, -1.0f, -1.0f);
gl.glVertex3f(+1.0f, +1.0f, -1.0f);
gl.glVertex3f(-1.0f, +1.0f, -1.0f);
//LEFT face (RED)
gl.glColor3f(0.7f, 0.0f, 0.0f);
gl.glVertex3f(-1.0f, -1.0f, -1.0f);
gl.glVertex3f(-1.0f, +1.0f, -1.0f);
gl.glVertex3f(-1.0f, +1.0f, +1.0f);
gl.glVertex3f(-1.0f, -1.0f, +1.0f);
//RIGHT face (ORANGE)
gl.glColor3f(1.0f, 0.45f, 0.05f);
gl.glVertex3f(+1.0f, -1.0f, -1.0f);
gl.glVertex3f(+1.0f, +1.0f, -1.0f);
gl.glVertex3f(+1.0f, +1.0f, +1.0f);
gl.glVertex3f(+1.0f, -1.0f, +1.0f);
//TOP face (WHITE)
gl.glColor3f(0.97f, 0.90f, 0.95f);
gl.glVertex3f(-1.0f, +1.0f, -1.0f);
gl.glVertex3f(+1.0f, +1.0f, -1.0f);
gl.glVertex3f(+1.0f, +1.0f, +1.0f);
gl.glVertex3f(-1.0f, +1.0f, +1.0f);
//BOTTOM face (YELLOW)
gl.glColor3f(0.93f, 0.87f, 0.07f);
gl.glVertex3f(-1.0f, -1.0f, -1.0f);
gl.glVertex3f(+1.0f, -1.0f, -1.0f);
gl.glVertex3f(+1.0f, -1.0f, +1.0f);
gl.glVertex3f(-1.0f, -1.0f, +1.0f);
gl.glEnd();
}
}
Ray.java
package com.gmail.bernabe.laurent.java_opengl.picking_test.logic;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.media.opengl.GL2;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.gl2.GLUgl2;
public class Ray {
private Vector3f origin, direction;
public Ray(Vector3f origin, Vector3f direction) {
this.origin = origin;
this.direction = direction;
}
public Vector3f getOrigin() {
return origin;
}
public Vector3f getDirection() {
return direction;
}
public static Ray fromMouseCoords(int mouseX, int mouseY, GL2 gl){
IntBuffer viewport;
FloatBuffer modelViewMatrix;
FloatBuffer projectionMatrix;
FloatBuffer objectPos;
FloatBuffer winZ;
ByteBuffer tempViewport = ByteBuffer.allocateDirect(4*4);
tempViewport.order(ByteOrder.nativeOrder());
viewport = tempViewport.asIntBuffer();
ByteBuffer tempModelView = ByteBuffer.allocateDirect(16*4);
tempModelView.order(ByteOrder.nativeOrder());
modelViewMatrix = tempModelView.asFloatBuffer();
ByteBuffer tempProjection = ByteBuffer.allocateDirect(16*4);
tempProjection.order(ByteOrder.nativeOrder());
projectionMatrix = tempProjection.asFloatBuffer();
ByteBuffer tempObjectPos = ByteBuffer.allocateDirect(3*4);
tempObjectPos.order(ByteOrder.nativeOrder());
objectPos = tempObjectPos.asFloatBuffer();
ByteBuffer tempWinZ = ByteBuffer.allocateDirect(1*4);
tempWinZ.order(ByteOrder.nativeOrder());
winZ = tempWinZ.asFloatBuffer();
gl.glGetIntegerv(GL2.GL_VIEWPORT, viewport);
gl.glGetFloatv(GL2.GL_MODELVIEW, modelViewMatrix);
gl.glGetFloatv(GL2.GL_PROJECTION, projectionMatrix);
float winY = viewport.get(3) * 1.0f - mouseY;
float winX = mouseX * 1.0f;
gl.glReadPixels(mouseX, mouseY, 1, 1, GL2.GL_DEPTH_COMPONENT, GL2.GL_FLOAT, winZ);
glu.gluUnProject(winX, winY, 0.0f, modelViewMatrix, projectionMatrix, viewport, objectPos);
Vector3f tempOrigin = new Vector3f(objectPos.get(0), objectPos.get(1), objectPos.get(2));
glu.gluUnProject(winX, winY, winZ.get(0), modelViewMatrix, projectionMatrix, viewport, objectPos);
Vector3f tempDest = new Vector3f(objectPos.get(0), objectPos.get(1), objectPos.get(2));
Vector3f tempDirection = tempDest.clone().sub(tempOrigin).normalize();
/////////////////////////////////
System.err.println("origin : "+tempOrigin);
System.err.println("dest : "+tempDest);
System.err.println("direction : "+tempDirection);
System.err.println();
/////////////////////////////
return new Ray(tempOrigin, tempDirection);
}
private static GLU glu = new GLUgl2();
}
最后,Vector3f.java
package com.gmail.bernabe.laurent.java_opengl.picking_test.logic;
public class Vector3f {
private float x, y, z;
public Vector3f(float x, float y, float z){
this.x = x;
this.y = y;
this.z = z;
}
public Vector3f(){
this(0.0f, 0.0f, 0.0f);
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getZ() {
return z;
}
public Vector3f clone(){
return new Vector3f(x, y, z);
}
/**
* With side effect !!!
* @param other
* @return
*/
public Vector3f add(Vector3f other){
x += other.x;
y += other.y;
z += other.z;
return this;
}
/**
* With side effect !!!
* @param other
* @return
*/
public Vector3f sub(Vector3f other){
x -= other.x;
y -= other.y;
z -= other.z;
return this;
}
public double length(){
return Math.sqrt(x*x + y*y + z*z);
}
/**
* With side effect !!!
* @return
*/
public Vector3f normalize(){
double norm = length();
if (norm > 1e-12f){
x /= norm;
y /= norm;
z /= norm;
}
return this;
}
public double dot(Vector3f other){
return x*other.x + y*other.y + z*other.z;
}
/**
* Without any side effect !!!
* @param other
* @return
*/
public Vector3f cross(Vector3f other){
float tempX, tempY, tempZ;
tempX = y*other.z - z*other.y;
tempY = z*other.x - x*other.z;
tempZ = x*other.y - y*other.x;
return new Vector3f(tempX, tempY, tempZ);
}
public String toString(){
return String.format("Vector3f(x=%f, y=%f, z=%f)", x,y,z);
}
}
那么,怎么了?