OpenGLES - Create objects at runtime
android, java, opengl-es, opengl-es-2.0
Solution
You can only make calls to OpenGL within an OpenGL context.
There are 3 methods in which this context exists:
1) `onSurfaceCreated` - when context is created/recreated - you should load resources here
2) `onSurfaceChanged` - after creation and on a surface resize - you should assign size-dependent variables here
3) `onDrawFrame` - here rendering is executed - here you should execute all drawing commands
If you try to execute OpenGL calls outside of the context, most likely the code will fail to execute correctly.
Problem
I'm new to OpenGL and started with the small tutorial from dev.android.com. The sample code includes this `Square` class for a square geometry. The object will be created in the `onSurfaceCreated()` method and drawn every frame using `onDrawFrame()`. Here is the example code of the `Square` (constructor and draw-method): ``` public Square() { // initialize vertex byte buffer for shape coordinates ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4); bb.order(ByteOrder.nativeOrder()); vertexBuffer = bb.asFloatBuffer(); vertexBuffer.put(squareCoords); vertexBuffer.position(0); // initialize byte buffer for the draw list ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2); dlb.order(ByteOrder.nativeOrder()); drawListBuffer = dlb.asShortBuffer(); drawListBuffer.put(drawOrder); drawListBuffer.position(0); // prepare shaders and OpenGL program int vertexShader = MyGLRenderer.loadShader( GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = MyGLRenderer.loadShader( GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program GLES20.glLinkProgram(mProgram); // create OpenGL program executables } public void draw(float[] mvpMatrix) { // Add program to OpenGL environment GLES20.glUseProgram(mProgram); // get handle to vertex shader's vPosition member mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); // Enable a handle to the triangle vertices GLES20.glEnableVertexAttribArray(mPositionHandle); // Prepare the triangle coordinate data GLES20.glVertexAttribPointer( mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); // get handle to fragment shader's vColor member mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); // Set color for drawing the triangle GLES20.glUniform4fv(mColorHandle, 1, color, 0); // get handle to shape's transformation matrix mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); MyGLRenderer.checkGlError("glGetUniformLocation"); // Apply the projection and view transformation GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); MyGLRenderer.checkGlError("glUniformMatrix4fv"); // Draw the square GLES20.glDrawElements( GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer); // Disable vertex array GLES20.glDisableVertexAttribArray(mPositionHandle); } ``` My question is now: how can I create the object not at `onSurfaceCreated()` but after a touch event? I tried to define a `Square` variable but not initialize it at `onSurfaceCreated()`, then check if the object is null before drawing it. After the touch I called: ``` mSquare = new Square(); ``` I know it's not a good way of implementing this, but I just wanted to try if it works. I would have created a list of drawable elements and run through it in the `onDrawFrame()` method, calling every `draw()` from the list objects. But since this method causes the program to crash, I don't know how to go on.