#ifndef __PLANEH__
#define __PLANEH__

#include "mathlib.h"

static const float Epsilon = 1.0e-05f;

struct plane_t
{
   plane_t()                           {d = 0;}
   virtual ~plane_t()                  { }
   
   void Reset(void)                    {n.Set(0, 0, 0); d = 0;}

   // Returns 1 if the point, 'pt', is in front of the plane
   bool IsFront(vec3_t &pt)     {return (GetPointDistance(pt) > 0.0f) ? 1 : 0;}

   // Returns 1 if the point, 'pt', is behind the plane
   bool IsBack(vec3_t &pt)             {return !(IsFront(pt));}

   // Returns 1 if the point, 'pt', is on the plane
   inline bool IsOn(vec3_t &pt);   

   // Calculates the plane equation given three points
   inline void CalcPlane(vec3_t &pta, vec3_t &ptb, vec3_t &ptc);

   // Returns 1 if the line from 'start' to 'end' intersects the plane.  
   // 'point' is a point on the plane and 'result' is the point of
   // intersection if there is one, if there is no intersection 'result' is
   // not modified.  
   inline bool LineIntersect(vec3_t &start, vec3_t &end, vec3_t &point,
    vec3_t &result);

   // Returns the distance that a point, 'pt', is from the plane
   float GetPointDistance(vec3_t &pt)  {return n.Dot(pt) + d;} 

   // Returns the normal, A B and C in the plane equation
   const vec3_t &GetNormal(void)              {return n;}
   
   // Returns the D component of the plane equation
   const float &GetD(void)                    {return d;}

protected:
   vec3_t n;
   float d;
};

inline bool plane_t::IsOn(vec3_t &pt)
{
   float d = GetPointDistance(pt);
   return (d > -Epsilon && d < Epsilon) ? 1 : 0;
}

inline void plane_t::CalcPlane(vec3_t &pta, vec3_t &ptb, vec3_t &ptc)
{
   n.Cross(ptb - pta, ptc - pta);
   n.Normalize();
   d = -ptc.Dot(n);
}

inline bool plane_t::LineIntersect(vec3_t &start, vec3_t &end, vec3_t &point,
 vec3_t &result)
{
	float denom, numer, u;
	vec3_t dir;

	dir = end - start;

	denom = n.Dot(dir);

   // No divide by zero!
	if (denom > -Epsilon && denom < Epsilon)
		return 0; // Line is parallel to the plane

	numer = n.Dot(point - start);

	u = numer / denom;

   // Is there an intersection along the line?
	if (u <= 0.0f || u > 1.0f)
		return 0;

	result = start + dir * u; // point of intersection

	return 1;
}

#endif