// Author : Josh Grant
// Course : CIS5900, Computer Graphics, Fall 2000
// Assignment : hw10
// Date : November 14th, 2000
// Description : This program randomly casts rays out from a view point and
// checks for an intersection between x number of spheres
// within a 3D scene.
#include <stdio.h>
#include <iostream.h>
#include <Sphere.h>
#include <ViewPoint.h>
#define RAYFILE "raycast.1"
int checkArgs (int myargc, char **myargv);
void printUsage (char *progname);
void writeRayFile (FILE *fptr, Vector center, Vector color);
void writeInventor(Vector center, Vector color, double radius);
// 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.0, vycenter = 0.0, vzcenter = 5.0;
int samples = 5000, sphere_num = 1;
int main(int argc, char **argv) {
int i, j, intersects, *obj_index, hold;
Sphere *objects;
ViewPoint *view;
Vector s_center, s_color, out_color, ray, q0, q1, normal, vcenter;
double s_radius = 0.0, x, y, z, r, g, b, vlength;
FILE *fptr;
// 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 = Vector(vxcenter, vycenter, vzcenter);
//vcenter.normalize();
view = new ViewPoint(vcenter, 0.1);
objects = new Sphere[sphere_num];
obj_index = new int[sphere_num];
cout << "#Inventor V2.1 ascii" << endl;
cout << endl;
cout << "Complexity {" << endl;
cout << " value 1.0" << endl;
cout << "}" << endl;
cout << endl;
writeInventor(vcenter, Vector(0.5, 0.5, 0.5), 0.1);
srand48(getpid());
for (i = 0; i < sphere_num; i++) {
obj_index[i] = i;
x = 2.0 * (drand48() - 0.5);
y = 2.0 * (drand48() - 0.5);
z = 2.0 * (drand48() - 0.5);
s_center = Vector(x, y, z);
s_radius = 0.2;
r = drand48();
g = drand48();
b = drand48();
s_color = Vector(r, g, b);
objects[i] = Sphere(s_radius, s_center, s_color);
writeInventor(s_center, s_color, s_radius);
}
for (i = sphere_num - 1; i >= 0; i--) {
for (j = 0; j < i; j++) {
if (objects[obj_index[j]].getCenter().length() >
objects[obj_index[j]].getCenter().length()) {
hold = obj_index[j];
obj_index[j] = obj_index[j+1];
obj_index[j+1] = hold;
}
}
}
fptr = fopen(RAYFILE, "w");
fprintf(fptr, "# RayCast File, First line is view point\n");
fprintf(fptr, "# x y z r g b\n");
fprintf(fptr, "%8.4f %8.4f %8.4f\n", vxcenter, vycenter, vzcenter);
cout << "Complexity {" << endl;
cout << " value 0.2" << endl;
cout << "}" << endl;
for (i = 0; i < samples; i++) {
if (view->castRay(ray)) {
//cout << ray << endl;
for (j = 0; j < sphere_num; j++) {
intersects = view->intersect(ray, objects[obj_index[j]], q0, q1);
if (intersects == 1) {
ray.normalize();
normal = q0 - objects[obj_index[j]].getCenter();
normal.normalize();
out_color = dot(normal, -ray) * objects[obj_index[j]].getColor();
writeRayFile(fptr, q0, out_color);
writeInventor(q0, out_color, 0.05);
break;
}
}
}
}
fclose(fptr);
return 0;
}
void writeRayFile (FILE *fptr, Vector center, Vector color) {
fprintf(fptr, "%8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n",
center.x(), center.y(), center.z(),
color.x(), color.y(), color.z());
}
void writeInventor (Vector center, Vector color, double radius) {
cout << "Separator {" << endl;
cout << " Material {" << endl;
cout << " emissiveColor "
<< color.x() << " "
<< color.y() << " "
<< color.z() << endl;
cout << " }" << endl;
cout << " Transform {" << endl;
cout << " translation ";
cout << center.x() << " " << center.y() << " " << center.z();
cout << endl;
cout << " }" << endl;
cout << " Sphere {" << endl;
cout << " radius " << radius << endl;
cout << " }" << endl;
cout << "}" << endl << endl;
}
// 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], "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], "spheres"))
sphere_num = atoi(myargv[i + 1]);
else if (!strcmp(myargv[i], "samples"))
samples = atoi(myargv[i + 1]);
else if (!strcmp(myargv[i], "-help"))
return 0;
}
return 1;
}
void printUsage(char *progname) {
cout << "Usage - " << endl;
exit(1);
}