2016-04-18 13 views
0

Hinweis Ich bin neu in Android und OpenGL.Rotierende Android Kamera Vorschau um 90 Grad auf GLSurfaceView mit OpenGL 2.0 APIs

Ich benutze den Code, um Android Camera Preview auf dem Bildschirm anzuzeigen. Ich möchte den Kamerawinkel mit OpenGL 2.0 um 90 Grad drehen (um meiner Kamera in Hochformat zu entsprechen, da sich meine App im Hochformat befindet) in der unten stehenden Klasse "MainRenderer". Ich habe in Android camera rotate geschaut, aber es hat keine Rotation ausgeführt.

Einstellung "android: rotation = '90 '" im Layout xml rotiert Oberflächenansicht, aber ergibt schwarze Oberfläche - keine Kameravorschau.

Da ich GLSurfaceView benutze, möchte ich nun die Kameravorschau in OpenGL 2.0 drehen, anstatt Matrixrotation und Anpassung des Seitenverhältnisses durchzuführen. Es gab wenige Beiträge wie How to rotate a camera view in OpenGL 2.0 ES und http://www.programcreek.com/java-api-examples/index.php?class=android.opengl.Matrix&method=rotateM aber ich konnte nicht API mit dem Code unten aufgrund meiner Unkenntnis mit OpenGL beziehen (die ich hoffe, bald bekannt zu werden).

Ich verstehe, dass vielleicht rotateM und translateM (raten mit ModelViewProjection Matrix) tun können, was ich vorhabe zu erreichen.

Ich frage mich, vtmp und ttmp müssen möglicherweise unten geändert werden?

Jede Hilfe wird geschätzt.

Der ursprüngliche Code ist aus http://maninara.blogspot.com/2012/09/render-camera-preview-using-opengl-es.html

// in Manifest

< uses-feature android:glEsVersion="0x00020000" android:required="true"/> 
< uses-feature android:name="android.hardware.camera"/> 
< uses-permission android:name="android.permission.CAMERA"/> 
< uses-permission android:name="android.permission.WAKE_LOCK"/> 
... android:screenOrientation="landscape" ... // activity property 

// Aktivität

public class MainActivity extends Activity { 
    private MainView mView; 
    private WakeLock mWL; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    // full screen & full brightness 
    requestWindowFeature (Window.FEATURE_NO_TITLE); 
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 
    mWL = ((PowerManager)getSystemService (Context.POWER_SERVICE)).newWakeLock(PowerManager.FULL_WAKE_LOCK, "WakeLock"); 
    mWL.acquire(); 
    mView = new MainView(this); 
    setContentView (mView); 
    } 

    @Override 
    protected void onPause() { 
    if (mWL.isHeld()) 
     mWL.release(); 
    mView.onPause(); 
    super.onPause(); 
    } 

    @Override 
    protected void onResume() { 
    super.onResume(); 
    mView.onResume(); 
    if(!mWL.isHeld()) mWL.acquire(); 
    } 
} 

// Ansicht

class MainView extends GLSurfaceView { 
    MainRenderer mRenderer; 

    MainView (Context context) { 
    super (context); 
    mRenderer = new MainRenderer(this); 
    setEGLContextClientVersion (2); 
    setRenderer (mRenderer); 
    setRenderMode (GLSurfaceView.RENDERMODE_WHEN_DIRTY); 
    } 

    public void surfaceCreated (SurfaceHolder holder) { 
    super.surfaceCreated (holder); 
    } 

    public void surfaceDestroyed (SurfaceHolder holder) { 
    mRenderer.close(); 
    super.surfaceDestroyed (holder); 
    } 

    public void surfaceChanged (SurfaceHolder holder, int format, int w, int h) { 
    super.surfaceChanged (holder, format, w, h); 
    } 
} 

// Renderer

public class MainRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { 
    private final String vss = 
     "attribute vec2 vPosition;\n" + 
     "attribute vec2 vTexCoord;\n" + 
     "varying vec2 texCoord;\n" + 
     "void main() {\n" + 
     " texCoord = vTexCoord;\n" + 
     " gl_Position = vec4 (vPosition.x, vPosition.y, 0.0, 1.0);\n" + 
     "}"; 

    private final String fss = 
     "#extension GL_OES_EGL_image_external : require\n" + 
     "precision mediump float;\n" + 
     "uniform samplerExternalOES sTexture;\n" + 
     "varying vec2 texCoord;\n" + 
     "void main() {\n" + 
     " gl_FragColor = texture2D(sTexture,texCoord);\n" + 
     "}"; 

    private int[] hTex; 
    private FloatBuffer pVertex; 
    private FloatBuffer pTexCoord; 
    private int hProgram; 

    private Camera mCamera; 
    private SurfaceTexture mSTexture; 

    private boolean mUpdateST = false; 

    private MainView mView; 

    MainRenderer (MainView view) { 
    mView = view; 
    float[] vtmp = { 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f }; 
    float[] ttmp = { 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f }; 
    pVertex = ByteBuffer.allocateDirect(8*4).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
    pVertex.put (vtmp); 
    pVertex.position(0); 
    pTexCoord = ByteBuffer.allocateDirect(8*4).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
    pTexCoord.put (ttmp); 
    pTexCoord.position(0); 
    } 

    public void close() 
    { 
    mUpdateST = false; 
    mSTexture.release(); 
    mCamera.stopPreview(); 
    mCamera.release(); 
    mCamera = null; 
    deleteTex(); 
    } 

    public void onSurfaceCreated (GL10 unused, EGLConfig config) { 
    //String extensions = GLES20.glGetString(GLES20.GL_EXTENSIONS); 
    //Log.i("mr", "Gl extensions: " + extensions); 
    //Assert.assertTrue(extensions.contains("OES_EGL_image_external")); 

    initTex(); 
    mSTexture = new SurfaceTexture (hTex[0]); 
    mSTexture.setOnFrameAvailableListener(this); 

    mCamera = Camera.open(); 
    try { 
     mCamera.setPreviewTexture(mSTexture); 
    } catch (IOException ioe) { 
    } 

    GLES20.glClearColor (1.0f, 1.0f, 0.0f, 1.0f); 

    hProgram = loadShader (vss, fss); 
    } 

    public void onDrawFrame (GL10 unused) { 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 

    synchronized(this) { 
     if (mUpdateST) { 
    mSTexture.updateTexImage(); 
    mUpdateST = false; 
     } 
    } 

    GLES20.glUseProgram(hProgram); 

    int ph = GLES20.glGetAttribLocation(hProgram, "vPosition"); 
    int tch = GLES20.glGetAttribLocation (hProgram, "vTexCoord"); 
    int th = GLES20.glGetUniformLocation (hProgram, "sTexture"); 

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, hTex[0]); 
    GLES20.glUniform1i(th, 0); 

    GLES20.glVertexAttribPointer(ph, 2, GLES20.GL_FLOAT, false, 4*2, pVertex); 
    GLES20.glVertexAttribPointer(tch, 2, GLES20.GL_FLOAT, false, 4*2, pTexCoord); 
    GLES20.glEnableVertexAttribArray(ph); 
    GLES20.glEnableVertexAttribArray(tch); 

    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 
    GLES20.glFlush(); 
    } 

    public void onSurfaceChanged (GL10 unused, int width, int height) { 
    GLES20.glViewport(0, 0, width, height); 
    Camera.Parameters param = mCamera.getParameters(); 
    List psize = param.getSupportedPreviewSizes(); 
    if (psize.size() > 0) { 
     int i; 
     for (i = 0; i < psize.size(); i++) { 
    if (psize.get(i).width < width || psize.get(i).height < height) 
     break; 
     } 
     if (i > 0) 
    i--; 
     param.setPreviewSize(psize.get(i).width, psize.get(i).height); 
     //Log.i("mr","ssize: "+psize.get(i).width+", "+psize.get(i).height); 
    } 
    param.set("orientation", "landscape"); 
    mCamera.setParameters (param); 
    mCamera.startPreview(); 
    } 

    private void initTex() { 
    hTex = new int[1]; 
    GLES20.glGenTextures (1, hTex, 0); 
    GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, hTex[0]); 
    GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 
    GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 
    GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 
    } 

    private void deleteTex() { 
    GLES20.glDeleteTextures (1, hTex, 0); 
    } 

    public synchronized void onFrameAvailable (SurfaceTexture st) { 
    mUpdateST = true; 
    mView.requestRender(); 
    } 

    private static int loadShader (String vss, String fss) { 
    int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); 
    GLES20.glShaderSource(vshader, vss); 
    GLES20.glCompileShader(vshader); 
    int[] compiled = new int[1]; 
    GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, compiled, 0); 
    if (compiled[0] == 0) { 
     Log.e("Shader", "Could not compile vshader"); 
     Log.v("Shader", "Could not compile vshader:"+GLES20.glGetShaderInfoLog(vshader)); 
     GLES20.glDeleteShader(vshader); 
     vshader = 0; 
    } 

    int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); 
    GLES20.glShaderSource(fshader, fss); 
    GLES20.glCompileShader(fshader); 
    GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, compiled, 0); 
    if (compiled[0] == 0) { 
     Log.e("Shader", "Could not compile fshader"); 
     Log.v("Shader", "Could not compile fshader:"+GLES20.glGetShaderInfoLog(fshader)); 
     GLES20.glDeleteShader(fshader); 
     fshader = 0; 
    } 

    int program = GLES20.glCreateProgram(); 
    GLES20.glAttachShader(program, vshader); 
    GLES20.glAttachShader(program, fshader); 
    GLES20.glLinkProgram(program); 

    return program; 
    } 
} 
+2

Wenn Sie wirklich die OpenGL ES Weg gehen wollen, "Textur von der Kamera" in Grafika sehen (https://github.com/google/grafika).Es zeigt eine beliebige Position, Rotation, Skalierung und "Zoom" der Kamera-Vorschau mit Ausgabe an eine SurfaceView. Außerdem: Sie scheinen die Wake-Lock-Erlaubnis zu beantragen; Lesen Sie unbedingt http://stackoverflow.com/questions/2131948/force-screen-on/2134602#2134602. – fadden

+0

@fadden danke. Yeah Wake Lock Artikel scheint zu helfen. – enthusiasticgeek

Antwort

3

Ich glaube, es gibt nur wenige Möglichkeiten abhängig, was zu Ihnen passt mehr:

  1. ändern Vertex-Array-Werte basierend auf Winkel (wahrscheinlich die einfachste)
  2. Camera.setDisplayOrientation
  3. Sie könnten Ihren Vertex ändern ein bisschen (es ist ein wenig anders als das, was Sie bisher haben, ich habe vec4 statt vec2 verwendet, einige andere Änderungen müssen getan werden, um das in Ihrem Code zu berücksichtigen):
static final String vss = 
    "uniform mat4 uMVPMatrix;\n" + 
    "uniform mat4 uSTMatrix;\n" + 
    "attribute vec4 vPosition;\n" + 
    "attribute vec4 vTexCoord;\n" + 
    "varying vec2 texCoord;\n" + 
    "void main() {\n" + 
    " gl_Position = uMVPMatrix * vPosition;\n" + 
    " texCoord = (uSTMatrix * vTexCoord).xy;\n" + 
    "}\n"; 

und dann

float[] mvpMatrix = new float[16]; 
int uMVPMatrixHandle; 

uMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix"); 
checkLocation(uMVPMatrixHandle, "uMVPMatrix"); 

bei jedem beliebigen Winkel angeben zeichnen möchten Sie:

Matrix.setIdentityM(mvpMatrix, 0); 
Matrix.rotateM(mvpMatrix, 0, angle, 0f, 0f, 1f); 
GLES20.glUniformMatrix4fv(uMVPMatrixHandle, 1, false, mvpMatrix, 0); 
EGL.checkGlError("glUniformMatrix4fv"); 
+0

Danke. Ich fügte checkGLError und checkLocation Funktionen von hier http://stackoverflow.com/questions/35227222/rendering-surfacetexture-to-unity-texture2d und andere Stücke von oben hinzu. Wenn ich jedoch den Code mit Ihren Vorschlägen ausgeführt habe, scheint er zu stürzen. Nur um klar zu sein, welche Teile des Codes, die Sie aufgelistet haben, sollten in 'onDraw' gehen und welche in 'onSurfaceCreated', 'onSurfaceChanged'? – enthusiasticgeek

+3

Camera.setDisplayOrientation hat bei mir nicht funktioniert. Ich benutzte die erste Option, ich nahm Papier und Bleistift und zeichnete ein einfaches Diagramm über das Koordinatensystem. Dann platzierte ich alle Koordinaten logisch und basierend darauf änderte ich 'vtmp' wie folgt,' float [] vtmp = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f}; 'um 90 Grad zu drehen. Und es hat gut für meine Anwendung funktioniert. – enthusiasticgeek

+0

Großartig, ja, letzter Ansatz ist gut, wenn mehr Kontrolle und zusätzliche Schritte benötigt werden. Ich denke, das erste ist für Ihren Fall am einfachsten, aber stellen Sie sicher, dass der Winkel von 90 Grad eine dynamische Variable ist, die je nach Gerät unterschiedlich sein kann (siehe http://developer.android.com/reference/android/hardware/Camera) .html # setDisplayOrientation (int) für weitere Informationen über die Handhabung von Winkeln), sollte Ihnen nichts passieren. –