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