Saturday, February 13, 2016

3d - OpenGL ES 2.0 gluUnProject


I've spent more time than I should trying to get my ray picking program working. I'm pretty convinced my math is solid with respect to line plane intersection, but I believe the problem lies with the changing of the mouse screen touch into 3D world space.


Heres my code:


    public void passTouchEvents(MotionEvent e){



int[] viewport = {0,0,viewportWidth,viewportHeight};
float x = e.getX(), y = viewportHeight - e.getY();

float[] pos1 = new float[4];
float[] pos2 = new float[4];
GLU.gluUnProject( x, y, 0.0f,
mViewMatrix, 0,
mProjectionMatrix, 0,
viewport, 0,
pos1, 0);



GLU.gluUnProject( x, y, 1.0f,
mViewMatrix, 0,
mProjectionMatrix, 0,
viewport, 0,
pos2, 0);
}

Just as a reference I've tried transforming the coordinates 0,0,0 and got an offset. It would be appreciated if you would answer using OpenGL ES 2.0 code.




Answer



The GLU library was made with 1.1, but the gluUnProject can still be used in 2.0 as long as you have the correct values. The 4th parameter should be the multiplied model view matrix, not just the model matrix or just the view matrix. Also, the calculated pos1 and pos2 values have to be converted from 4D vectors to 3D vectors by dividing them by their w component. According to this: http://forums.create.msdn.com/forums/p/10940/70238.aspx.
Here's how I did it for Android:


public void singleTouch(float x, float y)
{
float[] nearPos = new float[4];
float[] farPos = new float[4];
PointF touchPoint;

boolean unprojectedNear = (GLU.gluUnProject(x, y, 0,

floorViewDrawable.getMvMatrix(), 0, projectionMatrix, 0,
viewport, 0, nearPos, 0) == GLES10.GL_TRUE);
boolean unprojectedFar = (GLU.gluUnProject(x, y, 1,
floorViewDrawable.getMvMatrix(), 0, projectionMatrix, 0,
viewport, 0, farPos, 0) == GLES10.GL_TRUE);

if (unprojectedNear && unprojectedFar)
{
// To convert the transformed 4D vector to 3D, you must divide
// it by the W component

nearPos = convertTo3d(nearPos);
farPos = convertTo3d(farPos);

// Use the near and far instead of the assumed camera position
float floorViewX = (((farPos[0] - nearPos[0]) / (perspectiveFar - perspectiveNear)) * nearPos[2]) + nearPos[0];
float floorViewY = ((((farPos[1] - nearPos[1]) / (perspectiveFar - perspectiveNear)) * nearPos[2]) + nearPos[1]) + (2f * positionY);

touchPoint = new PointF(floorViewX, floorViewY);

if (floorViewDrawable.getArea()

.contains(touchPoint.x, touchPoint.y))
{
floorViewPoint = new PointF(nearPos[0], nearPos[1]);
Log.e(HostessMobileApp.TAG, "floorViewTouched");
}
}
}

private float[] convertTo3d(float[] vector) {
float[] result = new float[4];


for (int index = 0; index < vector.length; index++) {
result[index] = vector[index] / vector[3];
}

return result;
}

Here's a resource for explaining gluUnproject if anybody needs it. http://myweb.lmu.edu/dondi/share/cg/unproject-explained.pdf


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...