Search code examples
androidglsurfaceview

passing instructions from UI thread to Rendering thread (GLSurfaceView)


The Setup : A RelativeLayout with a GLSurfaceView and a Button as shown in the image..

enter image description here

The Problem: Lets say I have other triangle models (The one in the picture being the initial model)... I wish to change the models cyclically on click of the button. Since button is on the UI thread and glSurfaceView runs on a separate thread, I don't exactly know how to pass the info/instruction to it. I know there is this thing called Handler in Android which might be useful in this case... But I need some help here..

Edit: If Handler is the right way, I need to know how to add Looper to that Handler... The documentation says add looper.prepare() at the start of run() method.. But the glSurfaceView creates thread implicitly, resulting in no run() method directly available..


Solution

  • I don't think it is necessary to use handlers to solve this issue but you may need to adjust the way you organise your classes.

    Here is an example of an organisational structure that might solve your issue:

    Activity Class

    public class MainActivity extends Activity {
    
        private int modelNumber = 0;
        private ArrayList<Model> models = new ArrayList<Model>();
        private YourRendererClass renderer;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            ...
    
            // Setup GLSurfaceView
            GLSurfaceView surface = new GLSurfaceView(this);
            setContentView(surface);
    
            renderer = new YourRendererClass();
            surface.setRenderer(renderer);
    
            // Set up models
            models.add(new Model(x, y, size etc..));
            models.add(new Model(x, y, size etc..));
            models.add(new Model(x, y, size etc..));
            etc.
    
            // Display first model
            renderer.setCurrentModel(models.get(modelNumber));
    
            ...
        }
    
        // Called by the button press:
        // Use android:onClick="onClick"
        // in your layout xml file within button
        public void onClick(View view){
            // Make it loop round
            modelNumber++;
            if(modelNumber>=models.size()){
                modelNumber=0;
            }
    
            // Display current model
            renderer.setCurrentModel(models.get(modelNumber));
    
        }
    }
    

    Renderer Class

    public class YourRendererClass implements Renderer {
    
        private Model currentModel;
    
        @Override
        public void onDrawFrame(GL10 gl) {
    
            // ** Your existing set-up code **//
    
            // Draw model
            if (currentModel!=null){
                currentModel.draw(gl);
            }
    
        }
    
        public void setCurrentModel(Model model){
            currentModel = model;
        }
    
    }
    

    Model class

    public class Model {
        // Holds model information
        private int size;
        private int x;
        private int y;
        // etc...
    
        public model(int x, int y, int size etc...){
            this.x=x;
            this.y=y;
            this.size=size;
            // etc....
        }
    
        public void draw(GL10 gl) {
            // ** Draw model based on model information fields above **
        }
    }
    

    The above code is untested as I don't have access to your drawing code but the structure should work if implemented correctly. I've tried to make it clear where you'll have to insert your own code to make it work. In particular I wasn't sure what defines each of your different models so you'll need to include sufficient local variables within the Model class to define them.

    I hope my answer helps, let me know if you have any questions.

    Tim