// Smoke39 - some handy functions that don't seem to be included already

// TODO: remove old float min/max functions in favor of new built-in functions after Turok Ex 2.0 leaves beta
namespace Math
{
	float OLDMin( const float a, const float b )
	{
		return (a<b)? a : b;
	}
	int Min( const int a, const int b )
	{
		return (a<b)? a : b;
	}

	float OLDMax( const float a, const float b )
	{
		return (a>b)? a : b;
	}
	int Max( const int a, const int b )
	{
		return (a>b)? a : b;
	}

	float FClamp( const float val, const float min, const float max )
	{
		if ( val < min )
			return min;
		if ( val > max )
			return max;
		return val;
	}
	int Clamp( const int val, const int min, const int max )
	{
		if ( val < min )
			return min;
		if ( val > max )
			return max;
		return val;
	}

	int Sign( const float f )
	{
		return Int(f>0) - Int(f<0);
	}
	int Sign( const int i )
	{
		return Int(i>0) - Int(i<0);
	}

	float Sqr( const float f )
	{
		return f*f;
	}
	// converts the line y=x from 0 to 1 into a concave down curve with the same end points
	float FakeSqrt( float f )
	{
		f -= 1;
		return 1 - f*f;
	}

	int RandRange( int min, int max )
	{
		return min + RandMax(max-min+1);
	}

	// kVec3::Lerp() applies result to self -- this version does not
	kVec3 Lerp( kVec3&in a, kVec3&in b, float pct )
	{
		return kVec3(a).Lerp( b, pct );
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//    boolean
//

int Int( bool b )
{
	return b? 1 : 0;
}

bool Bool( int i )
{
	return i != 0;
}

////////////////////////////////////////////////////////////////////////////////
//
//    strings
//

kStr Str( float f )
{
	return ""+f;
}

// char code to int
int CtoI( int8 c )
{
	return c - "0"[0];
}

////////////////////////////////////////////////////////////////////////////////
//
//    vectors
//

bool Equal( kVec3 &in v1, kVec3 &in v2 )
{
	return v1.x==v2.x && v1.y==v2.y && v1.z==v2.z;
}

void GetAxes( const kQuat &in r, kVec3 &out x, kVec3 &out y, kVec3 &out z )
{
	x = kVec3(1,0,0) * r;
	y = kVec3(0,1,0) * r;
	z = kVec3(0,0,1) * r;
}
kVec3 ToLocal( const kVec3 &in v, const kQuat &in r )
{
	kVec3 x, y, z;
	GetAxes( r, x,y,z );
	return kVec3( v.Dot(x), v.Dot(y), v.Dot(z) );
}

////////////////////////////////////////////////////////////////////////////////
//
//    spacial
//

// deltaToOrigin = cylinder base - point of interest
// returns 0 on or inside the cylinder, and upwards as the point moves out from the surface
float DistToCylinder( kVec3 &in deltaToOrigin, float radius, float height )
{
	deltaToOrigin.x = Math::OLDMax( (deltaToOrigin*kVec3(1,1,0)).Unit() - radius, 0.0f );
	deltaToOrigin.y = 0;
	if ( deltaToOrigin.z < 0 )
		deltaToOrigin.z = Math::OLDMin( deltaToOrigin.z + height, 0.0f );
	return deltaToOrigin.Unit();
}
