我正在通过阅读教程并应用我已经知道的知识来学习Java和OpenGL ES for Android。在旋转物体时,我现在遇到了一堵砖墙。
通过触摸屏幕旋转立方体是没有问题的。但是如果我将立方体向上或向下旋转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 );
}
}
我当然希望有人可以帮助我。我一如既往地相信解决方案简单易行 - 只是我现在无法看到它。
答案 0 :(得分: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
答案 1 :(得分:0)
我认为这是你正在进行轮换的顺序。你是否尝试过这种方式:
gl.glRotatef( yRotation, 0.0f, 1.0f, 0.0f );
gl.glRotatef( xRotation, 1.0f, 0.0f, 0.0f );
答案 2 :(得分: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%确定上述内容不正确。你必须添加一些支票,一个减号等。但我希望你得到基本的想法?