最近迫于生存压力,不得不给人兼职打工。故在博文中加了个求点击的链接。麻烦有时间的博友们帮我点击一下。没时间的不用勉强啊。不过请放心,我是做技术的,肯定链接没病毒,就是我打工的淘宝店铺。嘻嘻。http://shop108130013.taobao.com。谢谢捧场。以后就每周写篇原创的技术博客回报大家,实在是迫于生计,无所不用其极。请谅解。
同实例2的原理,在<Pro OpenGL ES for Android (2012)>一书第二章的第二个例子,3D翻转的球体。
学了几天,发现opengl这东西跟别的没什么两样,就是要多练。除此以外,还要多看看算法。这个对我来说,真的需要下苦功夫啊。
对应这个例子的完整代码已经上传到CSDN的资源页:http://download.csdn.net/download/fener10289/5265380
代码如下:
package book.SolarSystem; import book.SolarSystem.SolarSystemRenderer; import android.app.Activity; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.view.WindowManager; public class SolarSystemActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); GLSurfaceView view = new GLSurfaceView(this); view.setRenderer(new SolarSystemRenderer()); setContentView(view); } }
package book.SolarSystem; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLSurfaceView; import java.lang.Math; class SolarSystemRenderer implements GLSurfaceView.Renderer { public SolarSystemRenderer() { mPlanet=new Planet(10,10,1.0f, 1.0f); } public void onDrawFrame(GL10 gl) { gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glClearColor(0.0f,0.0f,0.0f,1.0f); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0f,(float)Math.sin(mTransY), -4.0f); gl.glRotatef(mAngle, 1, 0, 0); gl.glRotatef(mAngle, 0, 1, 0); mPlanet.draw(gl); mTransY+=.075f; mAngle+=.4; } public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glViewport(0, 0, width, height); /* * Set our projection matrix. This doesn't have to be done * each time we draw, but usually a new projection needs to * be set when the viewport is resized. */ float aspectRatio; float zNear =.1f; float zFar =1000f; float fieldOfView = 30.0f/57.3f; float size; gl.glEnable(GL10.GL_NORMALIZE); aspectRatio=(float)width/(float)height; //h/w clamps the fov to the height, flipping it would make it relative to the width //Set the OpenGL projection matrix gl.glMatrixMode(GL10.GL_PROJECTION); size = zNear * (float)(Math.tan((double)(fieldOfView/2.0f))); gl.glFrustumf(-size, size, -size/aspectRatio, size /aspectRatio, zNear, zFar); //Make the OpenGL modelview matrix the default gl.glMatrixMode(GL10.GL_MODELVIEW); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { /* * By default, OpenGL enables features that improve quality * but reduce performance. One might want to tweak that * especially on software renderer. */ gl.glDisable(GL10.GL_DITHER); /* * Some one-time OpenGL initialization can be made here * probably based on features of this particular context */ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); gl.glEnable(GL10.GL_CULL_FACE); gl.glCullFace(GL10.GL_BACK); gl.glShadeModel(GL10.GL_SMOOTH); gl.glEnable(GL10.GL_DEPTH_TEST); } private Planet mPlanet; private float mTransY; private float mAngle; }
package book.SolarSystem; import java.util.*; import java.nio.*; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLES11; public class Planet { FloatBuffer m_VertexData; FloatBuffer m_NormalData; FloatBuffer m_ColorData; float m_Scale; float m_Squash; float m_Radius; int m_Stacks, m_Slices; public Planet(int stacks, int slices, float radius, float squash) { this.m_Stacks = stacks; this.m_Slices = slices; this.m_Radius = radius; this.m_Squash = squash; init(m_Stacks,m_Slices,radius,squash,"dummy"); } private void init(int stacks,int slices, float radius, float squash, String textureFile) { float[] vertexData; float[] colorData; float colorIncrement=0f; float blue=0f; float red=1.0f; int vIndex=0; //vertex index int cIndex=0; //color index m_Scale=radius; m_Squash=squash; colorIncrement=1.0f/(float)stacks; { m_Stacks = stacks; m_Slices = slices; //vertices vertexData = new float[ 3*((m_Slices*2+2) * m_Stacks)]; //color data colorData = new float[ (4*(m_Slices*2+2) * m_Stacks)]; int phiIdx, thetaIdx; //latitude for(phiIdx=0; phiIdx < m_Stacks; phiIdx++) { //starts at -90 degrees (-1.57 radians) goes up to +90 degrees (or +1.57 radians) //the first circle float phi0 = (float)Math.PI * ((float)(phiIdx+0) * (1.0f/(float)(m_Stacks)) - 0.5f); //the next, or second one. float phi1 = (float)Math.PI * ((float)(phiIdx+1) * (1.0f/(float)(m_Stacks)) - 0.5f); float cosPhi0 = (float)Math.cos(phi0); float sinPhi0 = (float)Math.sin(phi0); float cosPhi1 = (float)Math.cos(phi1); float sinPhi1 = (float)Math.sin(phi1); float cosTheta, sinTheta; //longitude for(thetaIdx=0; thetaIdx < m_Slices; thetaIdx++) { //increment along the longitude circle each "slice" float theta = (float) (-2.0f*(float)Math.PI * ((float)thetaIdx) * (1.0/(float)(m_Slices-1))); cosTheta = (float)Math.cos(theta); sinTheta = (float)Math.sin(theta); //we're generating a vertical pair of points, such //as the first point of stack 0 and the first point of stack 1 //above it. This is how TRIANGLE_STRIPS work, //taking a set of 4 vertices and essentially drawing two triangles //at a time. The first is v0-v1-v2 and the next is v2-v1-v3. Etc. //get x-y-z for the first vertex of stack vertexData[vIndex+0] = m_Scale*cosPhi0*cosTheta; vertexData[vIndex+1] = m_Scale*(sinPhi0*m_Squash); vertexData[vIndex+2] = m_Scale*(cosPhi0*sinTheta); vertexData[vIndex+3] = m_Scale*cosPhi1*cosTheta; vertexData[vIndex+4] = m_Scale*(sinPhi1*m_Squash); vertexData[vIndex+5] = m_Scale*(cosPhi1*sinTheta); colorData[cIndex+0] = (float)red; colorData[cIndex+1] = (float)0f; colorData[cIndex+2] = (float)blue; colorData[cIndex+4] = (float)red; colorData[cIndex+5] = (float)0f; colorData[cIndex+6] = (float)blue; colorData[cIndex+3] = (float)1.0; colorData[cIndex+7] = (float)1.0; cIndex+=2*4; vIndex+=2*3; } blue+=colorIncrement; red-=colorIncrement; // create a degenerate triangle to connect stacks and maintain winding order vertexData[vIndex+0] = vertexData[vIndex+3] = vertexData[vIndex-3]; vertexData[vIndex+1] = vertexData[vIndex+4] = vertexData[vIndex-2]; vertexData[vIndex+2] = vertexData[vIndex+5] = vertexData[vIndex-1]; } } m_VertexData = makeFloatBuffer(vertexData); m_ColorData = makeFloatBuffer(colorData); } public void draw(GL10 gl) { gl.glFrontFace(GL10.GL_CW); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, m_VertexData); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glColorPointer(4, GL10.GL_FLOAT, 0, m_ColorData); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, (m_Slices+1)*2*(m_Stacks-1)+2); } protected static FloatBuffer makeFloatBuffer(float[] arr) { ByteBuffer bb = ByteBuffer.allocateDirect(arr.length*4); bb.order(ByteOrder.nativeOrder()); FloatBuffer fb = bb.asFloatBuffer(); fb.put(arr); fb.position(0); return fb; } }
package book.SolarSystem; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL11; /** * A vertex shaded cube. */ class Cube { public Cube() { 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 }; byte maxColor=(byte)255; byte colors[] = { maxColor,maxColor, 0,maxColor, 0, maxColor,maxColor,maxColor, 0, 0, 0,maxColor, maxColor, 0,maxColor,maxColor, maxColor, 0, 0,maxColor, 0, maxColor, 0,maxColor, 0, 0,maxColor,maxColor, 0, 0, 0,maxColor }; byte tfan1[] = { 1,0,3, 1,3,2, 1,2,6, 1,6,5, 1,5,4, 1,4,0 }; byte tfan2[] = { 7,4,5, 7,5,6, 7,6,2, 7,2,3, 7,3,0, 7,0,4 }; ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); mFVertexBuffer = vbb.asFloatBuffer(); mFVertexBuffer.put(vertices); mFVertexBuffer.position(0); mColorBuffer = ByteBuffer.allocateDirect(colors.length); mColorBuffer.put(colors); mColorBuffer.position(0); mTfan1 = ByteBuffer.allocateDirect(tfan1.length); mTfan1.put(tfan1); mTfan1.position(0); mTfan2 = ByteBuffer.allocateDirect(tfan2.length); mTfan2.put(tfan2); mTfan2.position(0); } public void draw(GL10 gl) { gl.glVertexPointer(3, GL11.GL_FLOAT, 0, mFVertexBuffer); gl.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, 0, mColorBuffer); gl.glDrawElements( GL11.GL_TRIANGLE_FAN, 6 * 3, GL11.GL_UNSIGNED_BYTE, mTfan1); gl.glDrawElements( GL11.GL_TRIANGLE_FAN, 6 * 3, GL11.GL_UNSIGNED_BYTE, mTfan2); } private FloatBuffer mFVertexBuffer; private ByteBuffer mColorBuffer; private ByteBuffer mIndexBuffer; private ByteBuffer mTfan1; private ByteBuffer mTfan2; }