
class Point3 {
public:
	float x,y,z;
	Point3(float a, float b, float c);
};

class Vector3 {
public:
	float x,y,z;
	Vector3(float a, float b, float c);
};

class Color{
public:
	float r,g,b;
	Color(float a, float b, float c);
};

class Material{
public:
	Color Kd; // Specular reflectance
	Color Ks; // Diffuse reflectance
	float n;  // Shinyness
	Material(Color a, Color b, float f);
};

class Ray{
public:
	Point3 o; // Origin
	Vector3 d; // Direction
	Ray(Point3 a, Vector3 b);
};

class Interval{
public:
	float t1, t2; // Scalar range
	Interval(float a, float b);

	bool nullRange();
};

Interval::Interval(float a, float b)
{
	if (b > a){ t1 = a; t2 = b;}
	else { t2 = a; t1 = b;}
}

class Sphere{
public:
	float r; // radius
	Point3 c; // Center
	Material m;
	Sphere(float r, float x, float y, float z, Color Kd, Color Ks, float n);
	bool intersect(Ray *ray, float *t, Vector3 *n, Material *m);
	bool intersect(Ray *ray, Interval *in, Vector3 *n, Material *m);
		//This is an additional intersection routine to help do CSG operation.
};

// Let us assume that a CSG object is made up of 2 spheres.
// It can be made to be set operation of any two solids.
class CSG{
	enum {UNION, INTERSECTION, SUBTRACTION} optype;
public:
	bool intersect(Ray *r, Interval *in, Vector3 *n, Material *m);
	bool intersect(Ray *r, float *t, Vector3 *n, Material *m);
	Sphere s1, s2; // Two spheres
	CSG(char *typestring, Sphere s1, Sphere s2);
};

bool CSG::intersect(Ray *r, float *t, Vector3 *n, Material *m)
{
	// Intersect with Sphere 1. If intersects get the scalar interval of intersection
	// Intersect with Sphere 2. If intersects get the scalar interval of intersection
	// Depending on the type of intersection find the range of intersection
	// let it be "in"
	if (!in.nullRange()){ 
		-- Set the proper normal
		-- Set the proper material property
		*t = in.t1; 
		return true;
	}
	return false;
}