2011-02-14 16 views
23

Estoy escribiendo una API de visualización de información para Android y me encontré con un problema al tratar de colocar dos unidades de un GLSurfaceView personalizado en un diseño. El Custom GLSurfaceView en este punto es simplemente una extensión del GLSurfaceView para eliminar las posibles fallas causadas por los métodos personalizados.¿Cómo puedo usar múltiples componentes GLSurfaceView en el mismo diseño?

Cuando tengo ambos componentes agregados en el diseño y comienzo la aplicación se ejecuta. Pero nada se dibuja, parece que entra en un ciclo infinito. porque los mensajes de depuración dentro de los procesadores se imprimen en el LogCat. Sin embargo, funciona perfectamente bien si solo uso uno de los componentes personalizados GLSurfaceView.

He leído que hay un problema al usar GLSurfaceView en actividades múltiples y supongo que también se aplica cuando se utilizan dos de esos componentes al mismo tiempo. He intentado la solución publicada here pero tampoco puedo hacer que funcione.

Agradeceria cualquier ayuda. Elijo usar OpenGL para un mejor rendimiento, pero si no puedo usar varios componentes a la vez, supongo que tendré que usar Canvas en su lugar.

El manifiesto se ve de la siguiente manera:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <TextView android:text="@string/hello" android:id="@+id/TextView01" 
     android:layout_width="wrap_content" 
      android:layout_height="wrap_content" /> 

    <com.syntronic.vtadlib.VisualizationView android:id="@+id/glview" 
     android:layout_width="fill_parent" android:layout_height="300px" /> 


    <TextView android:text="@string/hello" android:id="@+id/TextView02" 
     android:layout_width="wrap_content" 
      android:layout_height="wrap_content" /> 

    <LinearLayout 
     android:orientation="vertical" android:layout_width="fill_parent" 
     android:layout_height="fill_parent"> 

     <com.syntronic.vtadlib.VisualizationView android:id="@+id/glview2" 
      android:layout_width="fill_parent" android:layout_height="fill_parent" /> 

    </LinearLayout> 

</LinearLayout> 

de la actividad es el código de la siguiente manera:

@Override 
public void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 

    setContentView(R.layout.main); 

    mSurfaceView = (VisualizationView) findViewById(R.id.glview); 
    mSurfaceView2 = (VisualizationView) findViewById(R.id.glview2); 

    //Enables debug flags for Errors 
    //mSurfaceView.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR); 
    //mSurfaceView2.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR); 

    mSurfaceView.setRenderer(new CoordinateSystemRenderer()); 
    mSurfaceView2.setRenderer(new CoordinateSystemRenderer()); 

} 

@Override 
protected void onPause() { 
    // TODO Auto-generated method stub 
    super.onPause(); 
    mSurfaceView.onPause(); 
    mSurfaceView2.onPause(); 
} 

@Override 
protected void onResume() { 
    // TODO Auto-generated method stub 
    super.onResume(); 
    mSurfaceView.onResume(); 
    mSurfaceView2.onResume(); 
} 

Me estoy perdiendo algo obvio? ¿O alguien puede explicar por qué no funciona?

+1

Lo primero que salta a la vista es que LinearLayout anidado está configurado en fill_parent. Verificaría que ambos GLSurfaceViews se distribuyan con una altura distinta de cero. Puede ser que ambos estén dibujando, pero uno tiene una altura de 0 píxeles y, por lo tanto, es invisible. –

+0

En lugar de dos 'GLSurfaceViews', puede ser mejor crear/administrar un hilo GL y el contexto usted mismo, aplicándolo a dos' SurfaceViews' (NO 'GLSurfaceViews'). Ver [discusión de Fadden y enlace a Grafika] (http://stackoverflow.com/a/22746240/199364). – ToolmakerSteve

Respuesta

0

Hay muchas cosas detrás de GLSurfaceView, incluida la administración de GLContext, estoy bastante seguro de que no podrá hacerlo funcionar, incluso si tiene éxito, podría tener problemas más inesperados más adelante. Así que realmente creo que no es la arquitectura de aplicación correcta.

8

[ACTUALIZACIÓN: Esta respuesta ya no es correcta, a partir de Android 5.0 (Lollipop). Vea fadden's answer para una discusión y enlaces. It was also incorrect as of Android 2.0, and apparently was only an issue for OVERLAPPING surfaces even before then.]

No puede colocar 2 SurfaceViews (SV) en una actividad. Para entender por qué debería saber cómo funcionan los SV.

Al crearlo y colocarlo en actividad, no se colocará en actividad (o en la parte superior), sino que se creará detrás de la actividad actual con una vista "transparente" creada en esa actividad.

En Android 4.0 (API 14) hay una nueva vista llamada TextureView No hay forma de crear algo así en las plataformas anteriores.

+1

¿Estás seguro de eso? Solo pensé que la limitación es que no puedes colocarlos uno encima del otro o superponerse. Siendo dicho que no puedes mostrar un video sobre una vista de superficie ya que la videoview extiende la vista superficial ... – WarrenFaith

+0

Sí, estoy seguro. Puede usar solo una instancia de SV a la vez. – pepyakin

+0

¿Podría proporcionar una fuente si tiene una? Estoy muy interesado en el tema SV completo. ¡Gracias! – WarrenFaith

0

Puede que desee investigar la superposición/colocación de sus modelos en el área 'correcta' de la pantalla utilizando una pantalla completa GLSurfaceView. Es posible que desee armar algún tipo de marco de diseño para hacerlo más simple, o tal vez usar múltiples ventanas gráficas en la pantalla completa GLSurfaceView. No he probado esto en OpenGL ES, pero generalmente cualquiera de estos métodos se usaría para representar múltiples vistas del mismo o incluso muchos modelos diferentes en una sola aplicación en un sistema de escritorio en lugar de usar múltiples GLContexts (si eso es lo que es pasando detrás de escena aquí).

2

¿Cuál es la implementación de CoordinateSystemRenderer?

Hoy cumplí con el mismo requisito y lo intenté, realmente funciona, es decir, puede poner 2 GLSurfaceView en la misma actividad.

Algo necesita ser notado,

  1. En GLRender, cuando onSurfaceChanged se invoca, debe cambiar el tamaño de la ventana gráfica
  2. Con 2 GLSurfaceView, el hilo rendir será de 2, por lo que la sincronización se produjo tema. Depende de su implementación de .

No es una prueba rápida para utilizar la API de demostración Android SDK en GLSurfaceViewActivity

/* 
* Copyright (C) 2007 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/ 

package com.example.android.apis.graphics; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

import android.opengl.GLSurfaceView; 

/** 
* Render a pair of tumbling cubes. 
*/ 

public class CubeRenderer implements GLSurfaceView.Renderer 
{ 
    boolean isReverse = false; 

    public CubeRenderer(boolean useTranslucentBackground, boolean isReverse) 
    { 
     mTranslucentBackground = useTranslucentBackground; 
     mCube = new Cube(); 
     this.isReverse = isReverse; 
    } 

    public CubeRenderer(boolean useTranslucentBackground) 
    { 
     this(useTranslucentBackground, false); 
    } 

    public void onDrawFrame(GL10 gl) 
    { 
     /* 
     * Usually, the first thing one might want to do is to clear the screen. The most efficient way of doing this is 
     * to use glClear(). 
     */ 

     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 

     /* 
     * Now we're ready to draw some 3D objects 
     */ 

     gl.glMatrixMode(GL10.GL_MODELVIEW); 
     gl.glLoadIdentity(); 
     gl.glTranslatef(0, 0, -3.0f); 
     gl.glRotatef(mAngle, 0, 1, 0); 
     gl.glRotatef(mAngle * 0.25f, 1, 0, 0); 

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

     mCube.draw(gl); 

     gl.glRotatef(mAngle * 2.0f, 0, 1, 1); 
     gl.glTranslatef(0.5f, 0.5f, 0.5f); 

     mCube.draw(gl); 

     if (isReverse) 
     { 
      mAngle -= 1.2f; 
     } 
     else 
     { 
      mAngle += 1.2f; 
     } 
    } 

    public void onSurfaceChanged(GL10 gl, int width, int height) 
    { 
     System.out.println("Joey's Log width : " + width + " height : " + height); 
     gl.glViewport(0, 0, width, height); 

     /* 
     * Set our projection matrix. This doesn't have to be done each time we draw, but usually a new projection needs 
     * to be set when the viewport is resized. 
     */ 

     float ratio = (float) width/height; 
     gl.glMatrixMode(GL10.GL_PROJECTION); 
     gl.glLoadIdentity(); 
     gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 
    } 

    public void onSurfaceCreated(GL10 gl, EGLConfig config) 
    { 
     /* 
     * By default, OpenGL enables features that improve quality but reduce performance. One might want to tweak that 
     * especially on software renderer. 
     */ 
     gl.glDisable(GL10.GL_DITHER); 

     /* 
     * Some one-time OpenGL initialization can be made here probably based on features of this particular context 
     */ 
     gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); 

     if (mTranslucentBackground) 
     { 
      gl.glClearColor(0, 0, 0, 0); 
     } 
     else 
     { 
      gl.glClearColor(1, 1, 1, 1); 
     } 
     gl.glEnable(GL10.GL_CULL_FACE); 
     gl.glShadeModel(GL10.GL_SMOOTH); 
     gl.glEnable(GL10.GL_DEPTH_TEST); 
    } 

    private boolean mTranslucentBackground; 

    private Cube mCube; 

    private float mAngle; 
} 


------------------------------------------------------------------------------------------ 
/* 
* Copyright (C) 2007 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/ 

package com.example.android.apis.graphics; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

import android.opengl.GLSurfaceView; 

/** 
* Render a pair of tumbling cubes. 
*/ 

public class CubeRenderer implements GLSurfaceView.Renderer { 
    boolean isReverse = false; 
    public CubeRenderer(boolean useTranslucentBackground,boolean isReverse) { 
     mTranslucentBackground = useTranslucentBackground; 
     mCube = new Cube(); 
     this.isReverse = isReverse; 
    } 

    public CubeRenderer(boolean useTranslucentBackground) 
    { 
     this(useTranslucentBackground, false); 
    } 

    public void onDrawFrame(GL10 gl) { 
     /* 
     * Usually, the first thing one might want to do is to clear 
     * the screen. The most efficient way of doing this is to use 
     * glClear(). 
     */ 

     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 

     /* 
     * Now we're ready to draw some 3D objects 
     */ 

     gl.glMatrixMode(GL10.GL_MODELVIEW); 
     gl.glLoadIdentity(); 
     gl.glTranslatef(0, 0, -3.0f); 
     gl.glRotatef(mAngle,  0, 1, 0); 
     gl.glRotatef(mAngle*0.25f, 1, 0, 0); 

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

     mCube.draw(gl); 

     gl.glRotatef(mAngle*2.0f, 0, 1, 1); 
     gl.glTranslatef(0.5f, 0.5f, 0.5f); 

     mCube.draw(gl); 

     if (isReverse) 
     { 
      mAngle -= 1.2f; 
     } 
     else 
     { 
      mAngle += 1.2f; 
     } 
    } 

    public void onSurfaceChanged(GL10 gl, int width, int height) { 
     System.out.println("Joey's Log width : " + width + " height : " + height); 
     gl.glViewport(0, 0, width, height); 

     /* 
      * Set our projection matrix. This doesn't have to be done 
      * each time we draw, but usually a new projection needs to 
      * be set when the viewport is resized. 
      */ 

     float ratio = (float) width/height; 
     gl.glMatrixMode(GL10.GL_PROJECTION); 
     gl.glLoadIdentity(); 
     gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 
    } 

    public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
     /* 
     * By default, OpenGL enables features that improve quality 
     * but reduce performance. One might want to tweak that 
     * especially on software renderer. 
     */ 
     gl.glDisable(GL10.GL_DITHER); 

     /* 
     * Some one-time OpenGL initialization can be made here 
     * probably based on features of this particular context 
     */ 
     gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, 
       GL10.GL_FASTEST); 

     if (mTranslucentBackground) { 
      gl.glClearColor(0,0,0,0); 
     } else { 
      gl.glClearColor(1,1,1,1); 
     } 
     gl.glEnable(GL10.GL_CULL_FACE); 
     gl.glShadeModel(GL10.GL_SMOOTH); 
     gl.glEnable(GL10.GL_DEPTH_TEST); 
    } 
    private boolean mTranslucentBackground; 
    private Cube mCube; 
    private float mAngle; 
} 
+0

¿Cómo es relevante este código? No muestra dos GLSurfaceViews. Simplemente muestra una vista única, dibujando dos cubos. – ToolmakerSteve

-1

Puede tener múltiples GLSurfaceViews activa y visible en una actividad. Cada vista tiene su propio contexto GL.

+0

OP intentó utilizar dos GLSurfaceViews y tiene problemas para hacerlo funcionar. ¿Cómo ayuda esta "respuesta"? – ToolmakerSteve

0

Aquí hay una forma alternativa de hacerlo. Descargue la muestra de los documentos de Android aquí: http://developer.android.com/shareables/training/OpenGLES.zip En este archivo comprimido, verá 2 proyectos. Abra el proyecto: HelloOpenGLES20 y reemplace la clase 'MyGLRenderer' con la que figura a continuación y ejecute el proyecto.

package com.example.android.opengl; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

import android.opengl.GLES20; 
import android.opengl.GLSurfaceView; 
import android.opengl.Matrix; 
import android.util.Log; 

public class MyGLRenderer implements GLSurfaceView.Renderer { 

    private static final String TAG = "MyGLRenderer"; 
    private Triangle[] mTriangle = new Triangle[2]; 
    private final float[] mMVPMatrix = new float[16]; 
    private final float[] mProjectionMatrix = new float[16]; 
    private final float[] mViewMatrix = new float[16]; 
    private final float[] mRotationMatrix = new float[16]; 

    private float mAngle; 

    @Override 
    public void onSurfaceCreated(GL10 unused, EGLConfig config) { 

     GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
     mTriangle[0] = new Triangle(); 
     mTriangle[1] = new Triangle(); 

    } 

    @Override 
    public void onDrawFrame(GL10 unused) { 

     final float[] scratch = new float[16]; 

     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 

     Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 

     Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); 

     for(int i = 0; i < 2; i++) { 

      if(i % 2 == 0) { 

       Matrix.setRotateM(mRotationMatrix, 0, mAngle/2f, 0, 0, 1.0f); 

      } 
      else { 

       Matrix.setRotateM(mRotationMatrix, 0, mAngle/4f, 0, 0, 1.0f); 

      } 

      Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0); 

      mTriangle[i].draw(scratch); 

     }//End for(int i = 0; i < 2; i++) 

    }//End public void onDrawFrame(GL10 unused) 

    @Override 
    public void onSurfaceChanged(GL10 unused, int width, int height) { 

     GLES20.glViewport(0, 0, width, height); 
     float ratio = (float) width/height; 
     Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7); 

    } 

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

     int shader = GLES20.glCreateShader(type); 
     GLES20.glShaderSource(shader, shaderCode); 
     GLES20.glCompileShader(shader); 

     return shader; 

    } 

    public static void checkGlError(String glOperation) { 

     int error; 

     while((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { 

      Log.e(TAG, glOperation + ": glError " + error); 
      throw new RuntimeException(glOperation + ": glError " + error); 

     } 

    } 

    public float getAngle() { 
     return mAngle; 
    } 


    public void setAngle(float angle) { 
     mAngle = angle; 
    } 

} 

Por lo que entiendo, OpenGLES está diseñado para usar solo una vista pero con objetivos de Render potencialmente múltiples. Aunque debo administrarlo, no estoy seguro de que lo que estás tratando de hacer esté mal o no. Soy un poco nuevo para OpenGLES. Tengo una biblioteca de código abierto OpenGL en bitbucket. Puede obtener algunas ideas de él: https://bitbucket.org/warwick/hacergestov2, es una biblioteca de gestos.

+0

Explique: ¿cómo es esta "forma alternativa de hacerlo"? El "it" discutido por OP está convirtiendo GL en dos vistas diferentes dentro de un diseño. ¿Qué estás proponiendo como una solución alternativa? – ToolmakerSteve

Cuestiones relacionadas