androidopengl-es3dpickingray-picking

Android Open Gl Object Selection


In open GL there is a term called picking. Which is used to determine which object on the screen was selected. Can someone explain to me what the difference between using picking and putting a touch based listener in each and every instance of a object ex. A Cube class.

Hypothetically; What i want to do is demonstrate multiple cubes on a screen randomly. I figured if I give the Cube class a listener, upon touching the cube the listener should fire off accordingly for each cube pressed.

This is the code I would add the listener to. Would this be possible or is picking necessary?

public class Cube extends Shapes {
private FloatBuffer mVertexBuffer;
private FloatBuffer mColorBuffer;
private ByteBuffer mIndexBuffer;
private Triangle[] normTris = new Triangle[12];
private Triangle[] transTris = new Triangle[12];

// every 3 entries represent the position of one vertex
private float[] vertices =
        {
                -1.0f, -1.0f, -1.0f,
                1.0f, -1.0f, -1.0f,
                1.0f, 1.0f, -1.0f,
                -1.0f, 1.0f, -1.0f,
                -1.0f, -1.0f, 1.0f,
                1.0f, -1.0f, 1.0f,
                1.0f, 1.0f, 1.0f,
                -1.0f, 1.0f, 1.0f
        };

// every 4 entries represent the color (r,g,b,a) of the corresponding vertex in      vertices
 private float[] colors =
        {
                1.0f, 0.0f, 0.0f, 1.0f,
                0.0f, 1.0f, 0.0f, 1.0f,
                0.0f, 0.0f, 1.0f, 1.0f,
                1.0f, 0.0f, 0.0f, 1.0f,
                0.0f, 1.0f, 0.0f, 1.0f,
                0.0f, 0.0f, 1.0f, 1.0f,
                0.0f, 0.0f, 0.0f, 1.0f,
                1.0f, 1.0f, 1.0f, 1.0f
        };
// every 3 entries make up a triangle, every 6 entries make up a side
private byte[] indices =
        {
                0, 4, 5, 0, 5, 1,
                1, 5, 6, 1, 6, 2,
                2, 6, 7, 2, 7, 3,
                3, 7, 4, 3, 4, 0,
                4, 7, 6, 4, 6, 5,
                3, 0, 1, 3, 1, 2
        };
private float[] createVertex(int Index)
{
   float[] vertex = new float[3];
   int properIndex = Index * 3;
   vertex[0] = vertices[properIndex];
   vertex[1] = vertices[properIndex + 1];
   vertex[2] = vertices[properIndex + 2];
   return vertex;
}

public Triangle getTriangle(int index){
    Triangle tri = null;
   //if(index >= 0 && index < indices.length){
       float[] v1 = createVertex(indices[(index * 3) + 0]);
       float[] v2 = createVertex(indices[(index * 3) + 1]);
       float[] v3 = createVertex(indices[(index * 3) + 2]);
       tri = new Triangle(v1, v2, v3);
  // }
       return tri;

}

public int getNumberOfTriangles(){
    return indices.length / 3;
}

public boolean checkCollision(Ray r, OpenGLRenderer renderer){

    boolean isCollide = false;

    int i = 0; 
    while(i < getNumberOfTriangles() && !isCollide){
        float[] I = new float[3];
        if(Shapes.intersectRayAndTriangle(r, transTris[i], I) > 0){
            isCollide = true;
        }

        i++;
    }


    return isCollide;
}

public void translate(float[] trans){
    for(int i = 0; i < getNumberOfTriangles(); i++){
        transTris[i].setV1(Vector.addition(transTris[i].getV1(), trans));
        transTris[i].setV2(Vector.addition(transTris[i].getV2(), trans));
        transTris[i].setV3(Vector.addition(transTris[i].getV3(), trans));
    }
}

public void scale(float[] scale){
    for(int i = 0; i < getNumberOfTriangles(); i++){
        transTris[i].setV1(Vector.scalePoint(transTris[i].getV1(), scale));
        transTris[i].setV2(Vector.scalePoint(transTris[i].getV2(), scale));
        transTris[i].setV3(Vector.scalePoint(transTris[i].getV3(), scale));
    }
}

public void resetTransfomations(){
    for(int i = 0; i < getNumberOfTriangles(); i++){
        transTris[i].setV1(normTris[i].getV1().clone());
        transTris[i].setV2(normTris[i].getV2().clone());
        transTris[i].setV3(normTris[i].getV3().clone());
    }
}

public Cube()
{
    Buffer[] buffers = super.getBuffers(vertices, colors, indices);
    mVertexBuffer = (FloatBuffer) buffers[0];
    mColorBuffer = (FloatBuffer) buffers[1];
    mIndexBuffer = (ByteBuffer) buffers[2];
}

public Cube(float[] vertices, float[] colors, byte[] indices)
{
    if(vertices != null) {
        this.vertices = vertices;
    }
    if(colors != null) {
        this.colors = colors;
    }
    if(indices != null) {
        this.indices = indices;
    }
    Buffer[] buffers = getBuffers(this.vertices, this.colors, this.indices);
    mVertexBuffer = (FloatBuffer) buffers[0];
    mColorBuffer = (FloatBuffer) buffers[1];
    mIndexBuffer = (ByteBuffer) buffers[2];

    for(int i = 0; i < getNumberOfTriangles(); i++){
        normTris[i] = getTriangle(i);
        transTris[i] = getTriangle(i);
    }
}

public void draw(GL10 gl)
{
    gl.glFrontFace(GL10.GL_CW);

    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
    gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

    // draw all 36 triangles
    gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);

    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
}
}

Solution

  • Using a Listener does not work in this case.

    If you for example take a look at the onTouchListener. This is basically an interface providing just a single method onTouch(). Now when android is processing touch inputs and the target view was touched it knows that your listener can be informed about the touch by calling onTouch() of your listener.

    When using OpenGL you have the problem, that noone handles the touch input inside your opengl surface. You have to do it yourself. So there is noone who will call your listener.

    Why? What you render inside your gl surface is up to you. You only know what the actual geometry is and therefore you are the only one who can decide which object was selected.

    You basically have two options to do the selection:

    For most applications I would prefer the second solution.