在freeglut_geometry.c中定义了几种常见图形的绘制,包括立方体, 球面, 圆锥体, 圆柱体, 圆环面, 十二面体, 八面体, 四面体, 二十面体, 菱形十二面体(斜十二面体)等几种立体几何对象的绘制。 移植后的Android Java代码如下所示:
/**
* fyjengine All Rights Reserved
*
* @author Yajun Fu
* 2011-11-4
*
* porting functions from freeglut
*/
package fyj.engine.utils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
public class FreeGLUT {
/*
* 立方体(线框)
*/
public static void glutWireCube(GL10 gl, float dSize) {
float size = dSize * 0.5f;
ByteBuffer bb = ByteBuffer.allocateDirect(24 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = bb.asFloatBuffer();
vertexBuffer.position(0);
bb = ByteBuffer.allocateDirect(24 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normalBuffer = bb.asFloatBuffer();
normalBuffer.position(0);
vertexBuffer.put(new float[] { +size, -size, +size, +size, -size,
-size, +size, +size, -size, +size, +size, +size,
+size, +size, +size, +size, +size, -size, -size, +size, -size,
-size, +size, +size,
+size, +size, +size, -size, +size, +size, -size, -size, +size,
+size, -size, +size,
-size, -size, +size, -size, +size, +size, -size, +size, -size,
-size, -size, -size,
-size, -size, +size, -size, -size, -size, +size, -size, -size,
+size, -size, +size,
-size, -size, -size, -size, +size, -size, +size, +size, -size,
+size, -size, -size });
normalBuffer.put(new float[] { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f,
-1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f,
0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-1.0f, 0.0f,
0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
0.0f, -1.0f,
});
vertexBuffer.position(0);
normalBuffer.position(0);
gl.glColor4f(1, 0, 0, 1);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normalBuffer);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
for (int i = 0; i < 6; i++)
gl.glDrawArrays(GL10.GL_LINE_LOOP, 4 * i, 4);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
}
/*
* 立方体
*/
public static void glutSolidCube(GL10 gl, float dSize) {
float size = dSize * 0.5f;
ByteBuffer bb = ByteBuffer.allocateDirect(24 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = bb.asFloatBuffer();
vertexBuffer.position(0);
bb = ByteBuffer.allocateDirect(24 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normalBuffer = bb.asFloatBuffer();
normalBuffer.position(0);
vertexBuffer.put(new float[] { +size, -size, +size, +size, -size,
-size, +size, +size, -size, +size, +size, +size,
+size, +size, +size, +size, +size, -size, -size, +size, -size,
-size, +size, +size,
+size, +size, +size, -size, +size, +size, -size, -size, +size,
+size, -size, +size,
-size, -size, +size, -size, +size, +size, -size, +size, -size,
-size, -size, -size,
-size, -size, +size, -size, -size, -size, +size, -size, -size,
+size, -size, +size,
-size, -size, -size, -size, +size, -size, +size, +size, -size,
+size, -size, -size });
normalBuffer.put(new float[] { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f,
-1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f,
0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-1.0f, 0.0f,
0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
0.0f, -1.0f, });
vertexBuffer.position(0);
normalBuffer.position(0);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normalBuffer);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
for (int i = 0; i < 6; i++)
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 4 * i, 4);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
bb.clear();
vertexBuffer.clear();
normalBuffer.clear();
}
private static void fghCircleTable(float sint[], float cost[], int n) {
int i;
/* Table size, the sign of n flips the circle direction */
int size = Math.abs(n);
/* Determine the angle between samples */
float angle = (float) (2 * Math.PI / (float) ((n == 0) ? 1 : n));
/* Compute cos and sin around the circle */
sint[0] = 0.0f;
cost[0] = 1.0f;
for (i = 1; i < size; i++) {
sint[i] = (float) Math.sin(angle * i);
cost[i] = (float) Math.cos(angle * i);
}
/* Last sample is duplicate of the first */
sint[size] = sint[0];
cost[size] = cost[0];
}
/*
* 球面(线框)
*/
public static void glutWireSphere(GL10 gl, float radius, int slices,
int stacks) {
int i, j;
/* Adjust z and radius as stacks and slices are drawn. */
float r;
float x, y, z;
/* Pre-computed circle */
float sint1[] = new float[slices + 1], cost1[] = new float[slices + 1];
float sint2[] = new float[stacks * 2 + 1], cost2[] = new float[stacks * 2 + 1];
fghCircleTable(sint1, cost1, -slices);
fghCircleTable(sint2, cost2, stacks * 2);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
ByteBuffer bb = ByteBuffer.allocateDirect((slices + 1) * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normals = bb.asFloatBuffer();
normals.position(0);
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
/* Draw a line loop for each stack */
for (i = 1; i < stacks; i++) {
z = cost2[i];
r = sint2[i];
for (j = 0; j <= slices; j++) {
x = cost1[j];
y = sint1[j];
normals.put(new float[] { x, y, z });
vertex.put(new float[] { x * r * radius, y * r * radius,
z * radius });
}
normals.position(0);
vertex.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normals);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, slices + 1);
}
/* Draw a line loop for each slice */
bb = ByteBuffer.allocateDirect((stacks + 1) * 3 * 4);
bb.order(ByteOrder.nativeOrder());
vertex = bb.asFloatBuffer();
vertex.position(0);
normals = bb.asFloatBuffer();
normals.position(0);
for (i = 0; i < slices; i++) {
for (j = 0; j <= stacks; j++) {
x = cost1[i] * sint2[j];
y = sint1[i] * sint2[j];
z = cost2[j];
normals.put(new float[] { x, y, z });
vertex.put(new float[] { x * radius, y * radius, z * radius });
}
normals.position(0);
vertex.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normals);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, stacks + 1);
}
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
/*
* 球面
*/
public static void glutSolidSphere(GL10 gl, float radius, int slices,
int stacks) {
int i, j;
/* Adjust z and radius as stacks are drawn. */
float z0, z1;
float r0, r1;
/* Pre-computed circle */
float sint1[] = new float[slices + 1], cost1[] = new float[slices + 1];
float sint2[] = new float[stacks * 2 + 1], cost2[] = new float[stacks * 2 + 1];
fghCircleTable(sint1, cost1, -slices);
fghCircleTable(sint2, cost2, stacks * 2);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
/* The top stack is covered with a triangle fan */
z0 = 1.0f;
z1 = cost2[(stacks > 0) ? 1 : 0];
r0 = 0.0f;
r1 = sint2[(stacks > 0) ? 1 : 0];
ByteBuffer bb = ByteBuffer.allocateDirect((slices + 2) * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normals = bb.asFloatBuffer();
normals.position(0);
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
normals.put(new float[] { 0, 0, 1 });
vertex.put(new float[] { 0, 0, radius });
for (j = slices; j >= 0; j--) {
normals.put(new float[] { cost1[j] * r1, sint1[j] * r1, z1 });
vertex.put(new float[] { cost1[j] * r1 * radius,
sint1[j] * r1 * radius, z1 * radius });
}
vertex.position(0);
normals.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normals);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, slices + 2);
bb = ByteBuffer.allocateDirect((slices + 1) * 3 * 2 * 4);
bb.order(ByteOrder.nativeOrder());
normals = bb.asFloatBuffer();
vertex = bb.asFloatBuffer();
/* Cover each stack with a quad strip, except the top and bottom stacks */
for (i = 1; i < stacks - 1; i++) {
z0 = z1;
z1 = cost2[i + 1];
r0 = r1;
r1 = sint2[i + 1];
normals.position(0);
vertex.position(0);
for (j = 0; j <= slices; j++) {
normals.put(new float[] { cost1[j] * r1, sint1[j] * r1, z1 });
vertex.put(new float[] { cost1[j] * r1 * radius,
sint1[j] * r1 * radius, z1 * radius });
normals.put(new float[] { cost1[j] * r0, sint1[j] * r0, z0 });
vertex.put(new float[] { cost1[j] * r0 * radius,
sint1[j] * r0 * radius, z0 * radius });
}
vertex.position(0);
normals.position(0);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normals);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, (slices + 1) * 2);
}
/* The bottom stack is covered with a triangle fan */
z0 = z1;
r0 = r1;
bb = ByteBuffer.allocateDirect((slices + 2) * 3 * 4);
bb.order(ByteOrder.nativeOrder());
normals = bb.asFloatBuffer();
normals.position(0);
vertex = bb.asFloatBuffer();
vertex.position(0);
normals.put(new float[] { 0, 0, -1 });
vertex.put(new float[] { 0, 0, -radius });
for (j = 0; j <= slices; j++) {
normals.put(new float[] { cost1[j] * r0, sint1[j] * r0, z0 });
vertex.put(new float[] { cost1[j] * r0 * radius,
sint1[j] * r0 * radius, z0 * radius });
}
vertex.position(0);
normals.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normals);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, slices + 2);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
/*
* 圆锥体(线框)
*/
public static void glutWireCone(GL10 gl, float base, float height,
int slices, int stacks) {
int i, j;
/* Step in z and radius as stacks are drawn. */
float z = 0.0f;
float r = base;
float zStep = height / ((stacks > 0) ? stacks : 1);
float rStep = base / ((stacks > 0) ? stacks : 1);
/* Scaling factors for vertex normals */
float cosn = (height / (float) Math.sqrt(height * height + base * base));
float sinn = (base / (float) Math.sqrt(height * height + base * base));
/* Pre-computed circle */
float sint[] = new float[slices + 1], cost[] = new float[slices + 1];
fghCircleTable(sint, cost, -slices);
/* Draw the stacks... */
ByteBuffer bb = ByteBuffer.allocateDirect(slices * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
for (i = 0; i < stacks; i++) {
for (j = 0; j < slices; j++) {
normal.put(new float[] { cost[j] * sinn, sint[j] * sinn, cosn });
vertex.put(new float[] { cost[j] * r, sint[j] * r, z });
}
normal.position(0);
vertex.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, slices);
z += zStep;
r -= rStep;
}
/* Draw the slices */
r = base;
bb = ByteBuffer.allocateDirect(slices * 2 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
vertex = bb.asFloatBuffer();
vertex.position(0);
normal.position(0);
for (j = 0; j < slices; j++) {
normal.put(new float[] { cost[j] * sinn, sint[j] * sinn, cosn });
vertex.put(new float[] { cost[j] * r, sint[j] * r, 0.0f, 0.0f,
0.0f, height });
}
vertex.position(0);
normal.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_LINES, 0, slices);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
}
/*
* 圆锥体
*/
public static void glutSolidCone(GL10 gl, float base, float height,
int slices, int stacks) {
int i, j;
/* Step in z and radius as stacks are drawn. */
float z0, z1;
float r0, r1;
float zStep = height / ((stacks > 0) ? stacks : 1);
float rStep = base / ((stacks > 0) ? stacks : 1);
/* Scaling factors for vertex normals */
float cosn = (height / (float) Math.sqrt(height * height + base * base));
float sinn = (base / (float) Math.sqrt(height * height + base * base));
/* Pre-computed circle */
float sint[] = new float[slices + 2], cost[] = new float[slices + 2];
fghCircleTable(sint, cost, -slices);
/* Cover the circular base with a triangle fan... */
z0 = 0.0f;
z1 = zStep;
r0 = base;
r1 = r0 - rStep;
ByteBuffer bb = ByteBuffer.allocateDirect((slices + 2) * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
bb = ByteBuffer.allocateDirect(3 * 4);
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
normal.put(new float[] { 0.0f, 0.0f, -1.0f });
vertex.put(new float[] { 0.0f, 0.0f, z0 });
for (j = 0; j <= slices; j++)
vertex.put(new float[] { cost[j] * r0, sint[j] * r0, z0 });
normal.position(0);
vertex.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, slices + 2);
/* Cover each stack with a quad strip, except the top stack */
bb = ByteBuffer.allocateDirect((slices + 1) * 2 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
vertex = bb.asFloatBuffer();
vertex.position(0);
bb = ByteBuffer.allocateDirect((slices + 1) * 3 * 4);
normal = bb.asFloatBuffer();
normal.position(0);
for (i = 0; i < stacks - 1; i++) {
for (j = 0; j <= slices; j++) {
normal.put(new float[] { cost[j] * sinn, sint[j] * sinn, cosn });
vertex.put(new float[] { cost[j] * r0, sint[j] * r0, z0,
cost[j] * r1, sint[j] * r1, z1 });
}
vertex.position(0);
normal.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, (slices + 1) * 2);
z0 = z1;
z1 += zStep;
r0 = r1;
r1 -= rStep;
}
/* The top stack is covered with individual triangles */
bb = ByteBuffer.allocateDirect(slices * 3 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
vertex = bb.asFloatBuffer();
vertex.position(0);
bb = ByteBuffer.allocateDirect((slices + 1) * 3 * 4);
normal = bb.asFloatBuffer();
normal.position(0);
normal.put(new float[] { cost[0] * sinn, sint[0] * sinn, cosn });
for (j = 0; j < slices; j++) {
vertex.put(new float[] { cost[j + 0] * r0, sint[j + 0] * r0, z0, 0,
0, height, cost[j + 1] * r0, sint[j + 1] * r0, z0 });
normal.put(new float[] { cost[j + 1] * sinn, sint[j + 1] * sinn,
cosn });
}
vertex.position(0);
normal.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, slices * 3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
}
/*
* 圆柱体(线框)
*/
public static void glutWireCylinder(GL10 gl, float radius, float height,
int slices, int stacks) {
int i, j;
/* Step in z and radius as stacks are drawn. */
float z = 0.0f;
float zStep = height / ((stacks > 0) ? stacks : 1);
/* Pre-computed circle */
float sint[] = new float[slices + 1], cost[] = new float[slices + 1];
fghCircleTable(sint, cost, -slices);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
/* Draw the stacks... */
ByteBuffer bb = ByteBuffer.allocateDirect(slices * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
for (i = 0; i <= stacks; i++) {
if (i == stacks)
z = height;
for (j = 0; j < slices; j++) {
normal.put(new float[] { cost[j], sint[j], 0.0f });
vertex.put(new float[] { cost[j] * radius, sint[j] * radius, z });
}
normal.position(0);
vertex.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, slices);
z += zStep;
}
/* Draw the slices */
bb = ByteBuffer.allocateDirect(slices * 2 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
vertex = bb.asFloatBuffer();
vertex.position(0);
bb = ByteBuffer.allocateDirect(slices * 3 * 4);
normal = bb.asFloatBuffer();
normal.position(0);
for (j=0; j<slices; j++)
{
normal.put(new float[] {
cost[j], sint[j], 0.0f
});
vertex.put(new float[] {
cost[j]*radius, sint[j]*radius, 0.0f,
cost[j]*radius, sint[j]*radius, height
});
}
normal.position(0);
vertex.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_LINES, 0, slices);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
}
/*
* 圆柱体
*/
public static void glutSolidCylinder(GL10 gl, float radius, float height,
int slices, int stacks) {
int i, j;
/* Step in z and radius as stacks are drawn. */
float z0, z1;
float zStep = height / ((stacks > 0) ? stacks : 1);
/* Pre-computed circle */
float sint[] = new float[slices + 2], cost[] = new float[slices + 2];
fghCircleTable(sint, cost, -slices);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
/* Cover the base and top */
ByteBuffer bb = ByteBuffer.allocateDirect((slices+2) * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
bb = ByteBuffer.allocateDirect(3 * 4);
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
normal.put(new float[] {
0.0f, 0.0f, -1.0f
});
vertex.put(new float[] {
0.0f, 0.0f, 0.0f
});
for (j=0; j<=slices; j++)
vertex.put(new float[] {
cost[j]*radius, sint[j]*radius, 0.0f
});
vertex.position(0);
normal.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, slices+2);
vertex.position(0);
normal.position(0);
normal.put(new float[] {
0.0f, 0.0f, 1.0f
});
vertex.put(new float[] {
0.0f, 0.0f, height
});
for (j=slices; j>=0; j--)
vertex.put(new float[] {
cost[j]*radius, sint[j]*radius, height
});
vertex.position(0);
normal.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, slices+2);
/* Do the stacks */
z0 = 0.0f;
z1 = zStep;
bb = ByteBuffer.allocateDirect((slices+1) * 2 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
vertex = bb.asFloatBuffer();
vertex.position(0);
bb = ByteBuffer.allocateDirect((slices+1) * 3 * 4);
normal = bb.asFloatBuffer();
normal.position(0);
for (i=1; i<=stacks; i++)
{
if (i==stacks)
z1 = height;
for (j=0; j<=slices; j++ )
{
normal.put(new float[] {
cost[j], sint[j], 0.0f
});
vertex.put(new float[] {
cost[j]*radius, sint[j]*radius, z0,
cost[j]*radius, sint[j]*radius, z1
});
}
normal.position(0);
vertex.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, (slices+1) * 2);
z0 = z1; z1 += zStep;
}
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
}
/*
* 圆环面(线框)
*/
public static void glutWireTorus(GL10 gl, float dInnerRadius,
float dOuterRadius, int nSides, int nRings) {
float iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
FloatBuffer vertex, normal;
int i, j;
float spsi, cpsi, sphi, cphi;
if (nSides < 1)
nSides = 1;
if (nRings < 1)
nRings = 1;
/*
* Increment the number of sides and rings to allow for one more point
* than surface
*/
nSides++;
nRings++;
float vertexArray[] = new float[3 * nSides * nRings];
float normalArray[] = new float[3 * nSides * nRings];
gl.glPushMatrix();
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
dpsi = 2.0f * (float) Math.PI / (float) (nRings - 1);
dphi = -2.0f * (float) Math.PI / (float) (nSides - 1);
psi = 0.0f;
for (j = 0; j < nRings; j++) {
cpsi = (float) Math.cos(psi);
spsi = (float) Math.sin(psi);
phi = 0.0f;
for (i = 0; i < nSides; i++) {
int offset = 3 * (j * nSides + i);
cphi = (float) Math.cos(phi);
sphi = (float) Math.sin(phi);
vertexArray[offset + 0] = cpsi * (oradius + cphi * iradius);
vertexArray[offset + 1] = spsi * (oradius + cphi * iradius);
vertexArray[offset + 2] = sphi * iradius;
normalArray[offset + 0] = cpsi * cphi;
normalArray[offset + 1] = spsi * cphi;
normalArray[offset + 2] = sphi;
phi += dphi;
}
psi += dpsi;
}
ByteBuffer bb = ByteBuffer.allocateDirect((nSides - 1) * (nRings - 1)
* 4 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
vertex = bb.asFloatBuffer();
vertex.position(0);
normal = bb.asFloatBuffer();
normal.position(0);
for (i = 0; i < nSides - 1; i++) {
for (j = 0; j < nRings - 1; j++) {
int offset = 3 * (j * nSides + i);
normal.put(new float[] { normalArray[offset],
normalArray[offset + 1], normalArray[offset + 2],
normalArray[offset + 3], normalArray[offset + 4],
normalArray[offset + 5],
normalArray[offset + 3 * nSides + 3],
normalArray[offset + 3 * nSides + 4],
normalArray[offset + 3 * nSides + 5],
normalArray[offset + 3 * nSides],
normalArray[offset + 3 * nSides + 1],
normalArray[offset + 3 * nSides + 2] });
vertex.put(new float[] { vertexArray[offset],
vertexArray[offset + 1], vertexArray[offset + 2],
vertexArray[offset + 3], vertexArray[offset + 4],
vertexArray[offset + 5],
vertexArray[offset + 3 * nSides + 3],
vertexArray[offset + 3 * nSides + 4],
vertexArray[offset + 3 * nSides + 5],
vertexArray[offset + 3 * nSides],
vertexArray[offset + 3 * nSides + 1],
vertexArray[offset + 3 * nSides + 2] });
}
}
vertex.position(0);
normal.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, (nSides - 1) * (nRings - 1) * 4);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glPopMatrix();
}
/*
* 圆环面
*/
public static void glutSolidTorus(GL10 gl, float dInnerRadius,
float dOuterRadius, int nSides, int nRings) {
float iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
FloatBuffer vertex, normal;
int i, j;
float spsi, cpsi, sphi, cphi;
if (nSides < 1)
nSides = 1;
if (nRings < 1)
nRings = 1;
/*
* Increment the number of sides and rings to allow for one more point
* than surface
*/
nSides++;
nRings++;
float vertexArray[] = new float[3 * nSides * nRings];
float normalArray[] = new float[3 * nSides * nRings];
gl.glPushMatrix();
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
dpsi = 2.0f * (float) Math.PI / (float) (nRings - 1);
dphi = -2.0f * (float) Math.PI / (float) (nSides - 1);
psi = 0.0f;
for (j = 0; j < nRings; j++) {
cpsi = (float) Math.cos(psi);
spsi = (float) Math.sin(psi);
phi = 0.0f;
for (i = 0; i < nSides; i++) {
int offset = 3 * (j * nSides + i);
cphi = (float) Math.cos(phi);
sphi = (float) Math.sin(phi);
vertexArray[offset + 0] = cpsi * (oradius + cphi * iradius);
vertexArray[offset + 1] = spsi * (oradius + cphi * iradius);
vertexArray[offset + 2] = sphi * iradius;
normalArray[offset + 0] = cpsi * cphi;
normalArray[offset + 1] = spsi * cphi;
normalArray[offset + 2] = sphi;
phi += dphi;
}
psi += dpsi;
}
ByteBuffer bb = ByteBuffer.allocateDirect((nSides - 1) * (nRings - 1)
* 4 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
vertex = bb.asFloatBuffer();
vertex.position(0);
normal = bb.asFloatBuffer();
normal.position(0);
for (i = 0; i < nSides - 1; i++) {
for (j = 0; j < nRings - 1; j++) {
int offset = 3 * (j * nSides + i);
normal.put(new float[] { normalArray[offset + 3 * nSides],
normalArray[offset + 3 * nSides + 1],
normalArray[offset + 3 * nSides + 2],
normalArray[offset], vertexArray[offset + 1],
normalArray[offset + 2],
normalArray[offset + 3 * nSides + 3],
normalArray[offset + 3 * nSides + 4],
normalArray[offset + 3 * nSides + 5],
normalArray[offset + 3], vertexArray[offset + 4],
normalArray[offset + 5] });
vertex.put(new float[] { vertexArray[offset + 3 * nSides],
vertexArray[offset + 3 * nSides + 1],
vertexArray[offset + 3 * nSides + 2],
vertexArray[offset], vertexArray[offset + 1],
vertexArray[offset + 2],
vertexArray[offset + 3 * nSides + 3],
vertexArray[offset + 3 * nSides + 4],
vertexArray[offset + 3 * nSides + 5],
vertexArray[offset + 3], vertexArray[offset + 4],
vertexArray[offset + 5] });
}
}
vertex.position(0);
normal.position(0);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, (nSides - 1) * (nRings - 1)
* 4);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glPopMatrix();
}
/*
* 十二面体(线框)
*/
public static void glutWireDodecahedron(GL10 gl) {
/*
* Magic Numbers: It is possible to create a dodecahedron by attaching
* two pentagons to each face of of a cube. The coordinates of the
* points are: (+-x,0, z); (+-1, 1, 1); (0, z, x ) where x = (-1 +
* sqrt(5))/2, z = (1 + sqrt(5))/2 or x = 0.61803398875 and z =
* 1.61803398875.
*/
ByteBuffer bb = ByteBuffer.allocateDirect(12 * 5 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
vertex.put(new float[] { 0.0f, 1.61803398875f, 0.61803398875f, -1.0f,
1.0f, 1.0f, -0.61803398875f, 0.0f, 1.61803398875f,
0.61803398875f, 0.0f, 1.61803398875f, 1.0f, 1.0f, 1.0f,
0.0f, 1.61803398875f, -0.61803398875f, 1.0f, 1.0f, -1.0f,
0.61803398875f, 0.0f, -1.61803398875f, -0.61803398875f, 0.0f,
-1.61803398875f, -1.0f, 1.0f, -1.0f,
0.0f, -1.61803398875f, 0.61803398875f, 1.0f, -1.0f, 1.0f,
0.61803398875f, 0.0f, 1.61803398875f, -0.61803398875f, 0.0f,
1.61803398875f, -1.0f, -1.0f, 1.0f,
0.0f, -1.61803398875f, -0.61803398875f, -1.0f, -1.0f, -1.0f,
-0.61803398875f, 0.0f, -1.61803398875f, 0.61803398875f, 0.0f,
-1.61803398875f, 1.0f, -1.0f, -1.0f,
0.61803398875f, 0.0f, 1.61803398875f, 1.0f, -1.0f, 1.0f,
1.61803398875f, -0.61803398875f, 0.0f, 1.61803398875f,
0.61803398875f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.61803398875f, 0.0f, 1.61803398875f, -1.0f, 1.0f, 1.0f,
-1.61803398875f, 0.61803398875f, 0.0f, -1.61803398875f,
-0.61803398875f, 0.0f, -1.0f, -1.0f, 1.0f,
0.61803398875f, 0.0f, -1.61803398875f, 1.0f, 1.0f, -1.0f,
1.61803398875f, 0.61803398875f, 0.0f, 1.61803398875f,
-0.61803398875f, 0.0f, 1.0f, -1.0f, -1.0f,
-0.61803398875f, 0.0f, -1.61803398875f, -1.0f, -1.0f, -1.0f,
-1.61803398875f, -0.61803398875f, 0.0f, -1.61803398875f,
0.61803398875f, 0.0f, -1.0f, 1.0f, -1.0f,
1.61803398875f, 0.61803398875f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f,
1.61803398875f, -0.61803398875f, 0.0f, 1.61803398875f,
0.61803398875f, 1.0f, 1.0f, 1.0f,
1.61803398875f, -0.61803398875f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f,
-1.61803398875f, 0.61803398875f, 0.0f, -1.61803398875f,
-0.61803398875f, 1.0f, -1.0f, -1.0f,
-1.61803398875f, 0.61803398875f, 0.0f, -1.0f, 1.0f, 1.0f, 0.0f,
1.61803398875f, 0.61803398875f, 0.0f, 1.61803398875f,
-0.61803398875f, -1.0f, 1.0f, -1.0f,
-1.61803398875f, -0.61803398875f, 0.0f, -1.0f, -1.0f, -1.0f,
0.0f, -1.61803398875f, -0.61803398875f, 0.0f, -1.61803398875f,
0.61803398875f, -1.0f, -1.0f, 1.0f
});
vertex.position(0);
bb = ByteBuffer.allocateDirect(12 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
normal.put(new float[] { 0.0f, 0.525731112119f, 0.850650808354f, 0.0f,
0.525731112119f, -0.850650808354f, 0.0f, -0.525731112119f,
0.850650808354f, 0.0f, -0.525731112119f, -0.850650808354f,
0.850650808354f, 0.0f, 0.525731112119f, -0.850650808354f, 0.0f,
0.525731112119f, 0.850650808354f, 0.0f, -0.525731112119f,
-0.850650808354f, 0.0f, -0.525731112119f, 0.525731112119f,
0.850650808354f, 0.0f, 0.525731112119f, -0.850650808354f, 0.0f,
-0.525731112119f, 0.850650808354f, 0.0f, -0.525731112119f,
-0.850650808354f, 0.0f });
normal.position(0);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
for (int i = 0; i < 12; i++)
gl.glDrawArrays(GL10.GL_LINE_LOOP, 5 * i, 5);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
/*
* 十二面体
*/
public static void glutSolidDodecahedron(GL10 gl) {
/*
* Magic Numbers: It is possible to create a dodecahedron by attaching
* two pentagons to each face of of a cube. The coordinates of the
* points are: (+-x,0, z); (+-1, 1, 1); (0, z, x ) where x = (-1 +
* sqrt(5))/2, z = (1 + sqrt(5))/2 or x = 0.61803398875 and z =
* 1.61803398875.
*/
ByteBuffer bb = ByteBuffer.allocateDirect(12 * 5 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
vertex.put(new float[] { 0.0f, 1.61803398875f, 0.61803398875f, -1.0f,
1.0f, 1.0f, -0.61803398875f, 0.0f, 1.61803398875f,
0.61803398875f, 0.0f, 1.61803398875f, 1.0f, 1.0f, 1.0f,
0.0f, 1.61803398875f, -0.61803398875f, 1.0f, 1.0f, -1.0f,
0.61803398875f, 0.0f, -1.61803398875f, -0.61803398875f, 0.0f,
-1.61803398875f, -1.0f, 1.0f, -1.0f,
0.0f, -1.61803398875f, 0.61803398875f, 1.0f, -1.0f, 1.0f,
0.61803398875f, 0.0f, 1.61803398875f, -0.61803398875f, 0.0f,
1.61803398875f, -1.0f, -1.0f, 1.0f,
0.0f, -1.61803398875f, -0.61803398875f, -1.0f, -1.0f, -1.0f,
-0.61803398875f, 0.0f, -1.61803398875f, 0.61803398875f, 0.0f,
-1.61803398875f, 1.0f, -1.0f, -1.0f,
0.61803398875f, 0.0f, 1.61803398875f, 1.0f, -1.0f, 1.0f,
1.61803398875f, -0.61803398875f, 0.0f, 1.61803398875f,
0.61803398875f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.61803398875f, 0.0f, 1.61803398875f, -1.0f, 1.0f, 1.0f,
-1.61803398875f, 0.61803398875f, 0.0f, -1.61803398875f,
-0.61803398875f, 0.0f, -1.0f, -1.0f, 1.0f,
0.61803398875f, 0.0f, -1.61803398875f, 1.0f, 1.0f, -1.0f,
1.61803398875f, 0.61803398875f, 0.0f, 1.61803398875f,
-0.61803398875f, 0.0f, 1.0f, -1.0f, -1.0f,
-0.61803398875f, 0.0f, -1.61803398875f, -1.0f, -1.0f, -1.0f,
-1.61803398875f, -0.61803398875f, 0.0f, -1.61803398875f,
0.61803398875f, 0.0f, -1.0f, 1.0f, -1.0f,
1.61803398875f, 0.61803398875f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f,
1.61803398875f, -0.61803398875f, 0.0f, 1.61803398875f,
0.61803398875f, 1.0f, 1.0f, 1.0f,
1.61803398875f, -0.61803398875f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f,
-1.61803398875f, 0.61803398875f, 0.0f, -1.61803398875f,
-0.61803398875f, 1.0f, -1.0f, -1.0f,
-1.61803398875f, 0.61803398875f, 0.0f, -1.0f, 1.0f, 1.0f, 0.0f,
1.61803398875f, 0.61803398875f, 0.0f, 1.61803398875f,
-0.61803398875f, -1.0f, 1.0f, -1.0f,
-1.61803398875f, -0.61803398875f, 0.0f, -1.0f, -1.0f, -1.0f,
0.0f, -1.61803398875f, -0.61803398875f, 0.0f, -1.61803398875f,
0.61803398875f, -1.0f, -1.0f, 1.0f
});
vertex.position(0);
bb = ByteBuffer.allocateDirect(12 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
normal.put(new float[] { 0.0f, 0.525731112119f, 0.850650808354f, 0.0f,
0.525731112119f, -0.850650808354f, 0.0f, -0.525731112119f,
0.850650808354f, 0.0f, -0.525731112119f, -0.850650808354f,
0.850650808354f, 0.0f, 0.525731112119f, -0.850650808354f, 0.0f,
0.525731112119f, 0.850650808354f, 0.0f, -0.525731112119f,
-0.850650808354f, 0.0f, -0.525731112119f, 0.525731112119f,
0.850650808354f, 0.0f, 0.525731112119f, -0.850650808354f, 0.0f,
-0.525731112119f, 0.850650808354f, 0.0f, -0.525731112119f,
-0.850650808354f, 0.0f });
normal.position(0);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
for (int i = 0; i < 12; i++)
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 5 * i, 5);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
/*
* 八面体(线框)
*/
public static void glutWireOctahedron(GL10 gl) {
float RADIUS = 1.0f;
ByteBuffer bb = ByteBuffer.allocateDirect(8 * 3 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
vertex.put(new float[] { RADIUS, 0.0f, 0.0f, 0.0f, RADIUS, 0.0f, 0.0f,
0.0f, RADIUS,
RADIUS, 0.0f, 0.0f, 0.0f, 0.0f, -RADIUS, 0.0f, RADIUS, 0.0f,
RADIUS, 0.0f, 0.0f, 0.0f, 0.0f, RADIUS, 0.0f, -RADIUS, 0.0f,
RADIUS, 0.0f, 0.0f, 0.0f, -RADIUS, 0.0f, 0.0f, 0.0f, -RADIUS,
-RADIUS, 0.0f, 0.0f, 0.0f, 0.0f, RADIUS, 0.0f, RADIUS, 0.0f,
-RADIUS, 0.0f, 0.0f, 0.0f, RADIUS, 0.0f, 0.0f, 0.0f, -RADIUS,
-RADIUS, 0.0f, 0.0f, 0.0f, -RADIUS, 0.0f, 0.0f, 0.0f, RADIUS,
-RADIUS, 0.0f, 0.0f, 0.0f, 0.0f, -RADIUS, 0.0f, -RADIUS, 0.0f
});
vertex.position(0);
bb = ByteBuffer.allocateDirect(8 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
normal.put(new float[] { 0.577350269189f, 0.577350269189f,
0.577350269189f, 0.577350269189f, 0.577350269189f,
-0.577350269189f, 0.577350269189f, -0.577350269189f,
0.577350269189f, 0.577350269189f, -0.577350269189f,
-0.577350269189f, -0.577350269189f, 0.577350269189f,
0.577350269189f, -0.577350269189f, 0.577350269189f,
-0.577350269189f, -0.577350269189f, -0.577350269189f,
0.577350269189f, -0.577350269189f, -0.577350269189f,
-0.577350269189f });
normal.position(0);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, 24);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
/*
* 八面体
*/
public static void glutSolidOctahedron(GL10 gl) {
float RADIUS = 1.0f;
ByteBuffer bb = ByteBuffer.allocateDirect(8 * 3 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
vertex.put(new float[] { RADIUS, 0.0f, 0.0f, 0.0f, RADIUS, 0.0f, 0.0f,
0.0f, RADIUS,
RADIUS, 0.0f, 0.0f, 0.0f, 0.0f, -RADIUS, 0.0f, RADIUS, 0.0f,
RADIUS, 0.0f, 0.0f, 0.0f, 0.0f, RADIUS, 0.0f, -RADIUS, 0.0f,
RADIUS, 0.0f, 0.0f, 0.0f, -RADIUS, 0.0f, 0.0f, 0.0f, -RADIUS,
-RADIUS, 0.0f, 0.0f, 0.0f, 0.0f, RADIUS, 0.0f, RADIUS, 0.0f,
-RADIUS, 0.0f, 0.0f, 0.0f, RADIUS, 0.0f, 0.0f, 0.0f, -RADIUS,
-RADIUS, 0.0f, 0.0f, 0.0f, -RADIUS, 0.0f, 0.0f, 0.0f, RADIUS,
-RADIUS, 0.0f, 0.0f, 0.0f, 0.0f, -RADIUS, 0.0f, -RADIUS, 0.0f
});
vertex.position(0);
bb = ByteBuffer.allocateDirect(8 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
normal.put(new float[] { 0.577350269189f, 0.577350269189f,
0.577350269189f, 0.577350269189f, 0.577350269189f,
-0.577350269189f, 0.577350269189f, -0.577350269189f,
0.577350269189f, 0.577350269189f, -0.577350269189f,
-0.577350269189f, -0.577350269189f, 0.577350269189f,
0.577350269189f, -0.577350269189f, 0.577350269189f,
-0.577350269189f, -0.577350269189f, -0.577350269189f,
0.577350269189f, -0.577350269189f, -0.577350269189f,
-0.577350269189f });
normal.position(0);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 24);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
/*
* Magic Numbers: r0 = ( 1, 0, 0 ) r1 = ( -1/3, 2 sqrt(2) / 3, 0 ) r2 = (
* -1/3, -sqrt(2) / 3, sqrt(6) / 3 ) r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3
* ) |r0| = |r1| = |r2| = |r3| = 1 Distance between any two points is 2
* sqrt(6) / 3
*
* Normals: The unit normals are simply the negative of the coordinates of
* the point not on the surface.
*/
private static final int NUM_TETR_FACES = 4;
private static float tet_r[][] = { { 1.0f, 0.0f, 0.0f },
{ -0.333333333333f, 0.942809041582f, 0.0f },
{ -0.333333333333f, -0.471404520791f, 0.816496580928f },
{ -0.333333333333f, -0.471404520791f, -0.816496580928f } };
private static int tet_i[][] = /* Vertex indices */
{ { 1, 3, 2 }, { 0, 2, 3 }, { 0, 3, 1 }, { 0, 1, 2 } };
/*
* 四面体(线框)
*/
public static void glutWireTetrahedron(GL10 gl) {
ByteBuffer bb = ByteBuffer.allocateDirect(4 * 3 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
vertex.put(tet_r[1]);
vertex.put(tet_r[3]);
vertex.put(tet_r[2]);
vertex.put(tet_r[0]);
vertex.put(tet_r[2]);
vertex.put(tet_r[3]);
vertex.put(tet_r[0]);
vertex.put(tet_r[3]);
vertex.put(tet_r[1]);
vertex.put(tet_r[0]);
vertex.put(tet_r[1]);
vertex.put(tet_r[2]);
vertex.position(0);
bb = ByteBuffer.allocateDirect(4 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
normal.put(new float[] { -tet_r[0][0], -tet_r[0][1], -tet_r[0][2],
-tet_r[1][0], -tet_r[1][1], -tet_r[1][2], -tet_r[2][0],
-tet_r[2][1], -tet_r[2][2], -tet_r[3][0], -tet_r[3][1],
-tet_r[3][2] });
normal.position(0);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, 12);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
/*
* 四面体
*/
public static void glutSolidTetrahedron(GL10 gl) {
ByteBuffer bb = ByteBuffer.allocateDirect(4 * 3 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
vertex.put(tet_r[1]);
vertex.put(tet_r[3]);
vertex.put(tet_r[2]);
vertex.put(tet_r[0]);
vertex.put(tet_r[2]);
vertex.put(tet_r[3]);
vertex.put(tet_r[0]);
vertex.put(tet_r[3]);
vertex.put(tet_r[1]);
vertex.put(tet_r[0]);
vertex.put(tet_r[1]);
vertex.put(tet_r[2]);
vertex.position(0);
bb = ByteBuffer.allocateDirect(4 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
normal.put(new float[] { -tet_r[0][0], -tet_r[0][1], -tet_r[0][2],
-tet_r[1][0], -tet_r[1][1], -tet_r[1][2], -tet_r[2][0],
-tet_r[2][1], -tet_r[2][2], -tet_r[3][0], -tet_r[3][1],
-tet_r[3][2] });
normal.position(0);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 12);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
private static float icos_r[][] = { { 1.0f, 0.0f, 0.0f },
{ 0.447213595500f, 0.894427191000f, 0.0f },
{ 0.447213595500f, 0.276393202252f, 0.850650808354f },
{ 0.447213595500f, -0.723606797748f, 0.525731112119f },
{ 0.447213595500f, -0.723606797748f, -0.525731112119f },
{ 0.447213595500f, 0.276393202252f, -0.850650808354f },
{ -0.447213595500f, -0.894427191000f, 0.0f },
{ -0.447213595500f, -0.276393202252f, 0.850650808354f },
{ -0.447213595500f, 0.723606797748f, 0.525731112119f },
{ -0.447213595500f, 0.723606797748f, -0.525731112119f },
{ -0.447213595500f, -0.276393202252f, -0.850650808354f },
{ -1.0f, 0.0f, 0.0f } };
private static int icos_v[][] = { { 0, 1, 2 }, { 0, 2, 3 }, { 0, 3, 4 },
{ 0, 4, 5 }, { 0, 5, 1 }, { 1, 8, 2 }, { 2, 7, 3 }, { 3, 6, 4 },
{ 4, 10, 5 }, { 5, 9, 1 }, { 1, 9, 8 }, { 2, 8, 7 }, { 3, 7, 6 },
{ 4, 6, 10 }, { 5, 10, 9 }, { 11, 9, 10 }, { 11, 8, 9 },
{ 11, 7, 8 }, { 11, 6, 7 }, { 11, 10, 6 } };
/*
* 二十面体(线框)
*/
public static void glutWireIcosahedron(GL10 gl) {
ByteBuffer bb = ByteBuffer.allocateDirect(20 * 3 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
bb = ByteBuffer.allocateDirect(20 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
for (int i = 0; i < 20; i++) {
normal.put((icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1])
* (icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2])
- (icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2])
* (icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1]));
normal.put((icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2])
* (icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0])
- (icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0])
* (icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2]));
normal.put((icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0])
* (icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1])
- (icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1])
* (icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0]));
vertex.put(icos_r[icos_v[i][0]]);
vertex.put(icos_r[icos_v[i][1]]);
vertex.put(icos_r[icos_v[i][2]]);
}
vertex.position(0);
normal.position(0);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
for (int i = 0; i < 20; i++)
gl.glDrawArrays(GL10.GL_LINE_LOOP, 3 * i, 3);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
/*
* 二十面体
*/
public static void glutSolidIcosahedron(GL10 gl) {
ByteBuffer bb = ByteBuffer.allocateDirect(20 * 3 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
bb = ByteBuffer.allocateDirect(20 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
for (int i = 0; i < 20; i++) {
normal.put((icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1])
* (icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2])
- (icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2])
* (icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1]));
normal.put((icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2])
* (icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0])
- (icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0])
* (icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2]));
normal.put((icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0])
* (icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1])
- (icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1])
* (icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0]));
vertex.put(icos_r[icos_v[i][0]]);
vertex.put(icos_r[icos_v[i][1]]);
vertex.put(icos_r[icos_v[i][2]]);
}
vertex.position(0);
normal.position(0);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
for (int i = 0; i < 20; i++)
gl.glDrawArrays(GL10.GL_TRIANGLES, 3 * i, 3);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
private static float rdod_r[][] = { { 0.0f, 0.0f, 1.0f },
{ 0.707106781187f, 0.000000000000f, 0.5f },
{ 0.000000000000f, 0.707106781187f, 0.5f },
{ -0.707106781187f, 0.000000000000f, 0.5f },
{ 0.000000000000f, -0.707106781187f, 0.5f },
{ 0.707106781187f, 0.707106781187f, 0.0f },
{ -0.707106781187f, 0.707106781187f, 0.0f },
{ -0.707106781187f, -0.707106781187f, 0.0f },
{ 0.707106781187f, -0.707106781187f, 0.0f },
{ 0.707106781187f, 0.000000000000f, -0.5f },
{ 0.000000000000f, 0.707106781187f, -0.5f },
{ -0.707106781187f, 0.000000000000f, -0.5f },
{ 0.000000000000f, -0.707106781187f, -0.5f }, { 0.0f, 0.0f, -1.0f } };
private static int rdod_v[][] = { { 0, 1, 5, 2 }, { 0, 2, 6, 3 },
{ 0, 3, 7, 4 }, { 0, 4, 8, 1 }, { 5, 10, 6, 2 }, { 6, 11, 7, 3 },
{ 7, 12, 8, 4 }, { 8, 9, 5, 1 }, { 5, 9, 13, 10 },
{ 6, 10, 13, 11 }, { 7, 11, 13, 12 }, { 8, 12, 13, 9 } };
private static float rdod_n[][] = {
{ 0.353553390594f, 0.353553390594f, 0.5f },
{ -0.353553390594f, 0.353553390594f, 0.5f },
{ -0.353553390594f, -0.353553390594f, 0.5f },
{ 0.353553390594f, -0.353553390594f, 0.5f },
{ 0.000000000000f, 1.000000000000f, 0.0f },
{ -1.000000000000f, 0.000000000000f, 0.0f },
{ 0.000000000000f, -1.000000000000f, 0.0f },
{ 1.000000000000f, 0.000000000000f, 0.0f },
{ 0.353553390594f, 0.353553390594f, -0.5f },
{ -0.353553390594f, 0.353553390594f, -0.5f },
{ -0.353553390594f, -0.353553390594f, -0.5f },
{ 0.353553390594f, -0.353553390594f, -0.5f } };
/*
* 菱形十二面体(线框)
*/
public static void glutWireRhombicDodecahedron(GL10 gl) {
ByteBuffer bb = ByteBuffer.allocateDirect(12 * 4 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
bb = ByteBuffer.allocateDirect(12 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
for (int i = 0; i < 12; i++) {
normal.put(rdod_n[i]);
vertex.put(rdod_r[rdod_v[i][0]]);
vertex.put(rdod_r[rdod_v[i][1]]);
vertex.put(rdod_r[rdod_v[i][2]]);
vertex.put(rdod_r[rdod_v[i][3]]);
}
vertex.position(0);
normal.position(0);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
for (int i = 0; i < 12; i++)
gl.glDrawArrays(GL10.GL_LINE_LOOP, 4 * i, 4);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
/*
* 菱形十二面体
*/
public static void glutSolidRhombicDodecahedron(GL10 gl) {
ByteBuffer bb = ByteBuffer.allocateDirect(12 * 4 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer vertex = bb.asFloatBuffer();
vertex.position(0);
bb = ByteBuffer.allocateDirect(12 * 3 * 4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer normal = bb.asFloatBuffer();
normal.position(0);
for (int i = 0; i < 12; i++) {
normal.put(rdod_n[i]);
vertex.put(rdod_r[rdod_v[i][0]]);
vertex.put(rdod_r[rdod_v[i][1]]);
vertex.put(rdod_r[rdod_v[i][2]]);
vertex.put(rdod_r[rdod_v[i][3]]);
}
vertex.position(0);
normal.position(0);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normal);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex);
for (int i = 0; i < 12; i++)
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 4 * i, 4);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
}
使用的例子如下:
package fyj.engine.renderers;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLU;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import fyj.engine.utils.FreeGLUT;
public class FreeglutTestRenderer implements CommonRenderer {
private float rot = 0;
public FreeglutTestRenderer(Context ctx) {
}
@Override
public void draw(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, -0.2f);
gl.glRotatef(rot, 0, 1, 0);
rot += 0.5f;
// Log.i("37", " rot = " + rot);
// Freeglut.glutSolidCube(gl, 1);
// Freeglut.glutWireSphere(gl, 1, 35, 45);
// FreeGLUT.glutWireTorus(gl, 0.5f, 1, 35, 30);
// Freeglut.glutSolidTorus(gl, 0.5f, 1, 20, 60);
// FreeGLUT.glutWireDodecahedron(gl);
// FreeGLUT.glutSolidDodecahedron(gl);
// FreeGLUT.glutWireOctahedron(gl);
// FreeGLUT.glutSolidOctahedron(gl);
// FreeGLUT.glutWireTetrahedron(gl);
// FreeGLUT.glutWireIcosahedron(gl);
// FreeGLUT.glutSolidIcosahedron(gl);
// FreeGLUT.glutWireRhombicDodecahedron(gl);
// FreeGLUT.glutSolidRhombicDodecahedron(gl);
// FreeGLUT.glutWireCone(gl, 1.0f, 5.0f, 35, 30);
// FreeGLUT.glutSolidCone(gl, 1.0f, 5.0f, 35, 30);
// FreeGLUT.glutWireCylinder(gl, 1.0f, 5, 35, 30);
FreeGLUT.glutSolidCylinder(gl, 1.0f, 5, 36, 30);
}
@Override
public void resize(GL10 gl, int w, int h) {
// TODO Auto-generated method stub
float fAspect;
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0)
h = 1;
gl.glViewport(0, 0, w, h);
fAspect = (float)w / (float)h;
// Reset the coordinate system before modifying
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
// Set the clipping volume
GLU.gluPerspective(gl, 45.0f, fAspect, 1.0f, 50.0f);
GLU.gluLookAt(gl, 0, 0, -5, 0, 0, 0, 0, 1, 0);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void init(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
gl.glClearColor(0.0f, 0.0f, .50f, 1.0f );
gl.glEnable(GL10.GL_DEPTH_TEST); // Hidden surface removal
// gl.glFrontFace(GL10.GL_CCW); // Counter clock-wise polygons face out
//
// gl.glEnable(GL10.GL_CULL_FACE); // Do not calculate inside of jet
}
@Override
public boolean keyEvent(KeyEvent event) {
// TODO Auto-generated method stub
return false;
}
@Override
public void createMenu(Menu menu) {
// TODO Auto-generated method stub
}
@Override
public void onMenuItemSelected(MenuItem item) {
// TODO Auto-generated method stub
}
}