PDA

View Full Version : OpenGL gluUnProject and gluLookAt trying to understand dependence of each other



stavbodik
08-23-2015, 05:31 AM
I am using gluUnProject function from OpenGL to transform mouse 2D coordinates to world space 3D coordinates , by doing this i am retrieving a ray start and end points accordingly to the near and far plane which configured in the glFrustumf inside onSurfaceChanged function .

I created 3d world space with surface size 20*20 and painted the x,y,z axis :

2059

I am using to move the camera with gluLookAt function , When the camera Eye is set to x=0,y=0,z=98 and look at x=0,y=0,z=0 whice is the far plane (gl.glFrustumf(-ratio, ratio, -1, 1, 1f, 100)) I am getting right 3D world space coordinates from mouse .

2060

Unfortunately whenever i move the camera to other position whice cuz camera rotatation The coordinates i am getting are wrong. I understand that i have to do some mathematic calculation to normalize the coordinates to 3D world space depending on the camera position, But how please help?

The ray class :


import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLU;
import android.opengl.Matrix;

public class Ray {

float[] P0;
float[] P1;

public Ray(GL10 gl, int width, int height, float xTouch, float yTouch) {
MatrixGrabber matrixGrabber = new MatrixGrabber();
matrixGrabber.getCurrentState(gl);

int[] viewport = {0, 0, width, height};

float[] nearCoOrds = new float[3];
float[] farCoOrds = new float[3];
float[] temp = new float[4];
float[] temp2 = new float[4];
// get the near and far ords for the click

float winx = xTouch, winy =(float)viewport[3] - yTouch;

int result = GLU.gluUnProject(winx, winy, 1.0f, matrixGrabber.mModelView, 0, matrixGrabber.mProjection, 0, viewport, 0, temp, 0); Matrix.multiplyMV(temp2, 0, matrixGrabber.mModelView, 0, temp, 0);
if(result == GL10.GL_TRUE){
nearCoOrds[0] = temp2[0] / temp2[3];
nearCoOrds[1] = temp2[1] / temp2[3];
nearCoOrds[2] = temp2[2] / temp2[3];
}

result = GLU.gluUnProject(winx, winy, 0, matrixGrabber.mModelView, 0, matrixGrabber.mProjection, 0, viewport, 0, temp, 0);
Matrix.multiplyMV(temp2,0,matrixGrabber.mModelView , 0, temp, 0);
if(result == GL10.GL_TRUE){
farCoOrds[0] = temp2[0] / temp2[3];
farCoOrds[1] = temp2[1] / temp2[3];
farCoOrds[2] = temp2[2] / temp2[3];
}
this.P0 = farCoOrds;
this.P1 = nearCoOrds;
}
}

The Render class :


import java.util.Arrays;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;

public class ExampleGLRenderer implements Renderer {

private float ratio;
private int width;
private int height;
private int prevPressX = -999;
private int prevPressY = -999;

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthRangef(0,1);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glDisable(GL10.GL_DITHER); // Disable dithering for better performance
}

public void onDrawFrame(GL10 gl) {

gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glMatrixMode(GL10.GL_MODELVIEW);

double camHight=98f;
double camX=0.1f;
double camZ=0;
GLU.gluLookAt(gl, (float)camX,(float)camHight,(float)camZ, 0, 0, 0, 0, 1, 0);

Ray ray = null;
if (prevPressX != -999) {
ray = new Ray(gl, width, height, prevPressX, prevPressY);
System.out.println(Arrays.toString(ray.P1));
}

paintXYZ(gl);
paintSurface(gl,null);

prevPressX = -999;

}

public void onSurfaceChanged(GL10 gl, int width, int height) {

gl.glViewport(0, 0, width, height);
if (height == 0) height = 1; // To prevent divide by zero

this.width = width;
this.height = height;

ratio = (float)width / height;

gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();

gl.glFrustumf(-ratio, ratio, -1, 1, 1f, 100);

gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}

public void paintSurface(GL10 gl,Ray ray){

//Surface
gl.glPushMatrix();
gl.glRotatef(90f, 1, 0, 0);
Mesh floor = new Mesh();
floor.setColor("gray");
floor.setSize(20);
floor.setup();
floor.draw(gl,ray);
gl.glPopMatrix();

Line line;
for(int i=-20; i<20; i++){
line = new Line();
if(i!=0){
line.setLineCord(-20f,0,i, 20f,0.0f,i);
line.setColor("black");
line.setup();
line.draw(gl);
}
}

for(int i=-20; i<20; i++){
if(i!=0){
line = new Line();
line.setLineCord(i, 0, -20f, i, 0.0f, 20f);
line.setColor("black");
line.setup();
line.draw(gl);
}
}
}
public void paintXYZ(GL10 gl){
// paint x axis
Line linex = new Line();
linex.setLineCord(-20f,0.0f,-0.0f,20f,0.0f,-0.0f);
linex.setColor("yellow");
linex.setup();
linex.draw(gl);


// paint y axis
Line lineY = new Line();
lineY.setLineCord(0.0f, -20f, -0.0f, 0.0f, 20f, -0.0f);
lineY.setColor("red");
lineY.setup();
lineY.draw(gl);

// paint Z axis
Line lineZ = new Line();
lineZ.setLineCord(0.0f, 0, -20f, 0.0f, 0.0f, 20f);
lineZ.setColor("green");
lineZ.setup();
lineZ.draw(gl);

}
public void onPress(int x, int y) {
prevPressX=x;
prevPressY=y;
}
}

GClements
08-23-2015, 09:07 AM
Matrix.multiplyMV(temp2, 0, matrixGrabber.mModelView, 0, temp, 0);

This shouldn't be here. It's transforming the un-projected coordinates from world space to eye space.

If you want eye-space coordinates, pass an identity matrix to gluUnProject() in place of the model-view matrix.

stavbodik
08-23-2015, 10:59 AM
Thanks for answere , can you please be more speciefic ? i need to transform screen space (mouse position) coordinates to camera/view coordinates system and then to my world space coordinates system . as i understand right now the ray i have is in camera/view space coordinates with depth of far/near plane and my problem is to find out where this ray intersect surface in world coordinates accordenly to mouse position and camera position ?

stavbodik
08-23-2015, 03:38 PM
Thanks i finaly solved it !!!

GLU.gluUnProject(winx, winy, 0, matrixGrabber.mModelView, 0, matrixGrabber.mProjection, 0, viewport, 0, temp2, 0);
//Matrix.multiplyMV(temp2, 0, matrixGrabber.mModelView, 0, temp, 0); // if we need the coordinatws in camera world coordinates system


now i know where exactly ray intersect with my surface ^^