www.pudn.com > Direct3D-3ds_loader-render.rar > Vector.h


#ifndef _VECTOR_H 
#define _VECTOR_H 
#include  
 
#ifndef PI180 
#define PI180	0.0174532925199432957692369076848861f	// pi / 180 
#endif 
 
#ifndef PI 
#define PI		3.1415926535897932384626433832795 
#endif 
 
#define MIN(x,y)		((x) < (y) ?  (x)      : (y))					// minimum 
#define MAX(x,y)		((x) > (y) ?  (x)      : (y))					// maximum 
#define ABS(x)			((x) < (0) ? -(x)      : (x))	 
 
class vec2; 
class vec4; 
 
class vec   
{ 
public: 
	union 
	{ 
		struct 
		{ 
			float x, y, z; 
		}; 
		float v[3]; 
	}; 
 
	vec(){} 
	inline vec( const vec &a); 
	inline vec( const vec2 &a); 
	inline vec( const vec4 &a); 
	inline vec( const float a, const float b, const float c); 
	inline void set( const float a, const float b, const float c); 
	inline void clear(); 
 
	inline vec operator+() const; 
	inline vec operator-() const;		// negative 
 
	inline void operator+= ( const vec &a); 
	inline void operator-= ( const vec &a); 
	inline void operator*= ( const vec &a); 
	inline void operator/= ( const vec &a); 
 
	inline void operator+= ( const float f); 
	inline void operator-= ( const float f); 
	inline void operator*= ( const float f); 
	inline void operator/= ( const float f); 
 
	inline vec CROSS( const vec &a) const; 
	inline float DOT3( const vec &a) const; 
	inline float Length() const; 
	inline float Length2() const;		// = Length ^ 2 
 
	inline void RotX( const float angle); 
	inline void RotY( const float angle); 
	inline void RotZ( const float angle); 
	 
	inline void Normalize(); 
	inline void ArbitraryRotate(float theta, vec r); 
/* 
	inline friend vec operator+ ( const vec &a, const vec &b ); 
	inline friend vec operator- ( const vec &a, const vec &b ); 
	inline friend vec operator* ( const vec &a, const vec &b ); 
	inline friend vec operator/ ( const vec &a, const vec &b ); 
 
	inline friend vec operator+ ( const float f, const vec &a ); 
	inline friend vec operator- ( const float f, const vec &a ); 
	inline friend vec operator* ( const float f, const vec &a ); 
//	inline friend vec operator/ ( const float f, const vec &a ); 
	 
	inline friend vec operator+ ( const vec &a, const float f ); 
	inline friend vec operator- ( const vec &a, const float f ); 
	inline friend vec operator* ( const vec &a, const float f ); 
	inline friend vec operator/ ( const vec &a, const float f ); 
 
	inline friend int operator< ( const vec &a, const vec &b ); 
	inline friend int operator<=( const vec &a, const vec &b ); 
	inline friend int operator> ( const vec &a, const vec &b ); 
	inline friend int operator>=( const vec &a, const vec &b ); 
	inline friend int operator==( const vec &a, const vec &b ); 
	inline friend int operator!=( const vec &a, const vec &b ); 
 
	inline friend vec CROSS ( const vec &a, const vec &b ); 
	inline friend float DOT3  ( const vec &a, const vec &b ); 
	inline friend vec Normalize( const vec &a ); 
	inline friend float Length( const vec &a ); 
	inline friend float Length2( const vec &a ); 
	inline friend float Distance ( const vec &a, const vec &b); 
	inline friend float Distance2 ( const vec &a, const vec &b); 
	inline friend vec MakeNormal( const vec &a, const vec &b, const vec &c); 
	inline friend vec ReflectedRay( const vec &in, const vec &n); 
	inline float PlaneDistance( const vec &normal, const vec &point); 
	inline float PlanePointDelta( const vec &normal, float distance, const vec &point); 
	inline float PlanePointDistance( const vec &normal, float distance, const vec &point); 
	// Collision 
	inline vec ClosestPointOnLine( const vec &a, const vec &b, const vec &point); 
	inline int SpherePlaneCollision( const vec ¢er, float radius, const vec &normal, float distance, float *distanceCenterToPlane ); 
	double AngleBetweenVectors( const vec &a, const vec &b); 
	inline int PointInsidePolygon( const vec &point, const vec &a, const vec &b, const vec &c); 
	inline int PointInsidePolygon( const vec &point, const vec v[], unsigned int count); 
	inline int EdgeSphereCollision( const vec ¢er, float radius, const vec &a, const vec &b, const vec &c); 
	inline int EdgeSphereCollision( const vec ¢er, float radius, vec v[], unsigned int count); 
	inline int SpherePolygonCollision(const vec ¢er, float radius, vec v[], unsigned int count, const vec &normal); 
	inline int SpherePolygonCollision(const vec ¢er, float radius, const vec &a, const vec &b, const vec &c, const vec &normal); 
	inline int LinePlaneCollision( const vec &a, const vec &b, const vec &normal, float distance); 
	inline vec LinePlaneIntersection( const vec &a, const vec &b, const vec &normal, float distance); 
	inline vec LinePlaneIntersectionDir( const vec &a, const vec &ab, const vec &normal, float distance); 
	inline float LinePlaneIntersectionDirParameter( const vec &a, const vec &ab, const vec &normal, float distance); 
	inline int LinePolygonCollision( const vec &a, const vec &b, vec v[], unsigned int count, const vec &normal); 
	inline int LineSphereIntersection( const vec &p1, const vec &p2, const vec ¢er, float radius, double *t1, double *t2 ); 
	inline int LineSphereIntersectionDir( const vec &p1, const vec &p12, const vec ¢er, float radius, double *t1, double *t2 ); 
*/ 
}; 
inline char isInfPlus( const float &x); 
inline char isInfMinus( const float &x); 
 
inline vec::vec( const vec &a) 
{	x = a.x; y = a.y; z = a.z;} 
inline vec::vec( const float a, const float b, const float c ) 
{	x = a; y = b; z = c;} 
 
inline void vec::set( const float a, const float b, const float c) 
{	x = a; y = b; z = c;} 
 
inline void vec::clear() 
{	x = 0.f; y = 0.f; z = 0.f;} 
 
inline vec vec::operator+() const	{	return *this;} 
inline vec vec::operator-() const	{	return vec( -x, -y, -z);} 
 
inline void vec::operator+= ( const vec &a){	x += a.x; y += a.y; z += a.z;} 
inline void vec::operator-= ( const vec &a){	x -= a.x; y -= a.y; z -= a.z;} 
inline void vec::operator*= ( const vec &a){	x *= a.x; y *= a.y; z *= a.z;} 
inline void vec::operator/= ( const vec &a){	x /= a.x; y /= a.y; z /= a.z;} 
inline void vec::operator+= ( const float f){	x += f; y += f; z += f; } 
inline void vec::operator-= ( const float f){	x -= f; y -= f; z -= f; } 
inline void vec::operator*= ( const float f){	x *= f; y *= f; z *= f; } 
inline void vec::operator/= ( const float f){	x /= f; y /= f; z /= f; } 
 
inline vec operator+ ( const vec &a, const vec &b ){return vec( a.x+b.x, a.y+b.y, a.z+b.z );} 
inline vec operator- ( const vec &a, const vec &b ){return vec( a.x-b.x, a.y-b.y, a.z-b.z );} 
inline vec operator* ( const vec &a, const vec &b ){return vec( a.x*b.x, a.y*b.y, a.z*b.z );} 
inline vec operator/ ( const vec &a, const vec &b ){return vec( a.x/b.x, a.y/b.y, a.z/b.z );} 
 
inline vec operator+ ( const float f, const vec &a ){return vec( f+a.x, f+a.y, f+a.z );} 
inline vec operator- ( const float f, const vec &a ){return vec( f-a.x, f-a.y, f-a.z );} 
inline vec operator* ( const float f, const vec &a ){return vec( f*a.x, f*a.y, f*a.z );} 
inline vec operator+ ( const vec &a, const float f ){return vec( a.x+f, a.y+f, a.z+f );} 
inline vec operator- ( const vec &a, const float f ){return vec( a.x-f, a.y-f, a.z-f );} 
inline vec operator* ( const vec &a, const float f ){return vec( a.x*f, a.y*f, a.z*f );} 
inline vec operator/ ( const vec &a, const float f ){float f_ = 1.0f/f;return vec( a.x*f_, a.y*f_, a.z*f_ );} 
 
inline int operator< ( const vec &a, const vec &b ){return ((a.x< b.x)&&(a.y< b.y)&&(a.z< b.z));} 
inline int operator<=( const vec &a, const vec &b ){return ((a.x<=b.x)&&(a.y<=b.y)&&(a.z<=b.z));} 
inline int operator> ( const vec &a, const vec &b ){return ((a.x> b.x)&&(a.y> b.y)&&(a.z> b.z));} 
inline int operator>=( const vec &a, const vec &b ){return ((a.x>=b.x)&&(a.y>=b.y)&&(a.z>=b.z));} 
inline int operator==( const vec &a, const vec &b ){return ((a.x==b.x)&&(a.y==b.y)&&(a.z==b.z));} 
inline int operator!=( const vec &a, const vec &b ){return ((a.x!=b.x)||(a.y!=b.y)||(a.z!=b.z));} 
 
inline vec CROSS ( const vec &a, const vec &b ) 
{ 
	return vec( a.y*b.z - a.z*b.y,			//  i   j   k 
					a.z*b.x - a.x*b.z,			// a.x a.y a.z 
					a.x*b.y - a.y*b.x );		// b.x b.y b.z 
} 
inline vec vec::CROSS( const vec &a) const 
{ 
	return vec( y*a.z - z*a.y, 
					z*a.x - x*a.z, 
					x*a.y - y*a.x ); 
} 
 
inline float DOT3( const vec &a, const vec &b ) 
{ 
	return (a.x*b.x + a.y*b.y + a.z*b.z); 
} 
inline float vec::DOT3( const vec &a) const 
{ 
	return (x*a.x + y*a.y +z*a.z); 
} 
 
inline float vec::Length() const 
{	 
	return (float) sqrt(x*x + y*y + z*z); 
} 
 
inline float vec::Length2() const 
{	 
	return (float) x*x + y*y + z*z; 
} 
 
inline void vec::RotX( const float angle) 
{ 
	float s = (float) sin( PI180*angle ); 
	float c = (float) cos( PI180*angle ); 
	float Y=y; 
	y =  y*c - z*s; 
	z =  Y*s + z*c; 
} 
inline void vec::RotY( const float angle) 
{ 
	float s = (float) sin( PI180*angle ); 
	float c = (float) cos( PI180*angle ); 
	float X=x; 
	x =  x*c + z*s; 
	z = -X*s + z*c; 
} 
inline void vec::RotZ( const float angle) 
{ 
	float s = (float) sin( PI180*angle ); 
	float c = (float) cos( PI180*angle ); 
	float X=x; 
	x =  x*c - y*s; 
	y =  X*s + y*c; 
} 
inline void vec::Normalize() 
{ 
	float length; 
 
	length = (float) sqrt(x*x + y*y + z*z); 
	if (length != 0) { 
		x /= length; 
		y /= length; 
		z /= length; 
	} else { 
		x = 0; 
		y = 0; 
		z = 0; 
	} 
} 
 
//	Rotate a vector by angle theta around an arbitrary axis r 
//	Positive angles are anticlockwise looking down the axis  towards the origin. 
inline void vec::ArbitraryRotate(float theta, vec r)	// Rotate a vector by angle theta around an arbitrary axis r 
{ 
	vec p(x,y,z); 
	float costheta,sintheta; 
 
	theta*=PI180; 
	r.Normalize(); 
	costheta = (float)cos(theta); 
	sintheta = (float)sin(theta); 
 
	x  = (costheta + (1 - costheta) * r.x * r.x) * p.x; 
	x += ((1 - costheta) * r.x * r.y - r.z * sintheta) * p.y; 
	x += ((1 - costheta) * r.x * r.z + r.y * sintheta) * p.z; 
 
	y  = ((1 - costheta) * r.x * r.y + r.z * sintheta) * p.x; 
	y += (costheta + (1 - costheta) * r.y * r.y) * p.y; 
	y += ((1 - costheta) * r.y * r.z - r.x * sintheta) * p.z; 
 
	z  = ((1 - costheta) * r.x * r.z - r.y * sintheta) * p.x; 
	z += ((1 - costheta) * r.y * r.z + r.x * sintheta) * p.y; 
	z += (costheta + (1 - costheta) * r.z * r.z) * p.z; 
} 
 
inline vec Normalize( const vec &a){	return a/a.Length();} 
inline float Length( const vec &a ){	return a.Length();} 
inline float Length2( const vec &a ){	return a.Length2();} 
inline float Distance ( const vec &a, const vec &b){	return Length( a-b );} 
inline float Distance2 ( const vec &a, const vec &b){	return Length2( a-b );} 
 
inline vec MakeNormal( const vec &a, const vec &b, const vec &c) 
{ 
	return Normalize(CROSS( b - a, c - a)); 
} 
 
inline vec ReflectedRay( const vec &in, const vec &n)	// in from eye to vertex 
{ 
	return (in - 2.f*n*DOT3( in, n)); 
} 
 
inline float PlaneDistance( const vec &normal, const vec &point) 
{ 
	return -DOT3( normal, point);	//	D = - Ax + By + Cz;   plane equation is Ax + By + Cz + D = 0 
} 
inline float PlanePointDelta( const vec &normal, float distance, const vec &point) 
{ 
	// if point is on normal side, return positive value, else return negative value 
	return DOT3( normal, point) + distance;			// d = Ax + By + Cz + D 
} 
inline float PlanePointDistance( const vec &normal, float distance, const vec &point) 
{	 
	// return always positive value 
	return ABS(DOT3( normal, point) + distance);			// distance = ABS(Ax + By + Cz + D) 
} 
 
// najblisi bod na usecke a,b k bodu point 
inline vec ClosestPointOnLine( const vec &a, const vec &b, const vec &point) 
{ 
	vec ap = point - a;			// vector from a to point 
	vec ab = b-a;				// vector from a to b 
	float d = ab.Length();		// = Distance( a, b);  // length Line 
	ab.Normalize();				// normalized direction vector from a to b 
	float t = DOT3( ab, ap);	// ab is unit vector, t is distance from a to point projected on line ab 
	if( t<= 0) return a;		// point projected on line ab is out of line, closest point on line is a 
	if( t>= d) return b;		// point projected on line ab is out of line, closest point on line is b 
	return a+t*ab;				// point away from a on t length in direction ab 
} 
inline int SpherePlaneCollision( const vec ¢er, float radius, const vec &normal, float distance, float *distanceCenterToPlane ) 
{ 
	*distanceCenterToPlane = DOT3( normal, center) + distance;			// d = Ax + By + Cz + D 
	if( fabs(*distanceCenterToPlane) < radius) return 1;	// sphere intersected plane 
//	if( *distanceCenterToPlane<= -radius) return 2;			// sphere behind plane 
//	else return 0;											// sphere is front plane 
	return 0;												// sphere is front or behind plane 
} 
 
inline double AngleBetweenVectors( const vec &a, const vec &b) 
{							 
	double angle = acos( DOT3( a, b) / ( a.Length()*b.Length() ) ); 
//	if(_isnan(angle))return 0;		// Here we make sure that the angle is not a -1.#IND0000000 number, which means indefinate 
	if( isInfPlus( (float)angle)||isInfMinus( (float)angle) )return 0; 
	return( angle ); 
} 
 
// return, t=0 a, t=1 b 
inline vec Interpolate( vec a, const vec &b, float t) 
{ 
	if(a==b)return a; 
	float angle = (float)AngleBetweenVectors( a, b); 
	a.ArbitraryRotate( angle*t/PI180, CROSS( a, b)); 
	return a; 
} 
 
inline int PointInsidePolygon( const vec &point, const vec &a, const vec &b, const vec &c) 
{ 
	vec pa = a-point; 
	vec pb = b-point; 
	vec pc = c-point; 
	double angle  = AngleBetweenVectors( pa, pb); 
	angle += AngleBetweenVectors( pb, pc); 
	angle += AngleBetweenVectors( pc, pa); 
 
	const double MATCH_FACTOR = 0.99;			// Used to cover up the error in floating point 
	if(angle >= (MATCH_FACTOR * (2.0 * PI)) )	// If the angle is greater than 2 PI, (360 degrees) 
		return 1;							// The point is inside of the polygon 
	return 0;								// If you get here, it obviously wasn't inside the polygon, so Return FALSE 
} 
 
inline int PointInsidePolygon( const vec &point, const vec v[], unsigned int count) 
{ 
	double angle = 0.0; 
	 
	for (int i = 0; (unsigned int)i= (MATCH_FACTOR * (2.0 * PI)) )	// If the angle is greater than 2 PI, (360 degrees) 
		return 1;							// The point is inside of the polygon 
	return 0;								// If you get here, it obviously wasn't inside the polygon, so Return FALSE 
} 
 
inline int EdgeSphereCollision( const vec ¢er, float radius, const vec &a, const vec &b, const vec &c) 
{ 
	if( Distance(center, ClosestPointOnLine( a, b, center)) < radius) return 1; 
	if( Distance(center, ClosestPointOnLine( b, c, center)) < radius) return 1; 
	if( Distance(center, ClosestPointOnLine( c, a, center)) < radius) return 1; 
	return 0; 
} 
 
inline int EdgeSphereCollision( const vec ¢er, float radius, vec v[], unsigned int count) 
{ 
	for(int i = 0; (unsigned int)i t2 
	return 2; 
} 
 
inline int LineSphereIntersection( const vec &p1, const vec &p2, const vec ¢er, float radius, double *t1, double *t2 ) 
{ 
	return LineSphereIntersectionDir( p1, p2-p1, center, radius, t1, t2); 
} 
/*  angle1 
   in\  A n-nomala 
      \ |     n1 - absolute refraction index of material 1 
       V|                        sin(angle1)   v1   c/n1   n2        1.0 
   -----+------  nr = n2/n1      ----------- = -- = ---- = -- = nr = --- 
         \                       sin(angle2)   v2   c/n2   n1        nri 
         |    n2 - absolute refraction index of material 2 
         \                       n1*sin(angle1) = n2*sin(angle2) 
   angle2 | T - transmission vector 
in - vector from eye to vertex, must be normalized 
n - normal vector 
nr - relative refraction index, water nr = 1.33 
nri - nri = 1.f/nr 
  T = nri*in - nri*(in*n)*n - sqrt( 1.0-nri^2*(1.0-(in,n)^2) )*n   */ 
// *i - call with nri = 1/relative refraction index 
// *n - vector in is Normalized 
inline vec RefractedRayin(const vec &in, const vec &n, float nri)	// in from eye to vertex 
{ 
//	float nri=1.f/nr; 
	float dot_in_n = DOT3(in,n); 
	float a = (float)sqrt( 1.f-nri*nri*(1.f-dot_in_n*dot_in_n) ); 
	return nri*in - (a+nri*dot_in_n)*n; 
} 
inline vec RefractedRayi( vec &in, const vec &n, float nri)		// normalize in 
{	return RefractedRayin( Normalize(in), n, nri);} 
inline vec RefractedRay( vec &in, const vec &n, float nr) 
{	return RefractedRayin( Normalize(in), n, 1.f/nr);} 
 
// work also if DOT3( in, n) > 0.f 
inline vec RefractedRayic( vec &in, const vec &n, float nri)	// in from eye to vertex 
{ 
	if( DOT3( in, n) > 0.f) 
		return RefractedRayi( in, -n, 1.f/nri); 
	else  
		return RefractedRayi( in, n, nri); 
} 
 
inline float FresnelF0( float nr) 
{ 
	float nri=1.f/nr; 
	float f0,f0_; 
	f0 = 1-nri;		//      (1-nri)^2 
	f0 *= f0;		// f0 = ---------- 
	f0_ = 1+nri;	//      (1+nri)^2 
	f0_ *= f0_; 
	f0 /= f0_; 
	return f0; 
} 
// Fresnel 
inline float Fresnelin( const vec &in, const vec &n, float nri, float f0) 
{ 
	float dot = DOT3( n, -in); 
	float dot2 = dot*dot; 
	dot *= dot2*dot2;		// dot = (n*v)^5 
	return f0+(1.f-f0)*dot; 
} 
inline float Fresneli( const vec &in, const vec &n, float nri, float f0) 
{	return Fresnelin( Normalize(in), n, nri, f0);} 
inline float Fresnel( const vec &in, const vec &n, float nr, float f0) 
{	return Fresnelin( Normalize(in), n, 1.f/nr, f0);} 
 
inline float Fresnelin_1( const vec &in, const vec &n, float nri, float f0) 
{ 
	float dot = DOT3( n, -in);	// dot = (n*v)^1 
	return f0+(1.f-f0)*dot; 
} 
inline float Fresnelin_3( const vec &in, const vec &n, float nri, float f0) 
{ 
	float dot = DOT3( n, -in); 
	dot *= dot*dot;				// dot = (n*v)^3 
	return f0+(1.f-f0)*dot; 
} 
 
inline char isInfPlus( const float &x) 
{ 
	float a; 
	*(unsigned int*)&a = (unsigned int)0x7f800000; 
	return ( x==a); 
//	return (*(unsigned int*) &x==0x7f800000); 
} 
 
inline float Fresnel2in( const vec &in, const vec &n, float nri) 
{ 
	float k,g; 
	 
	k = DOT3( in, n); 
	g = (float)sqrt(nri*nri+k*k-1); 
 
	float gmk = g-k; 
	float gpk = g+k; 
 
	float a = k*gpk-1; 
	float b = k*gmk+1; 
	return (gmk*gmk/(2*gpk*gpk)) *(1+(a*a)/(b*b)); 
} 
inline float Fresnel2( const vec &in, const vec &n, float nr) 
{	return Fresnel2in( Normalize(in), n, 1.f/nr);} 
 
 
 
inline char isInfMinus( const float &x) 
{ 
	float a; 
	*(unsigned int*)&a = (unsigned int)0xff800000; 
	return ( x==a); 
//	return (*(unsigned int*) &x==0xff800000); 
} 
 
 
class vec2   
{ 
public: 
	union 
	{ 
		struct 
		{ 
			float x, y; 
		}; 
		float v[2]; 
	}; 
	void set( float x_, float y_){ x=x_; y=y_;} 
}; 
 
class vec4  
{ 
public: 
	union 
	{ 
		struct 
		{ 
			float x, y, z, w; 
		}; 
		float v[4]; 
	}; 
 
	vec4(){} 
	inline vec4( const vec4 &a); 
	inline vec4( const vec &in); 
	inline vec4( const float a, const float b, const float c, const float d = 1.f); 
	inline void set( const float a, const float b, const float c, const float d = 1.f); 
	inline void clear(); 
}; 
 
inline vec4::vec4( const vec4 &a) 
{	x = a.x; y = a.y; z = a.z; w = a.w;} 
inline vec4::vec4( const vec &in) 
{	x = in.x; y = in.y; z = in.z; w = 1.f;} 
inline vec4::vec4( const float a, const float b, const float c, const float d) 
{	x = a; y = b; z = c; w = d;} 
inline void vec4::set( const float a, const float b, const float c, const float d) 
{	x = a; y = b; z = c; w = d;} 
inline void vec4::clear() 
{	x = 0; y = 0; z = 0; w = 1;} 
 
inline vec::vec( const vec4 &a) 
{	x = a.x; y = a.y; z = a.z;} 
 
inline vec::vec( const vec2 &a) 
{	x = a.x; y = a.y; z = 0.f;} 
 
 
inline vec Bspline( const vec &p0, const vec &p1, const vec &p2, const vec &p3, float t) 
{ 
	float t2=t*t;		// t^2 
	float c3=t2*t;		// t^3 
	float c0,c1,c2; 
 
	c0 = 1.f - t;	c0 *= c0*c0;		// c0 = (1-t)^3 
	c1 = 3.f*c3 - 6.f*t2 + 4;			// c1 = 3*t^3 - 6*t^2 + 4 
	c2 =-3.f*c3 + 3.f*t2 + 3.f*t + 1.f;	// c2 =-3*t^3 + 3*t^2 + 3*t + 1 
//	c3 = t*t*t; 
//	vec v = c0*p0 + c1*p1 + c2*p2 + c3*p3; 
//	v *= 0.166666666666666666666666666666667f;	// 1/6 
	return 0.166666666666666666666666666666667f*(c0*p0 + c1*p1 + c2*p2 + c3*p3); 
} 
 
inline vec BsplineDeriv( const vec &p0, const vec &p1, const vec &p2, const vec &p3, float t) 
{ 
	float t2=t*t;		// t^2 
	float c0,c1,c2,c3; 
//	(1-t)^3 = (1-t)*(1-t-t+t^2) = (1-t)*(1-2*t+t^2) = (1-2*t+t^2 -t +2*t^2 - t^3) = (1-3*t+3*t^2-t^3) 
	c0 =-3.f*t2 + 6.f*t - 3;			// c0 =-3*t^2 + 6*t - 3 
	c1 = 9.f*t2 -12.f*t;				// c1 = 9*t^2 -12*t 
	c2 =-9.f*t2 + 6.f*t + 3;			// c2 =-9*t^2 + 6*t + 3 
	c3 = 3.f*t*t;						// c3 = 3*t^2 
	return 0.166666666666666666666666666666667f*(c0*p0 + c1*p1 + c2*p2 + c3*p3); 
} 
 
inline vec HermiteCurve( const vec &p0, const vec &p1, const vec &t0, const vec &t1, float t) 
{ 
	float t2 = t*t; 
	float t3 = t2*t; 
	float h1 =  2*t3 - 3*t2 + 1; 
	float h2 = -2*t3 + 3*t2; 
	float h3 =    t3 - 2*t2 + t; 
	float h4 =    t3 -   t2; 
	return h1*p0 + h2*p1 + h3*t0 + h4*t1; 
} 
 
inline vec HermiteCurveDeriv( const vec &p0, const vec &p1, const vec &t0, const vec &t1, float t) 
{ 
	float t2 = t*t; 
	float h1 =  6*t2 - 6*t; 
	float h2 = -6*t2 + 6*t; 
	float h3 =  3*t2 - 4*t + 1; 
	float h4 =  3*t2 - 2*t; 
	return h1*p0 + h2*p1 + h3*t0 + h4*t1; 
} 
 
#endif