#include #include #include #include #include "defs.h" #include "functions.h" using namespace std; void printObject(Vector v) { cerr << v.x << " " << v.y << " " << v.z << endl; } void printObject(int i) { cerr << i << endl; } void printObject(double f) { cerr << f << endl; } void printObject(Light l) { cerr << l.center.x << " " << l.center.y << " " << l.center.z << " I: " << l.intensity << endl; } void printObject(MaterialAttributes attrib) { cerr << " k_dr, k_dg, k_db " << attrib.k_dr << " " << attrib.k_dg << " " << attrib.k_db << " " << attrib.k_ar << " " << attrib.k_ag << " " << attrib.k_ab << " " << attrib.k_s << " " << attrib.n_spec << endl; } void scanInput(MaterialAttributes &attrib, char* input) { char *pEnd; cin.getline(input,81); attrib.k_dr = strtod(input,&pEnd); attrib.k_dg = strtod(pEnd,&pEnd); attrib.k_db = strtod(pEnd,&pEnd); attrib.k_ar = strtod(pEnd,&pEnd); attrib.k_ag = strtod(pEnd,&pEnd); attrib.k_ab = strtod(pEnd,&pEnd); attrib.k_s = strtod(pEnd,&pEnd); attrib.n_spec = strtod(pEnd,NULL); } void scanInput(vector &primitives, int numPrimitives, char* input) { int i; char *pEnd; for (i = 0; i < numPrimitives; i++) { cin.getline(input,81); switch (input[0]) { case 'S': { Sphere* sphere = new Sphere(); cin.getline(input,81); sphere->center.x = strtod(input, &pEnd); sphere->center.y = strtod(pEnd, &pEnd); sphere->center.z = strtod(pEnd, &pEnd); sphere->radius = strtod(pEnd,NULL); scanInput(sphere->attrib, input); primitives.push_back(sphere); //printObject(sphere->attrib); #ifdef bDebug cout << "Got Sphere.." << endl; printObject(sphere->center); printObject(sphere->radius); printObject(sphere->attrib); #endif break; } case 'T': { Triangle* triangle = new Triangle(); scanInput(triangle->a1,input); scanInput(triangle->a2,input); scanInput(triangle->a3,input); scanInput(triangle->attrib, input); primitives.push_back(triangle); #ifdef bDebug cout << "Got Triangle.." << endl; printObject(triangle->a1); printObject(triangle->a2); printObject(triangle->a3); printObject(triangle->attrib); #endif break; } default: cout << "Error bad\n"; break; }; } } void scanInput(Vector &v, char* input) { char* pEnd; cin.getline(input, 81); v.x = strtod(input,&pEnd); v.y = strtod(pEnd,&pEnd); v.z = strtod(pEnd,NULL); } void scanInput(Light &light, char* input) { char* pEnd; cin.getline(input,81); light.center.x = strtod(input, &pEnd); light.center.y = strtod(pEnd, &pEnd); light.center.z = strtod(pEnd, &pEnd); light.intensity = strtod(pEnd, NULL); } /* Useful operator overloads */ /* ------------- -------------*/ Vector Vector::operator+(Vector &other) { Vector v; v.x = x + other.x; v.y = y + other.y; v.z = z + other.z; return v; } Vector Vector::operator-(Vector &other) { Vector v; v.x = x - other.x; v.y = y - other.y; v.z = z - other.z; return v; } Vector Vector::operator*(Vector &other) { Vector v; v.x = x * other.x; v.y = y * other.y; v.z = z * other.z; return v; } Vector Vector::operator/(Vector &other) { Vector v; v.x = x / other.x; v.y = y / other.y; v.z = z / other.z; return v; } Vector Vector::operator*(int &other) { Vector v; v.x = x * other; v.y = y * other; v.z = z * other; return v; } Vector Vector::operator*(double &other) { Vector v; v.x = x * other; v.y = y * other; v.z = z * other; return v; } /* ------------ ----------- */ /* ------------ ----------- */ ostream &operator<< ( ostream &ofs, struct MaterialAttributes m ) { ofs << " Material Attributes: " << endl; ofs << " k_dr: " << m.k_dr << " k_dg: " << m.k_dg << " k_db: " << m.k_db << endl; ofs << " k_ar: " << m.k_ar << " k_ag: " << m.k_ag << " k_ab: " << m.k_ab << endl; ofs << " k_s: " << m.k_s << " n_spec: " << m.n_spec << endl; return ofs; } ostream &operator<< ( ostream &ofs, Sphere s ) { ofs << "Sphere: " << endl; ofs << " Center: " << "(" << s.center.x << "," << s.center.y << "," << s.center.z << endl; return ofs; } ostream &operator<< ( ostream &ofs, Triangle t ) { ofs << "Triangle: " << endl; return ofs; } /* ------------ ------------- */ /* ----------- Primitive stuff ----------- */ double length(Vector p) { double toRet; toRet = pow(p.x,2)+pow(p.y,2)+pow(p.z,2); toRet = sqrt(toRet); return toRet; } double dot(Vector v1, Vector v2) { double toRet; toRet = (v1.x*v2.x) + (v1.y*v2.y) + (v1.z*v2.z); return toRet; } inline double discriminant(double A, double B, double C) { return ((B*B) - (4*A*C)); } void Sphere::printName() { cout << "This is of type Sphere" << endl; } bool Sphere::intersectsWithSelf(Point p, Light l, Point v) { Vector cp, pl; cp = p - this->center; pl = l.center - p; if (dot(cp,pl) < 0) { return true; } else return false; } double Sphere::intersectsWith(Ray ray) { double C = pow(length(ray.origin - this->center),2) - pow(this->radius,2); double B; double A; double discrim; A = pow(length(ray.direction),2); B = 2*dot(ray.direction,ray.origin - this->center); discrim = discriminant(A,B,C); if (discrim < 0) { return -1; } else if (discrim > 0) { double a, b; a = ((-1*B)+sqrt(discrim))/(2*A); b = ((-1*B)-sqrt(discrim))/(2*A); if (b>=0) return b; else return a; } else { //discrim==0 return ((-1*B) / (2*A)); } } void Triangle::printName() { cout << "This is of type Triangle" << endl; } inline Vector cross(Vector a, Vector b) { Vector toRet; toRet.x = ( (a.y*b.z) - (a.z*b.y) ); //i toRet.y = ( (a.z*b.x) - (a.x*b.z) ); //j toRet.z = ( (a.x*b.y) - (a.y*b.x) ); //k return toRet; } inline char bestCoord(Vector v1) { //Lazy fast method if (abs((int)v1.x) > abs((int)v1.y)) { if (abs((int)v1.x) > abs((int)v1.z)) { return 'x'; } else { return 'z'; } } else { if (abs((int)v1.y) > abs((int)v1.z)) { return 'y'; } else { return 'z'; } } } Vector Sphere::normal(Point p, Light l) { Vector normal; normal = p-this->center; return normal; } Vector Triangle::normal(Point p, Light l) { Vector normal, a1a2, a1a3, pl; a1a2 = this->a2 - this->a1; a1a3 = this->a3 - this->a1; normal = cross(a1a2,a1a3); pl = l.center - p; if (dot(normal,pl) < 0) { //normal = normal * ((double)-1.0); //STUPID OPERATOR OVERLOADING DOESNT WORK normal.x = normal.x * -1; normal.y = normal.y * -1; normal.z = normal.z * -1; } return normal; } Vector Triangle::normal(Point p) { Vector normal, a1a2, a1a3, pl; a1a2 = this->a2 - this->a1; a1a3 = this->a3 - this->a1; normal = cross(a1a2,a1a3); return normal; } bool Triangle::intersectsWithSelf(Point p, Light l, Point v) { Vector normal = this->normal(p,l), pv; pv = v - p; if (dot(normal,pv) < 0) { return true; } else return false; } double Triangle::intersectsWith(Ray ray) { Vector normal = this->normal(this->a1); //calculate t double top = dot(ray.origin - a1,normal); double bottom = dot(ray.direction, normal); double t = -1.0 * (top/bottom); if (t < 0) { return -1; } else { Point p = (ray.direction * t) + ray.origin; Vector pa1 = this->a1 - p; Vector pa2 = this->a2 - p; Vector pa3 = this->a3 - p; Vector pa1pa2 = cross(pa1,pa2); Vector pa2pa3 = cross(pa2,pa3); Vector pa3pa1 = cross(pa3,pa1); char best = bestCoord(pa1pa2); switch (best) { case 'x': if ((pa1pa2.x > 0 && pa2pa3.x > 0 && pa3pa1.x > 0) || (pa1pa2.x < 0 && pa2pa3.x < 0 && pa3pa1.x < 0)) { return t; } else { return -1; } case 'y': if ((pa1pa2.y > 0 && pa2pa3.y > 0 && pa3pa1.y > 0) || (pa1pa2.y < 0 && pa2pa3.y < 0 && pa3pa1.y < 0)) { return t; } else { return -1; } case 'z': if ((pa1pa2.z > 0 && pa2pa3.z > 0 && pa3pa1.z > 0) || (pa1pa2.z < 0 && pa2pa3.z < 0 && pa3pa1.z < 0)) { return t; } else { return -1; } default: cerr << "How?"; }; } return -1; }