/**
 * @class kVec3
 * @brief Representation of 3D vectors and points.
 */
 
class kVec3
{
public:

	kVec3(const kVec3 &in v);
	kVec3(float x, float y, float z);
	
	/**
	 * @brief Makes this vector have a magnitude of 1
	 */
	kVec3 &Normalize();
	
	/**
	 * @brief Returns the squared length of this vector
	 */
	float UnitSq();
	
	/**
	 * @brief Returns the length of this vector
	 */
	float Unit();
	
	/**
	 * @brief Dot Product of two vectors
	 */
	float Dot(const kVec3 &in other);
	
	/**
	 * @brief Cross Product of two vectors
	 */
	kVec3 Cross(const kVec3 &in);

	/**
	 * @brief Returns the Yaw direction in Rads
	 */
	float ToYaw();
	
	/**
	 * @brief Returns a nicely formatted string for this vector
	 */
	kStr ToString();
	
	/**
	 * @brief Returns the squared distance between this instance and \a other
	 */
	float DistanceSq(const kVec3 &in other);
	
	/**
	 * @brief Returns the distance between this instance and \a other
	 */
	const float Distance(const kVec3 &in other);
	
	/**
	 * @brief Linearly interpolates between two vectors
	 */
	const kVec3 Lerp(const kVec3 &in other, const float t);
	
	/**
	 * @brief Set x, y and z components of an this kVec3
	 */
	const void Set(const float x, const float y, const float z);
	
	/**
	 * @brief Sets x, y and z components to 0
	 */
	void Clear();
	
	/**
	 * @brief Returns the Pitch direction in Rads
	 */
	float ToPitch();
	
	kVec3 &Randomize(const float value);
	
	/**
	 * @brief Reflects a vector off the plane defined by a normal
	 */
	kVec3 &Reflect(const kVec3 &in normal, const float value);
	
	/**
	 * @brief Projects a vector onto another vector
	 */
	kVec3 &Project(const kVec3 &in normal, const float value);
	
	kVec3 &opAddAssign(const kVec3 &in other);
	kVec3 opAdd(const kVec3 &in other);
	kVec3 &QuadraticCurve(const kVec3 &in point1, const float value, const kVec3 &in point2, const kVec3 &in point3);
	kVec3 &CubicCurve(const kVec3 &in point1, const float value, const kVec3 &in point2);
	kVec3 opMul(const kVec3 &in other);
	kVec3 &opSubAssign(const kVec3 &in other);
	kVec3 opSub(const kVec3 &in other);
	kVec3 opNeg();
	kVec3 opDiv(const kVec3 &in other);
	kVec3 &opMulAssign(const float value);
	kVec3 &opMulAssign(const kVec3 &in other);
	kVec3 opMul(const float value);
	kVec3 &opAssign(const kVec3 &in other);
	kVec3 &opDivAssign(const kVec3 &in other);
	kVec3 opDiv(const float value);
	/**
	 * @brief Access the x, y, z components using [0], [1], [2] respectively
	 */
	float opIndex(uint);
	float x;
	float y;
	float z;
};
