//	Particle.h - a massive particle which is part of a rigid body.
//
//  Copyright (C) 2001--2002 Sam Varner
//
//  This file is part of Vamos Automotive Simulator.
//
//  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

#ifndef _PARTICLE_H_
#define _PARTICLE_H_

#include <vamos/geometry/Three_Vector.h>
#include <vamos/geometry/Three_Matrix.h>
#include <vamos/geometry/Inertia_Tensor.h>
#include <vamos/geometry/Material.h>
#include <vamos/body/Frame.h>
#include <vamos/body/Exerter.h>

namespace Vamos_Body
{
  //* A Particle is a massive particle which is part of a rigid body.
  // It has position and orientation information inherited from Frame.
  // The parent frame is the rigid body's.  A Particle can exert
  // forces and torques on the rigid body because it is derived from
  // Component.
  class Particle : public Frame, public Exerter
  {
  protected:
	// The mass of the particle.
	double m_mass;

	// Material properties for the particle.
	Vamos_Geometry::Material_Handle m_material;

  public:
	//** Constructors

	// Specify position and orientation.
	Particle (double mass, const Vamos_Geometry::Three_Vector& position, 
			  const Vamos_Geometry::Three_Matrix& orientation);

	// Take the parent's orientation.
	Particle (double mass, const Vamos_Geometry::Three_Vector& position);

	// The particle's frame is coincident with the parent's.
	Particle (double mass = 0.0);

	//** Destructor
	virtual ~Particle () {};

	// Return the force exerted on the rigid body in the body's frame.
	virtual Vamos_Geometry::Three_Vector force () const
	{ return rotate_out (m_force); }

	// Return the impulse exerted on the rigid body in the body's
	// frame.
	virtual Vamos_Geometry::Three_Vector impulse () const
	{ return rotate_out (m_impulse); }

	// Return the torque exerted on the rigid body in the body's frame.
	virtual Vamos_Geometry::Three_Vector torque () const
	{ return rotate_out (m_torque); }

	// Classes derived from Particle may lie about their positions
	// for collisions...
	virtual Vamos_Geometry::Three_Vector contact_position () const 
	{ return position (); }

	// ...for exerting forces and impulses...
	virtual Vamos_Geometry::Three_Vector force_position () const 
	{ return position (); }

	// ...for exerting torques...
	virtual Vamos_Geometry::Three_Vector torque_position () const 
	{ return position (); }

	// ...or for constructing the inertia tensor of the rigid body.
	virtual Vamos_Geometry::Three_Vector mass_position () const 
	{ return position (); }

	virtual double contact (const Vamos_Geometry::Three_Vector& position,
							const Vamos_Geometry::Inertia_Tensor& inertia,
							const Vamos_Geometry::Three_Vector& velocity,
							double distance,
							const Vamos_Geometry::Three_Vector& normal,
							const Vamos_Geometry::Three_Vector& ang_velocity,
							Vamos_Geometry::Material_Handle) 
	{ return 0.0; }

	// Return the particle's mass.
	double mass () const { return m_mass; }

	virtual bool single_contact () const { return true; }
	virtual void wind (const Vamos_Geometry::Three_Vector& wind_vector, 
					   double density) 
	{};

	// Return the material properties.
	const Vamos_Geometry::Material_Handle& material () const 
	{ return m_material; }
  };
}

#endif // not _PARTICLE_H_
