#ifndef SPHERE_HXX
#define SPHERE_HXX

#include "Primitive.hxx"
#include "Shader.hxx"

class Sphere : public Primitive
{
  Vec3f center;
  float radius;
public:
  Sphere(Vec3f center, float radius, Shader *shader)
    : Primitive(shader),center(center),radius(radius)
  {};

  virtual bool Intersect(Ray &ray)
  {
    // mathematical derivation, numerically not very stable, but simple

    // --> find roots of f(t) = ((R+tD)-C)^2 - r^2
    // f(t) = (R-C)^2 + 2(R-C)(tD) + (tD)^2 -r^2
    // --> f(t) = [D^2] t^2 + [2D(R-C)] t + [(R-C)^2 - r^2]
    Vec3f diff = ray.org - center;
    float a = Dot(ray.dir,ray.dir);
    float b = 2 * Dot(ray.dir,diff);
    float c = Dot(diff,diff) - radius * radius;

    // use 'abc'-formula for finding root t_1,2 = (-b +/- sqrt(b^2-4ac))/(2a)
    float inRoot = b*b - 4*a*c;
    if (inRoot < 0) return false;
    float root = sqrt(inRoot);

    float dist = (-b - root)/(2*a);
    if (dist > ray.t)
      return false;

    if (dist < Epsilon) {
      dist = (-b + root)/(2*a);
      if (dist < Epsilon || dist > ray.t)
	return false;
    }

    ray.t = dist;
    ray.hit = this;
    return true;
  };

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

  virtual Box CalcBounds()
  {
	assert(0);
	return Box();
  }
};

#endif
