/***************************************************************************
 *   Copyright (C) 2006 by Harish Kukreja   *
 *   harish.kukreja@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

//
// C++ Implementation: collision
//
// Description: Definitions of collision detection & reaction functions.
//
//
// Author: Harish Kukreja <harish.kukreja@gmail.com>, (C) 2006
//
// Copyright: See COPYING file that comes with this distribution
//
//

#include "collision.h"
#include "computations.h"

using namespace Physiks;
using namespace Physiks::Computation;

///////////////////////////////////////////////////////////////////////////////
bool Physiks::Collisions::Detection::point_sphere(const PhysicalObject &obj,
    const Sphere &sph) {
  return distance(obj, sph) < sph.radius;
}

///////////////////////////////////////////////////////////////////////////////
bool Physiks::Collisions::Detection::point_plane(const PhysicalObject &obj,
    const Plane &plane) {
  /* Find the minimum distance between the point and the plane. If the `base' of the plane-point
     interconnect lies in the bounded region, return true.   */
  Vector temp(obj.position - plane.position), normal_vec(plane.normal());
  Vector distance(Vector::dot(normal_vec, temp) * normal_vec);
  if (!plane.bounded()) {
    /* While this is the simplest form of "detection", it fails to account for the possibility
       of a PhysicalObject travelling at very high velocity and essentially passing through the 
       plane without ever being detected. This would happen if the PhysicalObject moves more than
       2.0E-3 in 1 timestep.   */
    return Vector::norm(distance) < 1.0E-3;  // This arbitrary value should not be hard-coded.
  } else {
    /*        if (plane.contains(obj.position - distance)) return distance.norm() < 1.0E-3;
              else return false;*/
  }
  return false;   // Temporary, until bounded plane collision detection can be implemented.
}

///////////////////////////////////////////////////////////////////////////////
bool Physiks::Collisions::Detection::sphere_sphere(const Sphere &sph1, const Sphere &sph2) {
  return distance(sph1, sph2) < (sph1.radius + sph2.radius);
}

///////////////////////////////////////////////////////////////////////////////
bool Physiks::Collisions::Detection::sphere_plane(const Sphere &sph, const Plane &plane) {
  Vector temp(sph.position - plane.position), normal_vec(plane.normal());
  Vector distance(Vector::dot(normal_vec, temp) * normal_vec);
  if (plane.bounded()) {
    /* How does one account for bounded planes? Hmmm....
       This doesn't take into account "skimming" collisions, where only a small portion of the
       sphere may strike the edge of the bounded plane.    */
    /*        if (plane.contains(sph.position - distance)) return distance.norm() < 1.0E-3;
              else return false;*/
  } else {
    /* Find the minimum distance between the center of the sphere and the plane, and compare it
       to the sphere's radius(). */
    return Vector::norm(distance) < sph.radius;
  }
  return false;   // Temporary, until bounded plane collision detection can be implemented.
}

//== TO BE IMPLEMENTED ============================================================

void Physiks::Collisions::Reaction::point_sphere(PhysicalObject &point, Sphere &sph) {
}

void Physiks::Collisions::Reaction::point_plane(PhysicalObject &poin, Plane &plane) {
}

void Physiks::Collisions::Reaction::sphere_sphere(Sphere &sph1, Sphere &sph2) {
}

void Physiks::Collisions::Reaction::sphere_plane(Sphere &sph, Plane &plane) {
}
