// Author : Josh Grant
// Course : CIS5900, Computer Graphics, Fall 2000
// Assignment : hw05
// Date : October 10th, 2000
// Description : This program randomly samples points on a sphere and outputs
// the scene in Inventor format. The class Sphere is called
// and used to handle the inventor writes. The center of the
// sphere, its radius, the number of samples and the radius of
// the samples can all be initilized with the command line.
// However, it is not necessary to run the program. A default
// value is given to each parameter if not stated on the
// command line. A -help option is also available to print
// the usage of the program.
#include <iostream.h>
#include <stdlib.h>
#include <unistd.h>
#include <sphere.h>
#include <vector.h>
int pointOnSphere(double &x, double &y, double &z);
int checkArgs(int myargc, char **myargv);
void printUsage(char *progname);
void writeInventorHeader();
// I know globals are bad, but this was a quick way to clean up the mess
// caused by parsing through the command line. Now the function is at the
// bottom of the page instead of right up top.
double xcenter = 0.0, ycenter = 0.0, zcenter = 0.0;
double radius = 0.75;
double sradius = 0.1;
int samples = 10;
int main(int argc, char **argv) {
int i;
double x = 0.0, y = 0.0, z = 0.0;
Sphere *sphere;
Vector *center, *samp;
double scolor[3];
scolor[0] = 0.0, scolor[1] = 1.0, scolor[2] = 0.0;
// if one of the command line arguments was not recognized, then we print
// the usage and quit.
if (!checkArgs(argc, argv))
printUsage(argv[0]);
// write inventor header info.
writeInventorHeader();
// Create a Vector for the center of the sphere and then create a new
// Sphere object.
center = new Vector(xcenter, ycenter, zcenter);
sphere = new Sphere(radius, *center);
sphere->writeInventor();
// Since sphere has already been written to stdout, we can now modify the
// object for different spheres.
sphere->radius = sradius;
sphere->diffuse = scolor;
srand48(getpid());
for (i = 0; i < samples; i++) {
if (pointOnSphere(x, y, z)) {
// Vector which holds the point to be sampled on the sphere.
samp = new Vector(xcenter + x*radius, ycenter + y*radius,
zcenter + z*radius);
*(sphere->center) = *samp;
sphere->writeInventor();
delete samp;
}
}
return 0;
}
// Function first looks for a point within the unit sphere by randomly
// picking a value for x, y, z and then scaling it between -1 and 1. If one
// is found then it is normalized.
int pointOnSphere(double &x, double &y, double &z) {
float length;
int maxAttempts = 10;
do {
x = 2.0 * (drand48() - 0.5);
y = 2.0 * (drand48() - 0.5);
z = 2.0 * (drand48() - 0.5);
length = sqrt(x*x + y*y + z*z);
} while ( ((length > 1.0) || (length == 0.0)) && (--maxAttempts) );
if ( (length <= 1.0) && (length > 0.0) ) { // Normalize.
x /= length;
y /= length;
z /= length;
} else { // throw exception
return 0;
}
return 1;
}
// checkArgs() checks the command line arguments and assigns all variables
// not listed on command to zero.
int checkArgs(int myargc, char **myargv) {
for (int i = 1; i < myargc; i += 2) {
if (!strcmp(myargv[i], "xcenter"))
xcenter = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "ycenter"))
ycenter = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "zcenter"))
zcenter = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "radius"))
radius = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "samples"))
samples = atoi(myargv[i + 1]);
else if (!strcmp(myargv[i], "sradius"))
sradius = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "-help"))
return 0;
}
return 1;
}
void printUsage(char *progname) {
cout << "Usage -" << endl;
cout << " " << progname << " [xcenter <num>] [ycenter <num>] [zcenter <num>]"
<< endl << " [radius <num>] [samples <num>] [sradius <num>]";
cout << "\nThis message:\n " << progname << " -help" << endl;
exit(1);
}
void writeInventorHeader() {
cout << "#Inventor V2.1 ascii" << endl;
cout << endl;
cout << "Complexity {" << endl;
cout << " value 0.5" << endl;
cout << "}" << endl;
cout << endl;
}