#include <math.h> #include "GoSphere.h" #define PI 3.14159265358979324 GoSphere::GoSphere(double radius, int slices, int stacks) { this->radius = radius; this->slices = slices; this->stacks = stacks; solidDirty = true; wireDirty = true; } void GoSphere::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 GoSphere::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 GoSphere::updateSolid(void) { double p0[3]; double p1[3]; int i, j; double stackAngle; double stackAngleInc = PI / stacks; double sliceAngle; double sliceAngleInc = PI / slices; double sliceRadius1; double sliceRadius2; // // Create the top triangle fan. // sliceAngle = 0.0; stackAngle = stackAngleInc; sliceRadius2 = radius * sin(stackAngle); topSolid = new GoTriangleFan(slices + 2, Go::NORMAL); topSolid->xyz(0, 0, 0, radius); topSolid->ijk(0, 0, 0, radius); sliceAngle = PI; for(j = 0; j <= slices; j++) { p0[0] = sliceRadius2 * sin(sliceAngle); p0[1] = sliceRadius2 * cos(sliceAngle); p0[2] = radius * 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 * sin(stackAngle2); midSolid[i - 1] = new GoTriangleStrip(slices * 2 + 2, Go::NORMAL); sliceAngle = PI; p0[0] = sliceRadius2 * sin(sliceAngle); p0[1] = sliceRadius2 * cos(sliceAngle); p0[2] = radius * cos(stackAngle2); p1[0] = sliceRadius1 * sin(sliceAngle); p1[1] = sliceRadius1 * cos(sliceAngle); p1[2] = radius * 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 * sin(sliceAngle); p0[1] = sliceRadius1 * cos(sliceAngle); p0[2] = radius * cos(stackAngle1); p1[0] = sliceRadius2 * sin(sliceAngle); p1[1] = sliceRadius2 * cos(sliceAngle); p1[2] = radius * 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 = PI; stackAngle = PI - stackAngleInc; sliceRadius1 = radius * 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 * sin(sliceAngle); p0[1] = sliceRadius1 * cos(sliceAngle); p0[2] = radius * 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 GoSphere::updateWire(void) { double p[3]; int i, j; double stackAngle; double stackAngleInc = PI / stacks; double sliceAngle; double sliceAngleInc = 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 * sin(stackAngle); stackWire[i] = new GoLineLoop(slices, Go::NORMAL); for(j = 0; j < slices; j++) { p[0] = sliceRadius * sin(sliceAngle); p[1] = sliceRadius * cos(sliceAngle); p[2] = radius * 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 * sin(stackAngle); sliceWire[i] = new GoLineStrip(stacks + 1, Go::NORMAL); for(j = 0; j < stacks + 1; j++) { p[0] = sliceRadius * sin(sliceAngle); p[1] = sliceRadius * cos(sliceAngle); p[2] = radius * 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 * sin(stackAngle); } sliceAngle += sliceAngleInc * 2.0; } wireDirty = false; }