Pasar variables entre el renderizador y otra clase con queueEvent ()

Quiero pasar a mi procesador algunos valores de otra clase. Después de que el renderizador haya calculado los valores, tengo un mutex en una clase auxiliar que debería decirme que el renderizador ha terminado de calcular para poder continuar con estos nuevos valores. Puedo pasar el procesador de los valores sin problemas, pero no puedo averiguar cómo recuperarlos. Actualmente utilizo algunas variables estáticas, pero después de que sean cambiadas por el renderizador, parece que se pierden. No son visibles en mi otra clase. Ejemplo:

Una clase

public class View extends SurfaceView{ private void doSomething(){ glSurfaceView.queueEvent(new Runnable() { @Override public void run() { //.. renderer.calculate(stack); } }); } private void doAnotherThing(){ //Never happens: if(Helper.hasCalculated){ /... } } 

}

En mi renderizador :

 public class MyRenderer implements GLSurfaceView.Renderer{ private void calculate(Stack stack){ Helper.hasCalculated = true } } 

Mi clase de ayuda:

 public class Helper{ public static volatile boolean hasCalculated = false; } 

HasCalculated definitivamente se establece en true en el renderizador, pero mi otra clase siempre lo ve como falso. ¿Alguna idea de por qué? Mi mejor conjetura es que es porque está en otro hilo, pero ¿cómo resolvería eso? Si hay un acercamiento más limpio y más seguro, yo sería feliz oírlo.

Puede mantener su renderizador como una variable en su actividad (no solo haga mGLView.setRenderer(new MyRenderer()); como mucha gente lo hace, sino MyRenderer myRenderer = new MyRenderer(); mGLView.setRenderer(myRenderer); ). Entonces usted puede comunicarse con su procesador fácilmente a través de llamadas de método. El problema sólo se reduce a la comunicación entre hilos. He puesto dos ejemplos a continuación, uno con la comunicación entre un hilo no UI, el hilo GL y el hilo principal de interfaz de usuario. El segundo ejemplo es sólo para la comunicación entre el subproceso GL y el subproceso UI

 public class Test3D extends Activity{ private MyRenderer renderer; // keep hold of the renderer as a variable in activity private MyAsyncTask gameLoop; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); myRenderer = new MyRenderer(); // create the renderer object GLSurfaceView mGLView = (GLSurfaceView)findViewById(R.id.glsurfaceview1); mGLView.setEGLConfigChooser(true); mGLView.setRenderer(myRenderer); // set the surfaceView to use the renderer gameLoop = new MyAsyncTask(); gameLoop.execute(); // start a new, non-UI, thread to do something } /// non-UI thread (inner class of my Test3D activity) class MyAsyncTask extends AsyncTask<Void, Void, Void>{ @Override protected Void doInBackground(Void... arg0) { myRenderer.startCalc(); // tell renderer to start calculation while(!myRenderer.isFinishedCalc()){ // waiting for calc to finish, but not blocking UI thread try { long x = 1000; Thread.sleep(x); // sleep the thread for x amount of time to save cpu cycles } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } publishProgress(null); // when calculation has finished, we will drop out of the loop // and update the UI } protected void onProgressUpdate(Void... progress) { // update UI } } } 

Entonces en renderer

 public class MyRenderer implements Renderer{ private boolean startCalc = false; private boolean finishCalc = false; public void startCalc(){ finishCalc = false; startCalc = true; } public boolean isFinishedCalc(){ return finishCalc; } public void onDraw(GL10 gl){ if(startCalc){ // do calculation using GL handle // always performed in the GL thread finishCalc = true; startCalc = false; } // draw } } 

He utilizado banderas en el ejemplo de renderizado de arriba, pero sería bastante sencillo convertirlo en una cola, si, digamos, querías decirle al renderizador "cargar esta matriz de modelos". Puesto que usted tiene que cargar los modelos (o al menos las texturas) en el hilo GL usando el identificador GL, puede tener otras clases e hilos hacer su lógica y tener sólo el material GL hecho en el hilo GL


Como alternativa, si sólo desea actualizar el subproceso de interfaz de usuario después de que se realiza el cálculo, en lugar de interactuar con otros subprocesos:

 public class MyRenderer implements Renderer{ private Handler handler = null; public static final int CALC_FINISHED = 1; public void startCalc(Handler handler){ this.handler = handler; } public void onDraw(GL10 gl){ if(handler!=null){ // do calculation using GL handle int flag = MyRenderer.CALC_FINISHED; handler.dispatchMessage(Message.obtain(handler, flag)); // adds a message to the UI thread's message queue handler = null; } // draw } } 

Y luego desde cualquier lugar:

 myRenderer.startCalc(new Handler(){ public void handleMessage (Message msg){ if(msg.what==MyRenderer.CALC_FINISHED){ // Update UI // this code will always be executed in the UI thread } } }); 
  • Combinación de SurfaceView con otras vistas, como TextView y botones
  • ¿Por qué eclipsar mi textura con el color?
  • Compartir recursos entre el contexto de OpenGL en Android
  • ¿Cómo usar MediaMuxer / MediaCodec InputSurface con GLSurfaceView?
  • Pinch-Zoom con GLSurfaceView
  • ¿Es mejor usar GL_FIXED o GL_FLOAT en Android
  • Animación esquelética en GPU para Android OpenGL ES
  • Compresión de textura de Android OpenGL
  • ¿Cómo puedo recursivamente dibujar un mapa hexadecimal en opengl?
  • Android Opengl-es carga un poder de 2 no-textura
  • OpenGL mal rendimiento en Android Gingerbread
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.