Having problem with mapping mouse click to points

I downloaded and got working JOGL 2.0 (I think beta 10 build from http://download.java.net/media/jogl/builds/archive/jsr-231-2.0-beta10/),

I’m trying to plot mouse clicks to points on the screen, but I’m always off a bit. I think its something to do with the transformation, which I still don’t full understand. Here is what I believe are the relevant sections of my code (I’ll post the entire file at the end).

Any suggestions would be helpful

main


public static void main(String[] args) {
Frame testFrame = new Frame("TestFrame");
		testFrame.setSize(screenHeight, screenHeight);
		GLCanvas canvas = new GLCanvas();
		
		testFrame.add( canvas );

		canvas.addGLEventListener(new DrawPoints(canvas));

		final Animator animator = new Animator( canvas);
		...
		testFrame.setVisible(true);
		animator.start();

init


 public void init(GLAutoDrawable gLDrawable) {
 	
     GL2 gl = gLDrawable.getGL().getGL2();
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		gl.glOrtho(0,screenWidth,0,screenHeight,-1,1);
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		gl.glLoadIdentity();

     if (gLDrawable instanceof AWTGLAutoDrawable) {
         AWTGLAutoDrawable awtDrawable = (AWTGLAutoDrawable) gLDrawable;
         awtDrawable.addMouseListener(this);   
     }
 }

mousepressed:

	public void mousePressed(MouseEvent e) {
		
		points.add(e.getPoint());
}

display:

	
public void display(GLAutoDrawable gLDrawable) {
		
		GL2 gl2 = gLDrawable.getGL().getGL2();
		// Clear the screen.
		gl2.glClear(GL2.GL_COLOR_BUFFER_BIT);
		gl2.glColor3i(0, 1, 0);
		if(!points.isEmpty()){
			if(points.size()==1){
			..
			}else{
				gl2.glBegin(mode);
				for (Iterator<Point> iterator = points.iterator(); iterator.hasNext();) {
					Point point = iterator.next();
					gl2.glVertex3f(point.x+canvas.getX(),screenHeight-point.y-canvas.getY(),0);
				}
			}
			gl2.glEnd();				// Done Drawing The Quad
			gl2.glFlush();
		}

	}

I tryed to trim irrelvant portions, but here is the whole file:

import java.awt.Frame;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Iterator;
import java.util.Vector;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.AWTGLAutoDrawable;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.GLU;


import com.sun.opengl.util.Animator;


public class DrawPoints implements GLEventListener, MouseListener {
	
	GLU glu = new GLU();
	static final int screenWidth = 640;         // width of the screen window in pixels
	static final int screenHeight = 640;        // height of the screen window in pixels
	
	private  double A = 0;
	private  double B = 0;
	private  double C = 0;
	private  double D = 0;
	
	private GLCanvas canvas;

	public DrawPoints() {
		super();
		points = new Vector<Point>();
		mode = GL2.GL_LINE_STRIP;
	}

	public DrawPoints(GLCanvas canvas) {
			this();
			this.canvas = canvas;
			
	}

	
	private Vector<Point> points;
	private int mode;
	
//	 /** Called by the drawable to initiate OpenGL rendering by the client.
//     * After all GLEventListeners have been notified of a display event, the
//     * drawable will swap its buffers if necessary.
//     * @param gLDrawable The GLAutoDrawable object.
//     */
	public void display(GLAutoDrawable gLDrawable) {
		
		GL2 gl2 = gLDrawable.getGL().getGL2();
		// Clear the screen.
		gl2.glClear(GL2.GL_COLOR_BUFFER_BIT);
		//223,y=214]
		gl2.glBegin(GL.GL_POINTS);
		gl2.glVertex3f(223,214,0);
		gl2.glEnd();				// Done Drawing The Quad
		
		//gl2.glLoadIdentity();
		gl2.glColor3i(0, 1, 0);
		if(!points.isEmpty()){
			if(points.size()==1){
				Point point = points.firstElement();
				gl2.glBegin(GL.GL_POINTS);
				gl2.glVertex3f(point.x+canvas.getX(),point.y+canvas.getY(),0);
			}else{
				gl2.glBegin(mode);
				for (Iterator<Point> iterator = points.iterator(); iterator.hasNext();) {
					Point point = iterator.next();
					gl2.glVertex3f(point.x+canvas.getX(),screenHeight-point.y-canvas.getY(),0);
				}
			}
			gl2.glEnd();				// Done Drawing The Quad
			gl2.glFlush();
		}

	}

//  /** Called by the drawable immediately after the OpenGL context is
//  * initialized for the first time. Can be used to perform one-time OpenGL
//  * initialization such as setup of lights and display lists.
//  * @param gLDrawable The GLAutoDrawable object.
//  */
 public void init(GLAutoDrawable gLDrawable) {
 	
 	//glu.gluOrtho2D(0, screenWidth, 0, screenHeight);
     GL2 gl = gLDrawable.getGL().getGL2();
     //gl.glViewport(0, 0, screenWidth	,screenHeight);
		gl.glClearColor(1.0f,1.0f,1.0f,0.0f);       // the background color is white
		gl.glPointSize(2.0f);                    // a 'dot' is 2 by 2 pixels
		//gl.glTra
		
		gl.glMatrixMode(GL2.GL_PROJECTION);

		gl.glLoadIdentity();

		gl.glOrtho(0,screenWidth,0,screenHeight,-1,1);

		gl.glMatrixMode(GL2.GL_MODELVIEW);

		gl.glLoadIdentity();
     

     if (gLDrawable instanceof AWTGLAutoDrawable) {
         AWTGLAutoDrawable awtDrawable = (AWTGLAutoDrawable) gLDrawable;
         awtDrawable.addMouseListener(this);
      
     }
     gl.glShadeModel(GL2.GL_LINE_SMOOTH);              // Enable Smooth Shading
     gl.glLineWidth(2);

 }
	
	



    /**
     * Called by the drawable during the first repaint after the component has
     * been resized. The client can update the viewport and view volume of the
     * window appropriately, for example by a call to
     * GL2.glViewport(int, int, int, int); note that for convenience the component
     * has already called GL2.glViewport(int, int, int, int)(x, y, width, height)
     * when this method is called, so the client may not have to do anything in
     * this method.
     * @param gLDrawable The GLAutoDrawable object.
     * @param x The X Coordinate of the viewport rectangle.
     * @param y The Y coordinate of the viewport rectanble.
     * @param width The new width of the window.
     * @param height The new height of the window.
     */
    public void reshape(GLAutoDrawable gLDrawable, int x, int y, int width, int height) {
//        final GL2 gl = gLDrawable.getGL().getGL2().getGL2();
//
//        if (height <= 0) // avoid a divide by zero error!
//            height = 1;
//        final float h = (float) width / (float) height;
//        gl.glViewport(0, 0, width, height);
//        gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
//        gl.glLoadIdentity();
//        glu.gluPerspective(45.0f, h, 1.0, 20.0);
//        gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
//        gl.glLoadIdentity();
    }


	@Override
	public void dispose(GLAutoDrawable drawable) {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed(MouseEvent e) {
		
		points.add(e.getPoint());
		canvas.getX();
		canvas.getY();
		if(e.getButton()!=MouseEvent.BUTTON1){
			mode=GL.GL_LINE_LOOP;
		}
		

	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub

	}
	
	public static void main(String[] args) {
		Frame testFrame = new Frame("TestFrame");
		testFrame.setSize(screenHeight, screenHeight);
		GLCanvas canvas = new GLCanvas();
		
		testFrame.add( canvas );

		canvas.addGLEventListener(new DrawPoints(canvas));

		final Animator animator = new Animator( canvas);
		 testFrame.addWindowListener(new WindowAdapter() {
		        public void windowClosing(WindowEvent e) {
		          // Run this on another thread than the AWT event queue to
		          // make sure the call to Animator.stop() completes before
		          // exiting
		          new Thread(new Runnable() {
		              public void run() {
		                animator.stop();
		                System.exit(0);
		              }
		            }).start();
		        }
		      });
		testFrame.setVisible(true);
		animator.start();
	}

	

	
}

I think you want:


glVertex3f(point.x, screenHeight - point.y);

I saw 2 places where this differed in your code. You should not need to account for the canvas’ x and y coordinates because the origin of the opengl points are relative to the GLCanvas (and not the window or screen). Additionally, the y axis and origin are flipped compared to AWT and OpenGL, which is why you need to do (screenHeight - y) in both point rendering places.

That was me trying to correct for the error. Even without it still is wrong. I did some calculating and it is about 2.5% off for the x and 6.5% off for the y. The below change seems to map clicks to points very close.

if(points.size()==1){
				Point point = points.firstElement();
				gl2.glBegin(GL.GL_POINTS);
				gl2.glVertex3d(point.x*1.025,screenHeight-(point.getY()*1.065),0);
			}else{
				gl2.glBegin(mode);
				for (Iterator<Point> iterator = points.iterator(); iterator.hasNext();) {
					Point point = iterator.next();
					gl2.glVertex3d(point.x*1.025,screenHeight-(point.getY()*1.065),0);
				}
			}

Am I doing something wrong, or misunderstanding how the ortho function works, or am I just working with a bad version of jogl.

Here’s a problem:
You’re creating a Frame that’s set to size 640 x 640 (or whatever screenHeight and screenWidth are). Then you add a GLCanvas to the Frame. However the frame’s dimensions include the border and title bar, which means that the content of the GLCanvas is actually slightly smaller than the what you think it is.

Because you use screenHeight and screenWidth within glOrtho, your ortho projection is similarly screwed up. You should add width/height variables to your DrawPoints class (not static). Then in the resize() method, assign the passed dimensions to those variables for later. Additionally, you should move the ortho projection setup to resize() from init() so you can use the correct dimensions. Then because the sizes should hopefully be accurate, you can remove the 1.025/1.065 from the glVertex calls.

Awesome, It works. thank you so much.


glVertex3f(point.x, (screenHeight-1) - point.y);