我使用 OpenGL_1 技术编写了一个自定义视图,以便让用户只需沿 x 轴拖动红色三角形即可旋转它。(将围绕 Y 轴旋转)。它可以工作,但是从一个方向拖动到另一个方向时会有一点延迟(不释放鼠标/手指)。所以看来我的代码还不是“目标完美”。(我相信没有代码本身是完美的)。
我想过使用四元数,但也许它不会那么有用:我真的必须使用四元数(或一种矩阵)吗?
我为 Android 4.0.3 设计了应用程序,但它也可以适合 Android api 3 (Android 1.5)(至少,我认为可以)。
所以这是我的主要布局:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.laurent_bernabe.android.triangletournant3d.MyOpenGLView
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
这是我的主要活动:
MainActivity.java
package com.laurent_bernabe.android.triangletournant3d;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
}
最后,我的 OpenGL 视图
MyOpenGLView.java
package com.laurent_bernabe.android.triangletournant3d;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class MyOpenGLView extends GLSurfaceView implements Renderer {
public MyOpenGLView(Context context, AttributeSet attrs) {
super(context, attrs);
setRenderer(this);
}
public MyOpenGLView(Context context) {
this(context, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int actionMasked = event.getActionMasked();
switch(actionMasked){
case MotionEvent.ACTION_DOWN:
savedClickLocationX = (int) event.getX();
break;
case MotionEvent.ACTION_UP:
savedClickLocationX = null;
break;
case MotionEvent.ACTION_MOVE:
Integer newClickLocationX = (int) event.getX();
int dx = newClickLocationX - savedClickLocationX;
angle += dx / 180.0f * 3.14159265f;
break;
}
return true;
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
GLU.gluLookAt(gl,
0f, 0f, 5f,
0f, 0f, 0f,
0f, 1f, 0f
);
gl.glRotatef(angle, 0f, 1f, 0f);
gl.glColor4f(1f, 0f, 0f, 0f);
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, triangleCoordsBuff);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
}
@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, 60f, (float) width / height, 0.1f, 10f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glClearDepthf(1.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
buildTriangleCoordsBuffer();
}
private void buildTriangleCoordsBuffer() {
ByteBuffer buffer = ByteBuffer.allocateDirect(4*triangleCoords.length);
buffer.order(ByteOrder.nativeOrder());
triangleCoordsBuff = buffer.asFloatBuffer();
triangleCoordsBuff.put(triangleCoords);
triangleCoordsBuff.rewind();
}
private float [] triangleCoords = {-1f, -1f,
+1f, -1f,
+1f, +1f};
private FloatBuffer triangleCoordsBuff;
private float angle = 0f;
private Integer savedClickLocationX;
}
(修改感谢 Mohamed Abdallah)。
我不认为我真的必须给你我的清单文件。但如果你认为有必要,我可以。
我刚刚在模拟器和真实设备上进行了测试。
我的配置
- 安卓 SDK 20.0.3
- 日蚀朱诺
- Ubuntu 12.10 64 位
- 已安装 OpenGL 驱动程序(来自 Canonical)。
那么,如何提高反应性呢?
提前致谢。