Кнопки, OpenGL и рендеры - Android - PullRequest
       29

Кнопки, OpenGL и рендеры - Android

3 голосов
/ 11 августа 2011

Я надеюсь, что у меня будет представление 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"
     />

Activity (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));


}
}

Renderer (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 Ответ

3 голосов
/ 22 ноября 2011

Я знаю, что это старый вопрос, но он получил несколько голосов, поэтому собираюсь на него ответить

Хитрость, которую я использую для связи между потоками с моим рендерером, заключается в том, чтобы сохранить объект рендеринга как переменную в действии, а затем поместить в очередь рендерер для выполнения его при рисовании следующего кадра (следующий вызов 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;

}

}

В приведенном выше примере вы можете захотеть изменить команду на массив и пройти через нее. Я на самом деле использую этот подход для того, чтобы сообщать моему рендереру, какие модели рисовать, или для того, чтобы мой рендерер начал загружать большую модель или текстуру раньше времени, чтобы, когда игра подошла к ней, она уже была в памяти и там не было. задержка загрузки до того, как она нарисована

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...