Glu.unproject总是给我零

时间:2012-11-25 10:19:52

标签: java opengl jogl glu

我使用的是Jogl2(更准确地说是2.0-b58-20120620)和Java7(第9版)。我想做一些挑选:我有一个带有3个彩色立方体的框架(透视投影)。

所以我试图从鼠标点击位置构建一条光线:但是当我调用gluUnproject时,我总是得到点(O,O,O)。

不幸的是,this already existing post无法帮助我。 在我的情况下this one似乎没有。

这是我的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);
    }

}

那么,出了什么问题?

1 个答案:

答案 0 :(得分:0)

我发现了我的错误!!!

我必须致电

gl.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, modelview)

而不是

gl.glGetFloatv(GL2.GL_MODELVIEW, modelview)

(我忘记了MATRIX后缀)。

GL_PROJECTION_MATRIX也一样。