按钮,OpenGL和渲染器 - Android

时间:2011-08-11 01:20:32

标签: android multithreading opengl-es runnable renderer

我希望有一个OpenGL视图(GLSurfaceView),它使用Renderer和RelativeLayout中的一些按钮,这样每个按钮都可以与渲染视图交互。

让我们说在这个RelativeLayout中我有一个GLSurfaceView,下面有一个按钮,当按下它时会将GLSurfaceView更改为随机纯色。我理解如何在OpenGL中绘制,我不理解的是如何从渲染器外部与渲染器交互,以便可以通过与视图本身上的触摸事件无关的用户输入来更改曲面。

根据我的研究,我猜我需要某种线程,我可能需要使用方法queueEvent(Runnable)。不知道从哪里开始。

XML(main.xml中)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RL1"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>

<android.opengl.GLSurfaceView
    android:id="@+id/GLView"
    android:layout_width="200dip"
    android:layout_height="200dip"
    android:layout_centerHorizontal="true"

     />


<Button
    android:id="@+id/Button1"
    android:layout_width="150dip"
    android:layout_height="100dip"
    android:text="Click."
    android:layout_below="@id/GLView"
    android:layout_centerHorizontal="true"
     />

活动(Basic.java)

import android.app.Activity;
import android.opengl.*;
import android.os.Bundle;


public class Basic extends Activity {
/** Called when the activity is first created. */


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    GLSurfaceView glView = (GLSurfaceView)findViewById(R.id.GLView);
    glView.setRenderer(new BasicRenderer(this));


}
}

渲染器(OpenGLRenderer.java)

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

import android.content.Context;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;

public class BasicRenderer implements Renderer {

private Context mContext;
private float mWidth, mHeight;
public BasicRenderer(Context context){
    mContext=context;
}

@Override
public void onDrawFrame(GL10 gl) {
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | 
            GL10.GL_DEPTH_BUFFER_BIT);



}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    mWidth = (float)width; 
    mHeight = (float)height;

    gl.glViewport(0, 0, width, height);

    gl.glMatrixMode(GL10.GL_PROJECTION);

    gl.glLoadIdentity();

    GLU.gluPerspective(gl, 45.0f,
                               (float) width / (float) height,
                               0.1f, 100.0f);

    gl.glMatrixMode(GL10.GL_MODELVIEW);

    gl.glLoadIdentity();

}

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

    // Set the background color to white
    gl.glClearColor(1f, 1f, 1f, 0.5f); 

    gl.glShadeModel(GL10.GL_SMOOTH);

    gl.glClearDepthf(1.0f);

    gl.glEnable(GL10.GL_DEPTH_TEST);

    gl.glDepthFunc(GL10.GL_LEQUAL);

    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, 
                      GL10.GL_NICEST);

}

}

1 个答案:

答案 0 :(得分:3)

我知道这是一个老问题,但它得到了一些投票,所以要回答它

我用来跨线程与渲染器进行通信的技巧是将渲染器对象保持为活动中的变量,然后在渲染器中排队,以便在绘制下一帧时进行处理(下一次调用onDraw) :

public class Basic extends Activity {
/** Called when the activity is first created. */

BasicRenderer myRenderer;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    myRenderer = new BasicRenderer(this);

    GLSurfaceView glView = (GLSurfaceView)findViewById(R.id.GLView);
    glView.setRenderer(myRenderer);


    myRenderer.queueDoSomethingNextTick(BasicRenderer.DO_THIS);

    findViewById(R.id.Button1).setOnTocuhListener(new OnTouchListener(){

        public void onTouch(MotionEvent event){
            myRenderer.queueDoSomethingNextTick(BasicRenderer.DO_THAT);
           // Compiler might complain about myRenderer not being final
        }


    });


}
}


public class BasicRenderer implements Renderer {

    private Context mContext;
    private float mWidth, mHeight;


    private int command;
    public static final DO_THIS = 1;
    public static final DO_THAT = 2;

public BasicRenderer(Context context){
    mContext=context;
}

@Override
public void onDrawFrame(GL10 gl) {

    if(command==DO_THIS){
        //doThis();
    } else if(command==DO_THAT){
        //doThat();
    }

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

    gl.glDrawAwesomeness();


}

public void queueDoSomethingNextTick(int command){

    this.command = command;

}

}

在上面的示例中,您可能希望将命令更改为数组并循环遍历它。我实际上使用这种方法告诉我的渲染器要绘制哪些模型,或者告诉我的渲染器提前开始加载大型模型或纹理,这样当游戏开始需要它时,它已经在内存中并且没有在绘制之前延迟加载