2010-10-24 228 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%肯定以上是不正確的。你將不得不添加一些支票,一個減號等,但我希望你有基本的想法?