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 :
[ATTACH=CONFIG]1228[/ATTACH]
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 .
[ATTACH=CONFIG]1229[/ATTACH]
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;
}
}