球体数据结构
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; // 1 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; // 2 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_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)]; // 4 // color data colorData = new float[(4 * (m_Slices * 2 + 2) * m_Stacks)]; // 5 int phiIdx, thetaIdx; // latitude 纬度 for (phiIdx = 0; phiIdx < m_Stacks; phiIdx++) { // 从 -90度 - +90度(-1.57-+1.57弧度) // 第一个圆 float phi0 = (float) Math.PI * ((float) (phiIdx + 0) * (1.0f / (float) (m_Stacks)) - 0.5f); // the next, or second one. // 8 float phi1 = (float) Math.PI * ((float) (phiIdx + 1) * (1.0f / (float) (m_Stacks)) - 0.5f); float cosPhi0 = (float) Math.cos(phi0); // 9 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++) { 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; // 11 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; // 12 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; // 13 vIndex += 2 * 3; // 14 } blue += colorIncrement; // 15 red -= colorIncrement; // create a degenerate triangle to connect stacks and maintain // winding order // 16 Log.i("hello", "vIndex:" + vIndex); 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); // 17 m_ColorData = makeFloatBuffer(colorData); } 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; } public void draw(GL10 gl) { gl.glFrontFace(GL10.GL_CW); // 1 // 第一个参数表示坐标的维数,可以是2或者3,如果是2,则坐标为(x,y),z轴默认为0;如果是3,则坐标为(x,y,z) // 第二个参数可以是GL10.GL_FIXED或者GL10.GL_FLOAT,如果是GL10.GL_FIXED,则第四个参数为IntBuffer类 // 型,如果为GL10.GL_FLOAT,则第四个参数为FloatBuffer类型 // 第三个参数表示步长 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, m_VertexData); // 2 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glColorPointer(4, GL10.GL_FLOAT, 0, m_ColorData); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); // 3 // GL10.GL_LINE_STRIP 显示线条 // 第一个参数有三种类型GL10.GL_TRIANGLES、GL10.GL_TRIANGLE_FAN、GL10.GL_TRIANGLE_STRIP // GL_TRIANGLES:每三个顶之间绘制三角形,之间不连接 // GL_TRIANGLE_FAN:以V0V1V2,V0V2V3,V0V3V4,……的形式绘制三角形 // GL_TRIANGLE_STRIP:顺序在每三个顶点之间均绘制三角形。这个方法可以保证从相同的方向上所有以三角形均被绘制。以V0V1V2,V1V2V3,V2V3V4……的形式绘制三角形 gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, (m_Slices + 1) * 2 * (m_Stacks - 1) + 2); }}
renderer
public class SolarSystemRenderer implements GLSurfaceView.Renderer { private Planet mPlanet; private float mAngle; private float mTransY; public SolarSystemRenderer() { mPlanet = new Planet(10, 10, 1.0f, 1.0f); } @Override 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(); // (x,y,z) 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; } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // 设置OpenGL场景的大小 gl.glViewport(0, 0, width, height); // 12 float ratio = (float) width / height; // 设置投影矩阵 gl.glMatrixMode(GL10.GL_PROJECTION); // 13 gl.glLoadIdentity(); // 设置视图的大小 gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glDisable(GL10.GL_DITHER); // 16 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, // 17 GL10.GL_FASTEST); gl.glClearColor(1, 1, 1, 1); gl.glEnable(GL10.GL_CULL_FACE); // 19 gl.glShadeModel(GL10.GL_SMOOTH); // 20 gl.glEnable(GL10.GL_DEPTH_TEST); }}