android是用OpenGL来实现3d的。OpenGL的处理机制是把所有的数据都用代码传递给opengl service,如果用户(这里是应用程序)想要画什么东西,就用告诉opengl 什么东西是可用的,然后在开始画。

这个例子一共分三步:
1."
"一个3d的图形(这里画的是菱形),把它传递给opengl service 端,然后建立一个画自己的方法。
2.
创建这个图形运行的环境。
3.
把这个环境,加载到android 的界面上去。

下面是具体的实现方法:
首先需要建两个array,第一array是用来告诉opengl这个图形有哪些顶点:
画一个三维的坐标轴,然后把你要画的点都算出来,然后放在这个array里。

float l=1.5f;
float[] vertex={

0.0f,l,0.0f,

l,0.0f,0.0f,

0.0f,0.0f,l,

-l,0.0f,0.0f,

0.0f,0.0f,-l,

0.0f,-l,0.0f

};
第二个array是告诉opengl 你要怎样组织这些点:
这里我要画三角形,所以每三个点是一组。
byte[] edge=

{

0,1,2,

1,2,5,



0,2,3,

5,2,3,



0,3,4,

5,3,4,



0,4,1,

5,4,1

};

这里的数字,是第一个arrayindex
下面你要建立两个Buffer它们是用来存放这两个array的。


ByteBuffer bb = ByteBuffer.allocateDirect(vertex.length*4);

bb.order(ByteOrder.nativeOrder());

fbv=bb.asFloatBuffer();

fbv.put(vertex);

fbv.position(0);




ffe=ByteBuffer.allocateDirect(edge.length);

ffe.put(edge);

ffe.position(0);
这样一个三维的菱形就画好了。

下面你要写一个方法能让它自己把自己画出来!
public void draw(GL10 gl)

{

gl.glFrontFace(GL10.GL_CW);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fbv);

gl.glDrawElements(GL10.GL_TRIANGLES, 24, GL10.GL_UNSIGNED_BYTE, ffe);

}
这几句话费了我好大力气去理解。
先说第一个glFrontFace,物体都有一个正面一个反面,这里告诉opengl显示这个物体按顺时针方向(CW=> clockwise

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fbv);
这个方法是把本程序所用的点都传递个openglopengl需要知道什么哪?首先是 这个点是几维的(opengl 支持234 维),这里是3所以是三维的,第二个参数告诉opengl,这个点是用什么样类型的变量来储存的,这里是float类型。第三个是步长(stride), 这个我还没弄明白,不过我看的例子都为0. 最后把你建立好的三维坐标点都传给opengl

gl.glDrawElements
这个方法是告诉opengl如果要画这个图形,应该怎么画。第一个参数,告诉opengl 用画三角形(这样opengl就以三个点为一组),然后告诉opengl你要用到多少个点(注意这个点是在第二个array里的点数)。 第三个是告诉opengl这些点(其实是三维坐标点的reference)的类型。这里是unsigned byte。最后把你排列点的array 放进去!


这样一个三维的图形就建立完成了!


第二个大的步骤是创建一个让这个三维坐标运行的环境(Renderer)。
这是一个interface
首先,在onDrawFrame里,我们告诉本程序这个三维图形的行为:
在做任何事情之前,我们要清空所有以前内存里的东西,这个内存包括:Color Depth
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
然后告诉opengl你要用那个MatrixMode 这个就比较难解释了。

如果写程序 只要记住 GL_MODELVIEW 是管理图形的 缩放,移动,和转动就行了.

gl.glTranslatef(0, 0, -3.0f);
这个方法告诉opengl把图形沿z轴迁移3unit。这三个值分别是xyz轴。
gl.glRotatef(angle,0, 1, 0);
这个方法告诉我们以y为轴。 angle个度数。注意这里的10是告诉沿着那个轴转,别的值应该没有意义。
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
还记得上边说的openglclient sideservice side吗。 这个是告诉opengl如果client side调用draw什么的时候,这个vertex array是可用的。opengl有很多这样的可选项,所以需要告诉opengl,因为我们已经设置了vertex array(我们的第一个array,所以告诉opengl 它是可用的(如果不告诉,opengl会忽略)!

trian.draw(gl);
这个方法是把图形画出来。

angle++;
为了达到动态的效果,我们让每一个frame angle,比上一个多一度。

当显示空间大小发生变化的时候,我们应该告诉opengl一下信息:

public void onSurfaceChanged(GL10 gl, int width, int height)

{

// TODO Auto-generated method stub

gl.glViewport(0, 0, width, height);

gl.glMatrixMode(GL10.GL_PROJECTION);

gl.glLoadIdentity();

float ratio = (float)width/height;

gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);



}
首先是opengl可用的空间
gl.glViewport(0, 0, width, height);
想象一下用这四个点画出来的四边形,就是opengl所能用的空间。

gl.glMatrixMode(GL10.GL_PROJECTION);
这个matrix是如何把三维坐标转换为二维坐标并把它放在显示器上。
gl.glLoadIdentity
是告诉opengl初始化这个matrix

gl.glFrustumf
要把三维的东西用二维显示出来,需要知道几个东西,第一是这个显示平面有多大,你可以看多近和多远。这里的头四个参数,建立了一个四边形,告诉opengl把图形显示在这个范围了。后两个参数告诉opengl这里显示平面里可以显示三维空间里最近和最远的位置。


当这个三维图形建立的是时候,我们可以告诉opengl一些基本参数。这里把能省略的都省略了(其实什么都没有也可以运行!)
public void onSurfaceCreated(GL10 gl, EGLConfig arg1)

{

gl.glEnable(GL10.GL_DEPTH_TEST);

gl.glClearColor(0,0, 0, 0);

}

gl.glEnable(GL10.GL_DEPTH_TEST);
告诉opengl要检查depth,为什么哪。在三维空间里一个物体A在另一个物体B后面,那么这个AB挡住里,所以你是看不见的。我们要告诉 opengl,我们不想看见被挡住的东西。这个GL_DEPTH_TEST 就是这个功能。
gl.glClearColor(0,0, 0, 0);
设置这个背景颜色为黑色,应为我们没有给我们的三维图形设置颜色(为了简单),它的初始化颜色是白色。

这样这个环境就建立起来了!

下面该把它放进,android里了
public class Triangle extends Activity {
/** Called when the activity is first created. */

private GLSurfaceView my_view;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
my_view = new GLSurfaceView(this);
my_view.setRenderer(new MySimpleRendered());
this.setContentView(my_view);
}
public void onResume()
{

super.onResume();

my_view.onResume();
}
public void onPause()
{

super.onPause();

my_view.onPause();
}
}

这就是我的第一个3D例子。希望能给初学者一点点提示!

源代码:
package Beta.ThreeD;

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

import javax.microedition.khronos.opengles.GL10;

public class TriangleShape
{

private final float l=1.5f;

private FloatBuffer fbv;

private ByteBuffer ffe;

public TriangleShape()

{

float[] vertex={

0.0f,l,0.0f,

l,0.0f,0.0f,

0.0f,0.0f,l,

-l,0.0f,0.0f,

0.0f,0.0f,-l,

0.0f,-l,0.0f

};


byte[] edge=

{

0,1,2,

1,2,5,



0,2,3,

5,2,3,



0,3,4,

5,3,4,



0,4,1,

5,4,1

};

ByteBuffer bb = ByteBuffer.allocateDirect(vertex.length*4);

bb.order(ByteOrder.nativeOrder());

fbv=bb.asFloatBuffer();

fbv.put(vertex);

fbv.position(0);




ffe=ByteBuffer.allocateDirect(edge.length);

ffe.put(edge);

ffe.position(0);

}

public void draw(GL10 gl)

{

gl.glFrontFace(GL10.GL_CW);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fbv);

gl.glDrawElements(GL10.GL_TRIANGLES, 24, GL10.GL_UNSIGNED_BYTE, ffe);

}
}


package Beta.ThreeD;

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

import android.opengl.GLSurfaceView.Renderer;

public class MySimpleRendered implements Renderer
{

private int angle=50;

private TriangleShape trian;

public MySimpleRendered()

{

trian = new TriangleShape();

}

@Override

public void onDrawFrame(GL10 gl)

{

// TODO Auto-generated method stub

gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);

gl.glMatrixMode(GL10.GL_MODELVIEW);

gl.glLoadIdentity();

gl.glTranslatef(0, 0, -3.0f);

gl.glRotatef(angle,0, 1, 0);

gl.glRotatef(angle, 1, 0, 0);

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

trian.draw(gl);

angle++;

}


@Override

public void onSurfaceChanged(GL10 gl, int width, int height)

{

// TODO Auto-generated method stub

gl.glViewport(0, 0, width, height);

gl.glMatrixMode(GL10.GL_PROJECTION);

gl.glLoadIdentity();

float ratio = (float)width/height;

gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);



}


@Override

public void onSurfaceCreated(GL10 gl, EGLConfig arg1)

{

gl.glEnable(GL10.GL_DEPTH_TEST);

gl.glClearColor(0,0, 0, 0);

}

}
package Beta.ThreeD;

import android.app.Activity;
import android.os.Bundle;
import android.opengl.GLSurfaceView;
public class Triangle extends Activity {
/** Called when the activity is first created. */

private GLSurfaceView my_view;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
my_view = new GLSurfaceView(this);
my_view.setRenderer(new MySimpleRendered());
this.setContentView(my_view);
}
public void onResume()
{

super.onResume();

my_view.onResume();
}
public void onPause()
{

super.onPause();

my_view.onPause();
}
}


更多相关文章

  1. Android(安卓)数据库SQLite更新升级问题
  2. Android(安卓)Beam 告诉我们未来近距离数据传输新方式(视频)
  3. android 下使用GPS 无法获取经纬度的解决方法
  4. Android(安卓)实现广告欢迎界面(倒计时)
  5. Android中ListView的几种常见的优化方法
  6. 探讨android更新UI的几种方法
  7. 使用iTunes把电脑中的视频传到iPhone的方法
  8. 【iOS】网页中调用JS与JS注入
  9. Android简单实现屏幕下方Tab菜单的方法

随机推荐

  1. cpanel导入大数据库(mysql)的方法
  2. mysql数据库中查看当前使用的数据库是哪
  3. 彻底删除mysql服务(清理注册表)
  4. MYSQL获取更新行的主键ID
  5. 为mysql数据备份建立最小权限的用户
  6. 如何轻松地从MySQL迁移到PostgreSQL?
  7. mysql索引性能测试
  8. 如果发现自己的mysql没有充分利用CPU该关
  9. MySQL在Linux下Shell脚本操作命令
  10. 关于mysql 和Oracle的一大堆麻烦问题的解