#ifndef SPHERE_HXX
#define SPHERE_HXX

#include "Primitive.hxx"
#include "Box.hxx"

class Sphere : public Primitive
{
	Vec3f center;
	float radius2, p, radicand, t[2];
	int   num;
public:
	Sphere(Vec3f center, float radius, Shader *shader)
		: center(center),radius2(radius)
	{
		box.min = center - Vec3f(radius2 + Epsilon);
		box.max = center + Vec3f(radius2 + Epsilon);

		this->shader = shader;
		// Precompute the radius' square
		radius2 = radius2 * radius2;
	};

	virtual bool Intersect(Ray &ray)
	{
		// Apply the p-q-Formula:
		p        = Dot(ray.dir, ray.org - center);
		radicand = p * p - Dot(ray.org - center, ray.org - center) + radius2;

		if (radicand >= 0.0)
		{
			// We have two solutions. The Sqrt is only calculated once:
			radicand = sqrt(radicand);
			t[0]     = -p + radicand;
			t[1]     = -p - radicand;

			// Check the closer intersection point and take it if necessary
			num = t[1] < t[0];
			if (t[num] < ray.t && t[num] > Epsilon)
			{
				ray.t = t[num];
				ray.hit = this;
				return true;
			}

			// Check the farer intersection point and take it if necessary
			num = !num;
			if (t[num] < ray.t && t[num] > Epsilon)
			{
				ray.t = t[num];
				ray.hit = this;
				return true;
			}
		}

		// We could not find any intersection point
		return false;
	};

	virtual Vec3f GetNormal(Ray &ray)
	{
		Vec3f normal = ray.t * ray.dir + ray.org -center;
		Normalize(normal);
		return normal;
	};

	virtual Box CalcBounds()
	{
		return box;
	}
};

#endif
