2010-10-24 5 views
1

Я изучаю Java и OpenGL ES для Android, читая учебные пособия и применяя то, что я уже знаю. И теперь я ударил кирпичную стену, когда дело доходило до поворота объекта.Вращающаяся проблема 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

Эта проблема присуща угловому представлению углов Эйлера (то есть сохранение вращения как вращения от опорных осей), поскольку каждая последующая часть вращения изменяет опорный кадр. Вы можете попробовать использовать другое представление вращения объекта, например, кватернионы или - по предложению Иштара - матрицу вращения или ось/угол.

Вот учебник по кватернионам, если вы хотели бы попробовать их: 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

0

Я думаю, что это для того, что вы делаете повороты в Пытались ли вы таким образом:.

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

я сделал. Он просто перемещает проблему на другую ось. – Espen

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% уверен, что вышеуказанное неверно. Вам придется добавить некоторые чеки, минус и т. Д. Но я надеюсь, что вы получите основную идею?

Смежные вопросы