1

I am new to OpenGL and I am trying to find a way to give a drawn object such as a triangle an ID of some kind. This way I can call the Id and give it motion as well as ad touch events.

I am not sure if this is the correct way or if there is a much better way to do this. I have objects made but do not know how to call them and give them motion or onClick event. I have looked around however a lot of the ways seem to be outdated and do not work or the link is now dead.

I have a Renderer as such:

public class MyGLRenderer implements GLSurfaceView.Renderer {
    private Triangle mTriangle;

    // Called once to set up the view's opengl es environment
    public void onSurfaceCreated(GL10 unused, EGLConfig config){

        //Set the background frame color
        GLES30.glClearColor(255.0f,255.0f,255.0f,0.0f);

        mTriangle = new Triangle();
    }

    // Called for each redraw of the view
    public void onDrawFrame(GL10 gl){
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        //Redraw background color
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);

        mTriangle.draw();
    }

    // Called if the geometry of the view changes (example is when the screen orientation changes from landscape to portrait
    public void onSurfaceChanged(GL10 unused, int width, int height){
        // Called if the geometry of the viewport changes
        GLES30.glViewport(0, 0, width, height);
    }

    public static int loadShader(int type, String shaderCode){

        // create a vertex shader type (GLES30.GL_VERTEX_SHADER)
        // or a fragment shader type (GLES30.GL_FRAGMENT_SHADER)
        int shader = GLES30.glCreateShader(type);

        // add the source code to the shader and compile it
        GLES30.glShaderSource(shader, shaderCode);
        GLES30.glCompileShader(shader);

        return shader;
    }
}

Surface View as Such:

public class MyGLSurfaceView extends GLSurfaceView {

    private final MyGLRenderer mRenderer;

    public MyGLSurfaceView(Context context, AttributeSet attrs){
        super(context, attrs);

        //Create an OpenGl 3.0 context
        setEGLContextClientVersion(3);

        mRenderer = new MyGLRenderer();

        //Set the Renderer for drawing on the GLSurfaceView
        setRenderer(mRenderer);

        //Render the view only when there is a change in the drawing data
        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
    }
}

And a Triangle Class as such:

public class Triangle {

    private FloatBuffer vertexBuffer;

    private final String vertexShaderCode =
            "attribute vec4 vPosition;" +
                    "void main() {" +
                    "  gl_Position = vPosition;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    private final int mProgram;

    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 3;
    static float triangleCoords[] = {   // in counterclockwise order:
            0.0f,  0.622008459f, 0.0f, // top
            -0.5f, -0.311004243f, 0.0f, // bottom left
            0.5f, -0.311004243f, 0.0f  // bottom right
    };

    // Set color with red, green, blue and alpha (opacity) values
    float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };

    public Triangle() {
        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (number of coordinate values * 4 bytes per float)
                triangleCoords.length * 4);
        // use the device hardware's native byte order
        bb.order(ByteOrder.nativeOrder());

        // create a floating point buffer from the ByteBuffer
        vertexBuffer = bb.asFloatBuffer();
       // add the coordinates to the FloatBuffer
       vertexBuffer.put(triangleCoords);
       // set the buffer to read the first coordinate
       vertexBuffer.position(0);

        int vertexShader = MyGLRenderer.loadShader(GLES30.GL_VERTEX_SHADER,
                vertexShaderCode);
        int fragmentShader =    MyGLRenderer.loadShader(GLES30.GL_FRAGMENT_SHADER,
                fragmentShaderCode);

        // create empty OpenGL ES Program
        mProgram = GLES30.glCreateProgram();

        // add the vertex shader to program
        GLES30.glAttachShader(mProgram, vertexShader);

        // add the fragment shader to program
        GLES30.glAttachShader(mProgram, fragmentShader);

        // creates OpenGL ES program executables
        GLES30.glLinkProgram(mProgram);
    }

    private int mPositionHandle;
    private int mColorHandle;

    private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

    public void draw() {
        // Add program to OpenGL ES environment
        GLES30.glUseProgram(mProgram);

        // get handle to vertex shader's vPosition member
        mPositionHandle = GLES30.glGetAttribLocation(mProgram, "vPosition");

        // Enable a handle to the triangle vertices
        GLES30.glEnableVertexAttribArray(mPositionHandle);

        // Prepare the triangle coordinate data
        GLES30.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                GLES30.GL_FLOAT, false,
                vertexStride, vertexBuffer);

        // get handle to fragment shader's vColor member
        mColorHandle = GLES30.glGetUniformLocation(mProgram, "vColor");

        // Set color for drawing the triangle
        GLES30.glUniform4fv(mColorHandle, 1, color, 0);

        // Draw the triangle
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vertexCount);

        // Disable vertex array
        GLES30.glDisableVertexAttribArray(mPositionHandle);
    }

I would like something to do the following:

drawnTriangleObject_ID.Add gravity to move down or up

drawnTriangleObject_ID.OnClick( // Do Something when this object is clicked )
halfer
  • 19,824
  • 17
  • 99
  • 186
L1ghtk3ira
  • 3,021
  • 6
  • 31
  • 70

1 Answers1

0

In your triangle class, add positioning data

float x = 0.0f;
float y = 0.0f;
float z = 0.0f;

and when drawing the triangle, you have to apply the translation

Matrix.setIdentityM(modelmatrix, 0);
Matrix.translateM(modelmatrix, 0, x, y, z);

then multiply the model matrix by the view matrix

Matrix.multiplyMM(resultmodelview, 0, viewmatrix, 0, modelmatrix, 0);

then multiply the result with projection matrix

Matrix.multiplyMM(resultresultprojection, 0, ProjectionMatrix, 0, resultmodelview, 0);

and publish it

World.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, resultresultprojection, 0);

This all supposing you have the frustum and projection and view matrix built already (which if you see the triangle, could be already done)..

Good luck and have fun coding !

As for the "OnClick" it is a bit more tricky: - Once the screen has been clicked, cast a ray from your XY plance (screen) to the 3D world. the ray (line) will have 2 coordinates, a start point and end point in form of X,Y,Z, or might have a start point and a vector(direction of the line)... On each frame you have to check if this ray is created, if it is, you need to use some Math to check if that line intersects your triangle (Don't forget to apply the rotation and translation of the triangle to it's vertices before checking intersection with the Ray). when the frame has been drawn don't forget to delete the ray

Rami Dabain
  • 4,709
  • 12
  • 62
  • 106
  • Any chance you van give an example for clicking using an array? Right now i found a way to use color picking but even when the whole traingle is green somehow the color values dont add up still. Not sure why – L1ghtk3ira Jul 23 '16 at 16:13
  • If you could somehow help with that or color picking id love to mark this answer correct as ut answers both parts of the question :) – L1ghtk3ira Jul 23 '16 at 16:14