package com.yarin.android.Examples_13_08; import java.io.BufferedReader; import java.io.InputStreamReader; import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLSurfaceView.Renderer; import android.view.KeyEvent; public class GLRender implements Renderer { public Random random = new Random(); FloatBuffer vertices = FloatBuffer.wrap(new float[512*3*3]); FloatBuffer colors = FloatBuffer.wrap(new float[512*3*4]); float xrot, yrot, zrot, // X, Y & Z Rotation xspeed, yspeed, zspeed, // X, Y & Z Spin Speed cx, cy, cz=-15; // X, Y & Z Position boolean morph=false; /* Default morph To False (Not Morphing) */ int step=0, steps=200; /* Step Counter And Maximum Number Of Steps */ int maxver; /* Will Eventually Hold The Maximum Number Of Vertices */ /* Our 4 Morphable Objects (morph1,2,3 & 4) */ OBJECT morph1 = new OBJECT(), morph2= new OBJECT(), morph3= new OBJECT(), morph4= new OBJECT(), helper= new OBJECT(), sour, dest; /* Helper Object, Source Object, Destination Object */ @Override public void onDrawFrame(GL10 gl) { int i; /* Temp X, Y & Z Variables */ float tx, ty, tz; /* Holds Returned Calculated Values For One Vertex */ VERTEX q = new VERTEX(0,0,0); /* Clear The Screen And The Depth Buffer */ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); /* Reset The View */ gl.glLoadIdentity(); /* Translate The The Current Position To Start Drawing */ gl.glTranslatef(cx, cy, cz); /* Rotate On The X Axis By xrot */ gl.glRotatef(xrot, 1, 0, 0); /* Rotate On The Y Axis By yrot */ gl.glRotatef(yrot, 0, 1, 0); /* Rotate On The Z Axis By zrot */ gl.glRotatef(zrot, 0, 0, 1); /* Increase xrot,yrot & zrot by xspeed, yspeed & zspeed */ xrot+=xspeed; yrot+=yspeed; zrot+=zspeed; /* Set pointers to vertex and texcoord arrays */ gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertices); gl.glColorPointer(4, GL10.GL_FLOAT, 0, colors); /* Enable vertex and color arrays */ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); colors.clear(); vertices.clear(); /* Begin Drawing Points */ /* Loop Through All The Verts Of morph1 */ for(i=0; i<morph1.verts; i++) { /* If morph Is True Calculate Movement Otherwise Movement=0 */ if (morph) { q=calculate(i); } else { q.x=q.y=q.z=0; } /* Subtract q.x Units From helper.points[i].x (Move On X Axis) */ helper.points.get(i).x-=q.x; /* Subtract q.y Units From helper.points[i].y (Move On Y Axis) */ helper.points.get(i).y-=q.y; /* Subtract q.z Units From helper.points[i].z (Move On Z Axis) */ helper.points.get(i).z-=q.z; /* Make Temp X Variable Equal To Helper's X Variable */ tx=helper.points.get(i).x; /* Make Temp Y Variable Equal To Helper's Y Variable */ ty=helper.points.get(i).y; /* Make Temp Z Variable Equal To Helper's Z Variable */ tz=helper.points.get(i).z; /* Set Color To A Bright Shade Of Off Blue */ colors.put(0.0f); colors.put(1.0f); colors.put(1.0f); colors.put(1.0f); /* Set A Point At The Current Temp Values (Vertex) */ vertices.put(tx); vertices.put(ty); vertices.put(tz); /* Darken Color A Bit */ colors.put(0.0f); colors.put(0.5f); colors.put(1.0f); colors.put(1.0f); /* Calculate Two Positions Ahead */ tx-=2*q.x; ty-=2*q.y; ty-=2*q.y; // Draw A Second Point At The Newly Calculate Position vertices.put(tx); vertices.put(ty); vertices.put(tz); /* Set Color To A Very Dark Blue */ colors.put(0.0f); colors.put(0.0f); colors.put(1.0f); colors.put(1.0f); /* Calculate Two More Positions Ahead */ tx-=2*q.x; ty-=2*q.y; ty-=2*q.y; /* Draw A Third Point At The Second New Position */ vertices.put(tx); vertices.put(ty); vertices.put(tz); /* This Creates A Ghostly Tail As Points Move */ } /* Done Drawing Points */ gl.glDrawArrays(GL10.GL_POINTS, 0, morph1.verts*3); /* Disable vertex and color arrays */ gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_COLOR_ARRAY); /* If We're Morphing And We Haven't Gone Through All 200 Steps Increase */ /* Our Step Counter Otherwise Set Morphing To False, Make Source=Dest */ /* And Set The Step Counter Back To Zero. */ if (morph && step<=steps) { step++; } else { morph=false; sour=dest; step=0; } gl.glFinish(); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { float ratio; /* Prevent A Divide By Zero By */ if (height==0) { /* Making Height Equal One */ height=1; } ratio=(float)width/(float)height; /* Reset The Current Viewport */ gl.glViewport(0, 0, width, height); /* Select The Projection Matrix */ gl.glMatrixMode(GL10.GL_PROJECTION); /* Reset The Projection Matrix */ gl.glLoadIdentity(); /* Calculate The Aspect Ratio Of The Window */ gl.glFrustumf(-ratio, ratio, -1, 1, 2.0f, 100.0f); //gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f); /* Select The Modelview Matrix */ gl.glMatrixMode(GL10.GL_MODELVIEW); /* Reset The Modelview Matrix */ gl.glLoadIdentity(); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { int i; /* Set The Blending Function For Translucency */ gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); /* This Will Clear The Background Color To Black */ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); /* Enables Clearing Of The Depth Buffer */ gl.glClearDepthf(1.0f); /* The Type Of Depth Test To Do */ gl.glDepthFunc(GL10.GL_LESS); /* Enables Depth Testing */ gl.glEnable(GL10.GL_DEPTH_TEST); /* Enables Smooth Color Shading */ gl.glShadeModel(GL10.GL_SMOOTH); /* Really Nice Perspective Calculations */ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); /* Sets Max Vertices To 0 By Default */ maxver=0; /* Load The First Object Into morph1 From File sphere.txt */ objload("sphere.txt",morph1); /* Load The Second Object Into morph2 From File torus.txt */ objload("torus.txt",morph2); /* Load The Third Object Into morph3 From File tube.txt */ objload("tube.txt",morph3); for(i=0; i<486; i++) { /* morph4 x Point Becomes A Random Float Value From -7 to 7 */ float xx=((float)(rand()%14000)/1000)-7; /* morph4 y Point Becomes A Random Float Value From -7 to 7 */ float yy=((float)(rand()%14000)/1000)-7; /* morph4 z Point Becomes A Random Float Value From -7 to 7 */ float zz=((float)(rand()%14000)/1000)-7; morph4.points.add(new VERTEX(xx,yy,zz)); } /* Load sphere.txt Object Into Helper (Used As Starting Point) */ objload("sphere.txt", helper); /* Source & Destination Are Set To Equal First Object (morph1) */ sour=dest=morph1; } public int rand() { return Math.abs(random.nextInt()); } /* Reads A String From File (f) */ public String readstr(BufferedReader br) { String str = ""; try { /* Do This */ do { /* Gets A String Of 255 Chars Max From f (File) */ //fgets(string, 255, f); str=br.readLine(); /* Until End Of Line Is Reached */ } while ((str.charAt(0) == '/')||(str.charAt(0)=='\n')); } catch (Exception e) { // TODO: handle exception } return str; } /* Loads Object From File (name) */ void objload(String name, OBJECT k) { int ver = 0; /* Will Hold Vertice Count */ String oneline; /* Holds One Line Of Text (255 Chars Max) */ int i; BufferedReader br = new BufferedReader(new InputStreamReader(GLFile.getFile(name))); //���������� oneline = readstr(br); ver=Integer.valueOf(oneline).intValue(); k.verts = ver; for (i=0; i<ver; i++) { oneline=readstr(br); String part[] = oneline.trim().split("\\s+"); float x = Float.valueOf(part[0]); float y = Float.valueOf(part[1]); float z = Float.valueOf(part[2]); VERTEX vertex = new VERTEX(x, y, z); k.points.add(vertex); } if (ver>maxver) { /* If ver Is Greater Than maxver Set maxver Equal To ver */ maxver=ver; } /* Keeps Track Of Highest Number Of Vertices Used In Any Of The Objects */ } /* Calculates Movement Of Points During Morphing */ VERTEX calculate(int i) { /* Temporary Vertex Called a */ VERTEX a = new VERTEX(0,0,0); /* a.x Value Equals Source x - Destination x Divided By Steps */ a.x=(sour.points.get(i).x-dest.points.get(i).x)/steps; /* a.y Value Equals Source y - Destination y Divided By Steps */ a.y=(sour.points.get(i).y-dest.points.get(i).y)/steps; /* a.z Value Equals Source z - Destination z Divided By Steps */ a.z=(sour.points.get(i).z-dest.points.get(i).z)/steps; /* Return The Results */ return a; /* This Makes Points Move At A Speed So They All Get To Their */ /* Destination At The Same Time */ } public boolean onKeyUp(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_1: if (!morph) { morph = true; dest = morph1; } break; case KeyEvent.KEYCODE_2: if (!morph) { morph = true; dest = morph2; } break; case KeyEvent.KEYCODE_3: if (!morph) { morph = true; dest = morph3; } break; case KeyEvent.KEYCODE_4: if (!morph) { morph = true; dest = morph4; } break; case KeyEvent.KEYCODE_N: zspeed+=0.01f;//������z����ת���ٶ� break; case KeyEvent.KEYCODE_M: zspeed-=0.01f;//������z����ת���ٶ� break; case KeyEvent.KEYCODE_Q: cz-=0.01f;// ����Ļ���ƶ� break; case KeyEvent.KEYCODE_Z: cz+=0.01f;// ����Ļ���ƶ� break; case KeyEvent.KEYCODE_W: cy+=0.01f;// �����ƶ� break; case KeyEvent.KEYCODE_S: cy-=0.01f;// �����ƶ� break; case KeyEvent.KEYCODE_D: cx+=0.01f;// �����ƶ� break; case KeyEvent.KEYCODE_A: cx-=0.01f;// �����ƶ� break; case KeyEvent.KEYCODE_DPAD_UP: xspeed-=0.01f;// ������x����ת���ٶ� break; case KeyEvent.KEYCODE_DPAD_DOWN: xspeed+=0.01f;// ������x����ת���ٶ� break; case KeyEvent.KEYCODE_DPAD_LEFT: yspeed-=0.01f;// ������y����ת���ٶ� break; case KeyEvent.KEYCODE_DPAD_RIGHT: yspeed+=0.01f;// ������y����ת���ٶ� break; } return false; } } class VERTEX { float x, y, z; /* X, Y & Z Points */ public VERTEX(float x,float y,float z) { this.x = x; this.y = y; this.z = z; } } class OBJECT { int verts; /* Number Of Vertices For The Object */ //VERTEX points; /* One Vertice (Vertex x, y & z) */ List<VERTEX> points = new ArrayList<VERTEX>(); }