六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 56|回复: 0

菱形3D实例

[复制链接]

升级  54.33%

109

主题

109

主题

109

主题

举人

Rank: 3Rank: 3

积分
363
 楼主| 发表于 2013-1-15 02:22:22 | 显示全部楼层 |阅读模式
下面是具体的实现方法:
首先需要建两个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};

这里的数字,是第一个array的index。
下面你要建立两个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);这个方法是把本程序所用的点都传递个opengl。opengl需要知道什么哪?首先是 这个点是几维的(opengl 支持2,3,4 维),这里是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 是管理图形的 缩放,移动,和转动就行了.(如果那个朋友想理解的更深一点,可以联系我,我可以把我的笔记发过去或者参考 http://glasnost.itcarlow.ie/~powerk/GeneralGraphicsNotes/projection/projection_viewing.html )。


gl.glTranslatef(0, 0, -3.0f);
这个方法告诉opengl把图形沿z轴迁移3个unit。这三个值分别是x,y,z轴。
gl.glRotatef(angle,0, 1, 0);
这个方法告诉我们以y为轴。 转angle个度数。注意这里的1和0是告诉沿着那个轴转,别的值应该没有意义。
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
还记得上边说的opengl分client side和service 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) {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后面,那么这个A被B挡住里,所以你是看不见的。我们要告诉opengl,我们不想看见被挡住的东西。这个GL_DEPTH_TEST 就是这个功能。
gl.glClearColor(0,0, 0, 0);
设置这个背景颜色为黑色,应为我们没有给我们的三维图形设置颜色(为了简单),它的初始化颜色是白色。

以下是源代码:
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();}@Overridepublic void onDrawFrame(GL10 gl) {// TODO Auto-generated method stubgl.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++;}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// TODO Auto-generated method stubgl.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);}@Overridepublic 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();    }}
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表