///////////////////////////////////////////////////////////////////////////////
/// @file deVec3.cpp
///
/// @brief Some non-inline 3D vector functions
///
/// @author Assassin
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Jan 2002
/// @author Assassin
/// @remarks Creation
///
/// @date Jul 2002
/// @author Hootie
/// @remarks Convert to static lib
///
///////////////////////////////////////////////////////////////////////////////

#include "deMath.hpp"

void Vec3d_Squeeze(deVec3d &v, deDouble e)
{ 
	v.X = (fabs(v.X) < e) ? 0 : v.X; 
	v.Y = (fabs(v.Y) < e) ? 0 : v.Y; 
	v.Z = (fabs(v.Z) < e) ? 0 : v.Z; 
}

void Vec3d_Cross(const deVec3d &V1, const deVec3d &V2, deVec3d &Result)
{
	Result.x = V1.y*V2.z - V1.z*V2.y;
	Result.y = V1.z*V2.x - V1.x*V2.z;
	Result.z = V1.x*V2.y - V1.y*V2.x;
}

void Vec3d_Cross(const deVertex &V1, const deVertex &V2, deVertex &Result)
{
	Result.x = V1.y*V2.z - V1.z*V2.y;
	Result.y = V1.z*V2.x - V1.x*V2.z;
	Result.z = V1.x*V2.y - V1.y*V2.x;
}

deDouble Vec3d_Normalize(deVec3d &V1)
{
	deDouble Length, OneOverLength;
	Length = (deDouble)sqrt(SQUARE(V1.x) + SQUARE(V1.y) + SQUARE(V1.z));

	if (Length <= 0.000001)
		return 0.0;

	OneOverLength = (deDouble)(1.0/Length);

	V1.x *= OneOverLength;
	V1.y *= OneOverLength;
	V1.z *= OneOverLength;

	return Length;
}

deFloat Vertex_Normalize(deVertex &V1)
{
	deFloat Length, OneOverLength;
	Length = (deFloat)sqrtf(SQUARE(V1.x) + SQUARE(V1.y) + SQUARE(V1.z));
	
	if (Length <= 0.000001)
		return 0.0;
	
	OneOverLength = (1.0f/Length);
	
	V1.x *= OneOverLength;
	V1.y *= OneOverLength;
	V1.z *= OneOverLength;
	
	return Length;
}

deARGB Vec3d_ConvertToDot3(const deVec3d &v, deFloat Height)
{
	DEBUG_EXP_RETURNMSG(Compare_Epsilon(Vec3d_Length(v), 1, 0.001), 0x00000000, "Vec3d_ConvertToDot3: un-normalized vector input");

	long r = (long)( 127.5 * v.x + 127.5 );
    long g = (long)( 127.5 * v.y + 127.5 );
    long b = (long)( 127.5 * v.z + 127.5 );
    long a = (long)( 255.0 * Height );

    return( (a<<24L) | (r<<16L) | (g<<8L) | (b<<0L) );
}

deARGB Vec3d_ConvertToDot3Clamp(const deVec3d &v, deFloat Height)
{
	long r = (long)( 127.5 * v.x + 127.5 );
    long g = (long)( 127.5 * v.y + 127.5 );
    long b = (long)( 127.5 * v.z + 127.5 );
    long a = (long)( 255.0 * Height );
	
	if (r > 255)
		r = 255;
	if (r < 0)
		r = 0;
	if (g > 255)
		g = 255;
	if (g < 0)
		g = 0;
	if (b > 255)
		b = 255;
	if (b < 0)
		b = 0;
	if (a > 255)
		a = 255;
	if (a < 0)
		a = 0;
	
    return( (a<<24L) | (r<<16L) | (g<<8L) | (b<<0L) );
}

