opengl-es onTouchEvents问题还是draw问题?
我刚刚开始在我的应用程序中使用 opengl,我感觉很好 =) 但最近我遇到了困难,因为我一直在尝试找出用户输入的方法。 我决定从一个简单的过程开始,在屏幕上触摸屏幕的位置绘制一个正方形。不幸的是,该应用程序似乎没有注册输入。
这是我的代码:
应用程序通过此活动打开>>
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class Practice extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
GLSurfaceView view = new GLSurfaceView (this);
view.setRenderer(new GLSurfaceRenderer());
setContentView(view);
}
}
这会初始化一个全屏 SurfaceView。
接下来是渲染器
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;
import android.view.MotionEvent;
public class GLSurfaceRenderer implements Renderer{
private FlatColoredSquare Square;
private float setx = 0;
private float sety = 0;
public GLSurfaceRenderer () {
Square = new FlatColoredSquare();
}
public boolean onTouchEvent (MotionEvent event, GL10 gl){
if (event.getAction() == MotionEvent.ACTION_UP){
gl.glPushMatrix();
gl.glTranslatef(event.getX(), event.getY(), -10);
Square.draw(gl);
gl.glPopMatrix();
}
return true;
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT |
GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glPushMatrix();
gl.glTranslatef(setx, sety, -10);
Square.draw(gl);
gl.glPopMatrix();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int 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, 100f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
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);
}
}
正如您所看到的,有一个 onTouchEvent 获取事件的坐标并将它们设置为顶部的浮动。然后,draw 方法使用这些坐标来设置正方形的位置。我认为这里的绘制方法更新不足以重新绘制正方形。如何设置绘制方法来更新方块 onTouch?除了尝试设置从 onTouch 方法内部绘制的正方形之外,我还将其留空,例如:
public boolean onTouchEvent (MotionEvent event){
if (event.getAction() == MotionEvent.ACTION_UP){
setx = event.getX();
sety = event.getY();
}
return true;
}
这两个都返回相同的结果 =( 那么我的 onTouchEvent 做错了吗? 或者我是否必须强制绘制方法以某种方式更新? 我将如何正确实施这一点?
感谢您花时间
编辑:
通过将方法移至 Practice 类,设法获取注册 onTouchEvent 的代码。
编辑:做了一些更多的改进,代码现在在一定程度上可以正常工作,但我没有在所需的位置重新绘制正方形,而是得到一个空白的清除屏幕。
这里是编辑的实践
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.app.ui.GLSurfaceRenderer;
public class Practice extends Activity {
private GLSurfaceRenderer glSurfaceRenderer;
public static float setx;
public static float sety;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
GLSurfaceView view = new GLSurfaceView (this);
view.setRenderer(glSurfaceRenderer = new GLSurfaceRenderer());
setContentView(view);
}
@Override
public synchronized boolean onTouchEvent (MotionEvent event){
if (event.getAction() == MotionEvent.ACTION_UP){
glSurfaceRenderer.randomMethod(event);
}
return true;
}
}
和编辑的渲染器类
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;
import android.view.MotionEvent;
public class GLSurfaceRenderer implements Renderer{
private float setx;
private float sety;
private FlatColoredSquare square;
public GLSurfaceRenderer () {
square = new FlatColoredSquare();
}
public synchronized void randomMethod(MotionEvent event){
setx = event.getX();
sety = event.getY();
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT |
GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glPushMatrix();
gl.glTranslatef(setx, sety, -10);
square.draw(gl);
gl.glPopMatrix();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int 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, 100f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
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);
}
}
有什么想法吗? 这是方形代码
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
public class FlatColoredSquare {
private float vertices[] = {
-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f
};
private short indices[] = {0, 1, 2, 0, 2, 3,};
private FloatBuffer vertexBuffer;
private ShortBuffer indexBuffer;
public FlatColoredSquare() {
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length*2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glColor4f(0.0f, 1.0f, 0.0f, 0.0f);
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
}
I am just getting started with using opengl in my apps and I get it fine =) but I've hit a brick wall recently as I have been attempting to work out methods of user input.
I decided to start with a simple process that draws a square to the screen at the position you touch the screen. Unfortunatly the app doesn't seem to register the input.
Here is my code:
The app opens with this activity >>
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class Practice extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
GLSurfaceView view = new GLSurfaceView (this);
view.setRenderer(new GLSurfaceRenderer());
setContentView(view);
}
}
This initializes a full screen SurfaceView.
Next the renderer
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;
import android.view.MotionEvent;
public class GLSurfaceRenderer implements Renderer{
private FlatColoredSquare Square;
private float setx = 0;
private float sety = 0;
public GLSurfaceRenderer () {
Square = new FlatColoredSquare();
}
public boolean onTouchEvent (MotionEvent event, GL10 gl){
if (event.getAction() == MotionEvent.ACTION_UP){
gl.glPushMatrix();
gl.glTranslatef(event.getX(), event.getY(), -10);
Square.draw(gl);
gl.glPopMatrix();
}
return true;
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT |
GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glPushMatrix();
gl.glTranslatef(setx, sety, -10);
Square.draw(gl);
gl.glPopMatrix();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int 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, 100f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
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);
}
}
As you can see there is an onTouchEvent that gets the coordinates of the event and sets them to the floats at the top. The draw method then uses these coordinates to set the position of the square. I don't think the draw method here updates enough to redraw the square. How can I set the draw method to update the square onTouch? As well as trying to set the square to draw from inside the onTouch method I have also left it blank like:
public boolean onTouchEvent (MotionEvent event){
if (event.getAction() == MotionEvent.ACTION_UP){
setx = event.getX();
sety = event.getY();
}
return true;
}
Both of these return the same results =(
So am I doing the onTouchEvent wrong?
or do I have to force the draw method to update somehow?
and how would I implement this properly?
Thank you for your time
EDIT:
Managed to get the code to register an onTouchEvent by moving the method over to the Practice class.
EDIT: Made some more improvements code now works properly to an extent but instead of redrawing the square in the desired place I instead get a blank cleared screen.
Here is edited Practice
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.app.ui.GLSurfaceRenderer;
public class Practice extends Activity {
private GLSurfaceRenderer glSurfaceRenderer;
public static float setx;
public static float sety;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
GLSurfaceView view = new GLSurfaceView (this);
view.setRenderer(glSurfaceRenderer = new GLSurfaceRenderer());
setContentView(view);
}
@Override
public synchronized boolean onTouchEvent (MotionEvent event){
if (event.getAction() == MotionEvent.ACTION_UP){
glSurfaceRenderer.randomMethod(event);
}
return true;
}
}
And edited Renderer Class
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;
import android.view.MotionEvent;
public class GLSurfaceRenderer implements Renderer{
private float setx;
private float sety;
private FlatColoredSquare square;
public GLSurfaceRenderer () {
square = new FlatColoredSquare();
}
public synchronized void randomMethod(MotionEvent event){
setx = event.getX();
sety = event.getY();
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT |
GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glPushMatrix();
gl.glTranslatef(setx, sety, -10);
square.draw(gl);
gl.glPopMatrix();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int 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, 100f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
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);
}
}
Any ideas?
Here is the square code
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
public class FlatColoredSquare {
private float vertices[] = {
-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f
};
private short indices[] = {0, 1, 2, 0, 2, 3,};
private FloatBuffer vertexBuffer;
private ShortBuffer indexBuffer;
public FlatColoredSquare() {
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length*2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glColor4f(0.0f, 1.0f, 0.0f, 0.0f);
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里有两个问题。
1) 您正在使用自己的自定义
onTouchEvent()
方法。您的方法onTouchEvent()
与参数MotionEvent event, GL10 gl
在 SDK 中没有官方支持。2) 您正在修改显式在另一个线程中运行的数据。触摸事件的线程与 GL 线程不同。
你的解决方案很简单。覆盖
onTouchEvent(MotionEvent 事件)
(或设置onTouchListener
到您的 Activity 类中的GLSurfaceView
类)并调用一个方法(应声明为synchronized) 在你的视图类中。另一种方法是在不同的线程中更新逻辑,但这由您决定。
Two problems here.
1) You are using your own, custom
onTouchEvent()
method. Your methodonTouchEvent()
with the argumentsMotionEvent event, GL10 gl
has no official support in the SDK.2) You are modifying data that explicitly are running in another thread. The touch event's threads differs from the GL thread.
Your solution is simple. Override
onTouchEvent(MotionEvent event)
(or set anonTouchListener
to yourGLSurfaceView
class) in your activity class and call a method (which should be declared assynchronized
) in your view class within it. An alternative is to update logic in a different thread, however, that is up to you to decide.