按钮、OpenGL 和渲染器 - Android

发布于 2024-11-29 00:14:15 字数 2922 浏览 2 评论 0原文

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

假设在此相对布局中,我有一个 GLSurfaceView 和其下方的一个按钮,按下该按钮会将 GLSurfaceView 更改为随机纯色。我了解如何在 OpenGL 中绘制,但我不了解如何从渲染器外部与渲染器进行交互,以便可以通过与视图本身上的触摸事件无关的用户输入来更改表面。

根据我的研究,我猜测我需要某种线程,并且我可能需要使用方法queueEvent(Runnable)。但不知道从这里去哪里。

XML(主.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);

}

}

I'm looking to have an OpenGL view (GLSurfaceView) that uses a Renderer alongside some buttons in a RelativeLayout so that each of these buttons can interact with the rendered view.

Let's say in this RelativeLayout I have one GLSurfaceView and one button underneath it that when pressed will change the GLSurfaceView to a random solid color. I understand how to draw in OpenGL, what I don't understand is how to interact with a renderer from outside the renderer so that the surface can be altered by user input not associated with a touch event on the view itself.

From my research, I'm guessing that I'll need a thread of some sort, and I may need to use the method, queueEvent(Runnable). Not sure where to go from here though.

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

}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

养猫人 2024-12-06 00:14:15

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

我用来跨线程与渲染器进行通信的技巧是将渲染器对象保留为活动中的变量,然后在渲染器中对其进行排队绘制下一帧时要做的事情(下一次调用 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;

}

}

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

I know this is an old question, but it got some votes, so going to answer it

The trick I use to communicate across threads to my renderer is to keep the renderer object as a variable in activity and then queue stuff in the renderer for it to do when it comes to draw the next frame (next call of 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;

}

}

In the above example, you might want to change command to an array and loop through it. I actually use this approach for telling my renderer which models to draw, or telling my renderer to start loading a large model or texture ahead of time, so that when the game gets round to needing it, it is already in memory and there is no delay in loading it before it is drawn

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文