// Author : Josh Grant
// Course : CIS5900, Computer Graphics, Fall 2000
// Assignment : hw05
// Date : October 10th, 2000
// Description : This program samples random directions around a 3D viewpoint
// (vx, vy, vz) supplied by the command line. The scene is
// written out in Inventor format. The final scene has several
// spheres sampled on the viewing sphere which coincide with
// spheres on the user sphere. The spheres match up because
// they because when the viewing sphere casts a ray it
// intersects at the point marked on the user sphere. The
// below arguments can be optionally changed when exectued at the
// command line...
// vxcenter - x center coordinate of viewing sphere
// vycenter - y center coordinate of viewing sphere
// vzcenter - z center coordinate of viewing sphere
// uxcenter - x center coordinate of user sphere
// uxcenter - y center coordinate of user sphere
// uxcenter - z center coordinate of user sphere
// vradius - radius of the viewing sphere
// uradius - radius of the user sphere
// samples - number of samples to attempt.
// 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 vxcenter = -0.75, vycenter = -0.75, vzcenter = -0.75;
double uxcenter = 0.75, uycenter = 0.75, uzcenter = 0.75;
double vradius = 0.25, uradius = 0.75;
double lradius = 0.05;
int samples = 5000;
int main(int argc, char **argv) {
int i, intersects;
double x = 0.0, y = 0.0, z = 0.0;
Sphere *view, *user, *little;
Vector *dp, *vcenter, *ucenter, q0, q1;
double lcolor[3], vcolor[3];
lcolor[0] = 0.0; lcolor[1] = 0.0, lcolor[2] = 1.0;
vcolor[0] = 1.0; vcolor[1] = 0.0, vcolor[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]);
// Set up some Vectors for the center of the viewing point and the user
// sphere.
vcenter = new Vector(vxcenter, vycenter, vzcenter);
ucenter = new Vector(uxcenter, uycenter, uzcenter);
*ucenter = *ucenter - *vcenter;
// Write Inventor Header info
writeInventorHeader();
// Write the viewing sphere
view = new Sphere(vradius, *vcenter);
view->writeInventor();
// Write the user sphere
user = new Sphere(uradius, *ucenter);
user->writeInventor();
// Set up the object for all the sampled spheres
little = new Sphere();
little->radius = lradius;
little->diffuse = lcolor;
srand48(getpid());
for (i = 0; i < samples; i++) {
if (pointOnSphere(x, y, z)) {
//Create Vector for the point on the viewing sphere
dp = new Vector(x*vradius, y*vradius, z*vradius);
// Does the ray cast from the center of the viewing sphere, to the
// point dp and beyond, intersect any point on the user sphere?
intersects = view->intersect(*dp, *ucenter, uradius, q0);
if (intersects == 1) {
*(little->center) = *dp + *vcenter;
little->diffuse = vcolor;
little->radius = lradius * 0.5;
little->writeInventor();
little->diffuse = lcolor;
little->radius = lradius;
*(little->center) = q0;
little->writeInventor();
}
delete dp;
}
}
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], "uxview"))
uxcenter = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "uyview"))
uycenter = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "uzview"))
uzcenter = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "uradius"))
uradius = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "samples"))
samples = atoi(myargv[i + 1]);
else if (!strcmp(myargv[i], "vxview"))
vxcenter = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "vyview"))
vycenter = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "vzview"))
vzcenter = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "vradius"))
vradius = atof(myargv[i + 1]);
else if (!strcmp(myargv[i], "-help"))
return 0;
}
return 1;
}
void printUsage(char *progname) {
cout << "Usage - " << endl;
cout << " " << progname << " [vxcenter <num>] [vycenter <num>] " << endl;
cout << " [vzcenter <num>] [uxcenter <num>] [uycenter <num>] "<< endl;
cout << " [vucenter <num>] [vradius <num>] [uradius <num>] " << endl;
cout << " [samples <num>] " << endl;
cout << " " << progname << " -help" << endl;
exit(1);
}
void writeInventorHeader() {
cout << "#Inventor V2.1 ascii" << endl;
cout << endl;
cout << "Complexity {" << endl;
cout << " value 0.3" << endl;
cout << "}" << endl;
cout << endl;
}