2
votes

I'm trying to implement ray-picking in OpenGL ES 2.0 to determine if an object has been clicked or not. So far I'm just trying to check if a specific triangle has been pressed. I`m using this site as a motivation http://android-raypick.blogspot.ca/2012/04/first-i-want-to-state-this-is-my-first.html

This is what I have so far:

public void onClick(float x, float y)
{
    float[] temp = new float[4];
    float[] temp2 = new float[4];
    System.out.println("X coordinate: " + x);
    System.out.println("Y coordinate: " + y);
    float[] pos = new float[4];

    y = (float) viewport[3] - y;

    int res = GLU.gluUnProject(x, y, 1.0f, 
            mMVPMatrix, 0,
            mProjectionMatrix, 0,
            viewport, 0, 
            temp, 0);

    Matrix.multiplyMV(temp2, 0, mMVPMatrix, 0, temp, 0);
    float[] nearCoOrds = new float[3];

    if(res == GLES20.GL_TRUE)
    {
        nearCoOrds[0] = temp2[0] / temp2[3];
        nearCoOrds[1] = temp2[1] / temp2[3];
        nearCoOrds[2] = temp2[2] / temp2[3];
        System.out.println("Near0: " + nearCoOrds[0]);
        System.out.println("Near1: " + nearCoOrds[1]);
        System.out.println("Near2: " + nearCoOrds[2]);
    }

    res = GLU.gluUnProject(x, y, 0,
            mMVPMatrix, 0,
            mProjectionMatrix, 0,
            viewport, 0,
            temp, 0);

    Matrix.multiplyMV(temp2,0,mMVPMatrix, 0, temp, 0);
    float[] farCoOrds = new float[3];

    if(res == GLES20.GL_TRUE)
    {
        farCoOrds[0] = temp2[0] / temp2[3];
        farCoOrds[1] = temp2[1] / temp2[3];
        farCoOrds[2] = temp2[2] / temp2[3];
        System.out.println("Far0: " + farCoOrds[0]);
        System.out.println("Far1: " + farCoOrds[1]);
        System.out.println("Far2: " + farCoOrds[2]);
    }

    float[] coords = new float[3];

    coords[0] = farCoOrds[0]-nearCoOrds[0];
    coords[1] = farCoOrds[1]-nearCoOrds[1];
    coords[2] = farCoOrds[2]-nearCoOrds[2];

    System.out.println("REAL COORDS 0: " + coords[0]);
    System.out.println("REAL COORDS 1: " + coords[1]);
    System.out.println("REAL COORDS 2: " + coords[2]);

}

The x and the y float is the x and the y coordinate of where the finger pressed the screen. The function onClick is called from the MainActivity.

In

 GLU.gluUnProject(x, y, 1.0f, 
            mMVPMatrix, 0,
            mProjectionMatrix, 0,
            viewport, 0, 
            temp, 0);

mMVPMatrix is the Modelview Matrix. mProjectionMatrix is the Projection Matrix and the viewport has the values {0,0,screenhwidth,screenheight}.

Example of output I get is (touched around middle of the screen):

REAL COORDS 0: -0.21542415
REAL COORDS 1: 0.31117013
REAL COORDS 2: 9.000003

My question/topic is that I don't know if I'm on the right track here? Have I gotten the right idea or does it seem that I have misunderstood something? Or are there any other ways I can achieve touch detection on triangles?

Thanks for any help or guidance!

2
By looking only at some sample coordinates I can't tell you whether your results are correct or not.keaukraine

2 Answers

1
votes

There is an excellent OpenGL framework for Android called Rajawali. It supports object picking, the sample code looks very simple, you should try it.

0
votes

I believe you many have misunderstood a bit (or maybe I have^^). The near and far coordinates are used to construct your ray segment to testing against your polys/hitboxes. The segment is in whats called world space and to test against your vertices/models you will need to convert them from model space(what they are in when loaded) to world space by multiplying them by their mModelView matrix (has all of their transforms, rotations, etc in it). That article you linked seems to take it through that point^^ Make sense or have I missed something?

bonus link for you: http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter0.htm