2010-10-24 230 views
1

我正在通过阅读教程和应用我已经知道的,学习适用于Android的Java和OpenGL ES。当谈到旋转物体时,我已经撞到了一堵砖墙。OpenGL旋转问题

通过触摸屏幕来旋转立方体是没有问题的。但是,如果我将立方体向上或向下旋转180度,那么当我现在尝试向左或向右旋转立方体时,它会倒转。我知道这是为什么发生,但我找不到解决方案。

的代码如下如果有的想测试一下:

文件 “Rotating.java”:

package com.test.opengl; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.Window; 
import android.view.WindowManager; 

public class Rotating extends Activity { 

    private GLControlView glControlView; 

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

     glControlView = new GLControlView(this); 
     setContentView(glControlView); 

    } 

} 

文件 “GLControlView.java”:

package com.test.opengl; 

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

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

public class GLControlView extends GLSurfaceView implements Renderer { 

    private Context context; 

    private float xPrevious, yPrevious; 
    private float xRotation = 0.0f, yRotation = 0.0f; 

    private SimpleCubeObject cubeObject; 

    public GLControlView(Context context) { 
     super(context); 

     this.context = context; 

     this.setRenderer(this); 

     this.requestFocus(); 
     this.setFocusableInTouchMode(true); 

     cubeObject = new SimpleCubeObject(); 

    } 

    public void onSurfaceCreated(GL10 gl, EGLConfig config) { 

     gl.glClearColor(0.0f, 0.0f, 0.0f, 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); 

    } 

    public void onDrawFrame(GL10 gl) { 

     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 
     gl.glLoadIdentity(); 
     gl.glTranslatef(0.0f, 0.0f, -10.0f); 

     gl.glPushMatrix(); 

     gl.glRotatef(xRotation, 1.0f, 0.0f, 0.0f); 
     gl.glRotatef(yRotation, 0.0f, 1.0f, 0.0f); 

     gl.glPushMatrix(); 
     cubeObject.draw(gl); 
     gl.glPopMatrix(); 

     gl.glPopMatrix(); 

    } 

    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, 100.0f); 
     gl.glMatrixMode(GL10.GL_MODELVIEW); 
     gl.glLoadIdentity(); 

    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 

     float xEvent = event.getX(); 
     float yEvent = event.getY(); 

     switch(event.getAction()) { 

      case MotionEvent.ACTION_DOWN: { 

       xPrevious = xEvent; 
       yPrevious = yEvent; 

       return true; 

      } 

      case MotionEvent.ACTION_MOVE: { 

       float xDelta = xEvent - xPrevious; 
       float yDelta = yEvent - yPrevious; 

       xRotation += (yDelta * 0.5f); 
       yRotation += (xDelta * 0.5f); 

       xPrevious = xEvent; 
       yPrevious = yEvent; 

       return true; 

      } 

      default: return super.onTouchEvent(event); 

     } 

    } 

} 

文件“SimpleCubeObject .java“:

package com.test.opengl; 

import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 
import java.nio.ShortBuffer; 

import javax.microedition.khronos.opengles.GL10; 

public class SimpleCubeObject { 

    private int[] textures = new int[ 1 ]; 

    private float[] colors = { 

      0.0f, 0.0f, 0.0f, 1.0f, 
      1.0f, 0.0f, 0.0f, 1.0f, 
      0.0f, 1.0f, 0.0f, 1.0f, 
      0.0f, 0.0f, 1.0f, 1.0f, 
      1.0f, 0.0f, 1.0f, 1.0f, 
      0.0f, 1.0f, 1.0f, 1.0f, 
      1.0f, 1.0f, 0.0f, 1.0f, 
      1.0f, 1.0f, 1.0f, 1.0f 

    }; 

    private short[] indices = { 

      0, 1, 2, 0, 2, 3, 
      1, 5, 6, 1, 6, 2, 
      2, 6, 7, 2, 7, 3, 
      3, 7, 4, 3, 4, 0, 
      0, 4, 5, 0, 5, 1, 
      7, 6, 5, 7, 5, 4 

    }; 

    private float[] vertices = { 

      -1.0f, 1.0f, -1.0f, 
      -1.0f, 1.0f, 1.0f, 
      1.0f, 1.0f, 1.0f, 
      1.0f, 1.0f, -1.0f, 
      -1.0f, -1.0f, -1.0f, 
      -1.0f, -1.0f, 1.0f, 
      1.0f, -1.0f, 1.0f, 
      1.0f, -1.0f, -1.0f 

    }; 

    private FloatBuffer colorBuffer; 
    private ShortBuffer indexBuffer; 
    private FloatBuffer vertexBuffer; 

    public SimpleCubeObject() { 

     ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4); 
     cbb.order(ByteOrder.nativeOrder()); 
     colorBuffer = cbb.asFloatBuffer(); 
     colorBuffer.put(colors); 
     colorBuffer.position(0); 

     ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2); 
     ibb.order(ByteOrder.nativeOrder()); 
     indexBuffer = ibb.asShortBuffer(); 
     indexBuffer.put(indices); 
     indexBuffer.position(0); 

     ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); 
     vbb.order(ByteOrder.nativeOrder()); 
     vertexBuffer = vbb.asFloatBuffer(); 
     vertexBuffer.put(vertices); 
     vertexBuffer.position(0); 

    } 

    public void draw(GL10 gl) { 

     gl.glFrontFace(GL10.GL_CCW); 
     gl.glEnable(GL10.GL_CULL_FACE); 
     gl.glCullFace(GL10.GL_BACK); 

     gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[ 0 ]); 

     gl.glEnableClientState(GL10.GL_COLOR_ARRAY); 
     gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 

     gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer); 
     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.glDisableClientState(GL10.GL_COLOR_ARRAY); 

     gl.glDisable(GL10.GL_CULL_FACE); 

    } 

} 

我当然希望有人能帮助我。我相信,一如既往,解决方案简单易行 - 只是我现在看不到它。

回答

1

这个问题是旋转的欧拉角表示(即将旋转存储为参考轴的旋转)固有的,因为随后的每个旋转部分都会改变参考坐标系。 你可以尝试使用一些不同的对象旋转表示法,如四元数或 - 根据Ishtar的建议 - 旋转矩阵或轴/角度。

这里是四元数的教程,如果你想尝试一下: http://gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation

,也有一些不同的建议: http://gpwiki.org/forums/viewtopic.php?t=8611&sid=7d8cb26617084c80c670634d3d7e9f36

http://www.gamedev.net/community/forums/topic.asp?topic_id=491391

+0

Thanx!这似乎是一个不可能完成的任务,但是四元数是我需要的。 – Espen 2010-10-24 20:04:05

0

我认为这是你正在做的旋转的顺序,你是否尝试过这种方式。

gl.glRotatef(yRotation, 0.0f, 1.0f, 0.0f); 
    gl.glRotatef(xRotation, 1.0f, 0.0f, 0.0f); 
+0

我做到了。它只是将问题移到另一个轴上。 – Espen 2010-10-24 14:08:30

0

这并不简单。

xRotation += (yDelta * 0.5f); 
yRotation += (xDelta * 0.5f); 

这是行不通的。您的x轴或y轴不正确,这些是纵摇和横轴(?)。不是x和y轴。

我想你需要记住旋转矩阵本身,而不是一些x和y旋转。你最好只有一个正在旋转的轴。轴当然取决于MotionEvent的方向。和总拖动距离上的旋转量。

float xDelta = xEvent - xActionDown;//from starting point 
float yDelta = yEvent - yActionDown; 
float distance = sqrt(xDelta*xDelta+yDelta*yDelta); 
float xaxis = xDelta/distance;//normalized: 0.0 <-> 1.0 
float yaxis = yDelta/distance; 

gl.glRotatef(distance, yaxis, xaxis, 0.0f);//x and y swapped! 

我100%肯定以上是不正确的。你将不得不添加一些支票,一个减号等,但我希望你有基本的想法?