//***********************************************************//
// Demo:    VertexLight Demo
// Author:  terror
//***********************************************************//
#include "plane.h"

inline float flabs(float f) { return (f>=0.0f?f:-f); }
const float epsilon=1e-8f;
inline bool IsZero(float f) { return flabs(f)<epsilon; }


int triangle_t::operator = ( triangle_t &src )
{
	Vertex[0]  = src.Vertex[0];
	Vertex[1]  = src.Vertex[1];
	Vertex[2]  = src.Vertex[2];
	TVertex[0] = src.TVertex[0];
	TVertex[1] = src.TVertex[1];
	TVertex[2] = src.TVertex[2];
	Normal = src.Normal;
	D = src.D;

	return 0;
}


bool triangle_t::PointInTri ( const vector &p )
{
	int i1, i2;
	vector c ( flabs(Normal.v[0]), flabs(Normal.v[1]), flabs(Normal.v[2]) );
	if (c.v[0]>c.v[1])
	{ if (c.v[0]>c.v[2]) { i1=1; i2=2; } else { i1=0; i2=1; } }
	else
	{ if (c.v[1]>c.v[2]) { i1=0; i2=2; } else { i1=0; i2=1; } }
	vector u(		p.v[i1]-Vertex[0].v[i1], Vertex[1].v[i1]-Vertex[0].v[i1], Vertex[2].v[i1]-Vertex[0].v[i1]);
	vector v(		p.v[i2]-Vertex[0].v[i2], Vertex[1].v[i2]-Vertex[0].v[i2], Vertex[2].v[i2]-Vertex[0].v[i2]);
    float a,b;
    if (u.v[1]==0.0f)
    {
      b=u.v[0]/u.v[2];
      if (b>=0.0f && b<=1.0f) a=(v.v[0]-b*v.v[2])/v.v[1];
      else return false;
    }
    else
    {
      b=(v.v[0]*u.v[1]-u.v[0]*v.v[1])/(v.v[2]*u.v[1]-u.v[2]*v.v[1]);
      if (b>=0.0f && b<=1.0f) a=(u.v[0]-b*u.v[2])/u.v[1];
      else return false;
    }
    return (a>=0 && (a+b)<=1);
}


bool triangle_t::Intersect ( const vector &Origin, const vector &Dir, vector &cp,
													 float& tparm, float segmax )
{
	float denom=Normal.Dot ( Dir );
	if (IsZero(denom)) return false;
	float t=-(D+Normal.Dot(Origin))/denom;
	if (t<=0.0f) return false;
	if (t>segmax) return false;
	cp = Origin + t * Dir;

	if ( PointInTri ( cp ))
	{
		tparm = t;
		return true;
	}

	return false;
}


void triangle_t::Set ( vector &a, vector &b, vector &c )
{
	Vertex[0] = a;	Vertex[1] = b;	Vertex[2] = c;
	Normal.Cross ( Vertex[1] - Vertex[0], Vertex[2] - Vertex[0] );
	Normal.Normalize();
	D = -Normal.Dot(Vertex[0]);
}

void triangle_t::Set ( void )
{
	Normal.Cross ( Vertex[1] - Vertex[0], Vertex[2] - Vertex[0] );
	Normal.Normalize();
	D = -Normal.Dot(Vertex[0]);
}
