import go.*; public class GoSphere { double radius; int slices; int stacks; GoTriangleFan topSolid; GoTriangleFan botSolid; GoTriangleStrip[] midSolid; GoLineStrip[] sliceWire; GoLineLoop[] stackWire; boolean solidDirty; boolean wireDirty; public GoSphere(double radius, int slices, int stacks) { this.radius = radius; this.slices = slices; this.stacks = stacks; solidDirty = true; wireDirty = true; } void renderSolid(Go go) { int i; if(solidDirty) updateSolid(); go.push(Go.FLAGS); go.enable(Go.CULL); go.render(topSolid); for(i = 0; i < stacks - 2; i++) { go.render(midSolid[i]); } go.render(botSolid); go.pop(Go.FLAGS); } void renderWire(Go go) { int i; if(wireDirty) updateWire(); for(i = 0; i < stacks - 1; i++) { go.render(stackWire[i]); } for(i = 0; i < slices; i++) { go.render(sliceWire[i]); } } void updateSolid() { double[] p0 = new double[3]; double[] p1 = new double[3]; int i, j; double stackAngle; double stackAngleInc = Math.PI / stacks; double sliceAngle; double sliceAngleInc = Math.PI / slices; double sliceRadius1; double sliceRadius2; // // Create the top triangle fan. // sliceAngle = 0.0; stackAngle = stackAngleInc; sliceRadius2 = radius * Math.sin(stackAngle); topSolid = new GoTriangleFan(slices + 2, Go.NORMAL); topSolid.xyz(0, 0, 0, radius); topSolid.ijk(0, 0, 0, radius); sliceAngle = Math.PI; for(j = 0; j <= slices; j++) { p0[0] = sliceRadius2 * Math.sin(sliceAngle); p0[1] = sliceRadius2 * Math.cos(sliceAngle); p0[2] = radius * Math.cos(stackAngle); topSolid.xyz(j + 1, p0[0], p0[1], p0[2]); topSolid.ijk(j + 1, p0[0], p0[1], p0[2]); sliceAngle -= sliceAngleInc * 2.0; } // // Create the middle triangle strips. // midSolid = new GoTriangleStrip[stacks - 2]; double stackAngle1; double stackAngle2 = stackAngle; for(i = 1; i < stacks - 1; i++) { stackAngle1 = stackAngle2; stackAngle2 += stackAngleInc; sliceRadius1 = sliceRadius2; sliceRadius2 = radius * Math.sin(stackAngle2); midSolid[i - 1] = new GoTriangleStrip(slices * 2 + 2, Go.NORMAL); sliceAngle = Math.PI; p0[0] = sliceRadius2 * Math.sin(sliceAngle); p0[1] = sliceRadius2 * Math.cos(sliceAngle); p0[2] = radius * Math.cos(stackAngle2); p1[0] = sliceRadius1 * Math.sin(sliceAngle); p1[1] = sliceRadius1 * Math.cos(sliceAngle); p1[2] = radius * Math.cos(stackAngle1); midSolid[i - 1].xyz(0, p0[0], p0[1], p0[2]); midSolid[i - 1].ijk(0, p0[0], p0[1], p0[2]); midSolid[i - 1].xyz(1, p1[0], p1[1], p1[2]); midSolid[i - 1].ijk(1, p1[0], p1[1], p1[2]); for(j = 0; j < slices; j++) { sliceAngle += sliceAngleInc * 2.0; p0[0] = sliceRadius1 * Math.sin(sliceAngle); p0[1] = sliceRadius1 * Math.cos(sliceAngle); p0[2] = radius * Math.cos(stackAngle1); p1[0] = sliceRadius2 * Math.sin(sliceAngle); p1[1] = sliceRadius2 * Math.cos(sliceAngle); p1[2] = radius * Math.cos(stackAngle2); midSolid[i - 1].xyz(j*2+2, p1[0], p1[1], p1[2]); midSolid[i - 1].ijk(j*2+2, p1[0], p1[1], p1[2]); midSolid[i - 1].xyz(j*2+3, p0[0], p0[1], p0[2]); midSolid[i - 1].ijk(j*2+3, p0[0], p0[1], p0[2]); } stackAngle += stackAngleInc * 2.0; } // // Create the bottom triangle fan. // sliceAngle = Math.PI; stackAngle = Math.PI - stackAngleInc; sliceRadius1 = radius * Math.sin(stackAngle); botSolid = new GoTriangleFan(slices + 2, Go.NORMAL); botSolid.xyz(0, 0, 0, -radius); botSolid.ijk(0, 0, 0, -radius); for(j = 0; j <= slices; j++) { p0[0] = sliceRadius1 * Math.sin(sliceAngle); p0[1] = sliceRadius1 * Math.cos(sliceAngle); p0[2] = radius * Math.cos(stackAngle); botSolid.xyz(j + 1, p0[0], p0[1], p0[2]); botSolid.ijk(j + 1, p0[0], p0[1], p0[2]); sliceAngle += sliceAngleInc * 2.0; } solidDirty = false; } void updateWire() { double[] p = new double[3]; int i, j; double stackAngle; double stackAngleInc = Math.PI / stacks; double sliceAngle; double sliceAngleInc = Math.PI / slices; double sliceRadius; // // Create the stacks. // stackWire = new GoLineLoop[stacks - 1]; stackAngle = stackAngleInc; for(i = 0; i < stacks - 1; i++) { sliceAngle = 0.0; sliceRadius = radius * Math.sin(stackAngle); stackWire[i] = new GoLineLoop(slices, Go.NORMAL); for(j = 0; j < slices; j++) { p[0] = sliceRadius * Math.sin(sliceAngle); p[1] = sliceRadius * Math.cos(sliceAngle); p[2] = radius * Math.cos(stackAngle); stackWire[i].xyz(j, p[0], p[1], p[2]); stackWire[i].ijk(j, p[0], p[1], p[2]); sliceAngle -= sliceAngleInc * 2.0; } stackAngle += stackAngleInc; } // // Create the slices. // sliceWire = new GoLineStrip [slices]; sliceAngle = 0.0; for(i = 0; i < slices; i++) { stackAngle = 0.0; sliceRadius = radius * Math.sin(stackAngle); sliceWire[i] = new GoLineStrip(stacks + 1, Go.NORMAL); for(j = 0; j < stacks + 1; j++) { p[0] = sliceRadius * Math.sin(sliceAngle); p[1] = sliceRadius * Math.cos(sliceAngle); p[2] = radius * Math.cos(stackAngle); sliceWire[i].xyz(j, p[0], p[1], p[2]); sliceWire[i].ijk(j, p[0], p[1], p[2]); stackAngle -= stackAngleInc; sliceRadius = radius * Math.sin(stackAngle); } sliceAngle += sliceAngleInc * 2.0; } wireDirty = false; } }