//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
//**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************//
using System;
using System.Runtime.InteropServices;
namespace BansheeEngine
{
/** @addtogroup Math
* @{
*/
///
/// A three dimensional vector.
///
[StructLayout(LayoutKind.Sequential), SerializeObject]
public struct Vector3 // Note: Must match C++ class Vector3
{
public static readonly Vector3 Zero = new Vector3(0.0f, 0.0f, 0.0f);
public static readonly Vector3 One = new Vector3(1.0f, 1.0f, 1.0f);
public static readonly Vector3 XAxis = new Vector3(1.0f, 0.0f, 0.0f);
public static readonly Vector3 YAxis = new Vector3(0.0f, 1.0f, 0.0f);
public static readonly Vector3 ZAxis = new Vector3(0.0f, 0.0f, 1.0f);
public float x;
public float y;
public float z;
///
/// Accesses a specific component of the vector.
///
/// Index of the component.
/// Value of the specific component.
public float this[int index]
{
get
{
switch (index)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
default:
throw new IndexOutOfRangeException("Invalid Vector3 index.");
}
}
set
{
switch (index)
{
case 0:
x = value;
break;
case 1:
y = value;
break;
case 2:
z = value;
break;
default:
throw new IndexOutOfRangeException("Invalid Vector3 index.");
}
}
}
///
/// Returns a normalized copy of the vector.
///
public Vector3 Normalized
{
get
{
return Normalize(this);
}
}
///
/// Returns the length of the vector.
///
public float Length
{
get
{
return (float)MathEx.Sqrt(x * x + y * y + z * z);
}
}
///
/// Returns the squared length of the vector.
///
public float SqrdLength
{
get
{
return (x * x + y * y + z * z);
}
}
///
/// Creates a new three dimensional vector.
///
/// X coordinate.
/// Y coordinate.
/// Z coordinate.
public Vector3(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
///
/// Converts a three dimensional vector into a four dimensional vector. w component will be set to zero.
///
/// Vector to convert.
/// A new four dimensional vector.
public static explicit operator Vector4(Vector3 vec)
{
return new Vector4(vec.x, vec.y, vec.z, 0.0f);
}
public static Vector3 operator+ (Vector3 a, Vector3 b)
{
return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
}
public static Vector3 operator- (Vector3 a, Vector3 b)
{
return new Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
}
public static Vector3 operator- (Vector3 v)
{
return new Vector3(-v.x, -v.y, -v.z);
}
public static Vector3 operator*(Vector3 a, Vector3 b)
{
return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
}
public static Vector3 operator* (Vector3 v, float d)
{
return new Vector3(v.x * d, v.y * d, v.z * d);
}
public static Vector3 operator* (float d, Vector3 v)
{
return new Vector3(v.x * d, v.y * d, v.z * d);
}
public static Vector3 operator/ (Vector3 v, float d)
{
return new Vector3(v.x / d, v.y / d, v.z / d);
}
public static bool operator ==(Vector3 lhs, Vector3 rhs)
{
return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z;
}
public static bool operator !=(Vector3 lhs, Vector3 rhs)
{
return !(lhs == rhs);
}
///
/// Calculates the magnitude of the provided vector.
///
/// Vector to calculate the magnitude for.
/// Magnitude of the vector.
public static float Magnitude(Vector3 v)
{
return MathEx.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
///
/// Calculates the squared magnitude of the provided vector.
///
/// Vector to calculate the magnitude for.
/// Squared magnitude of the vector.
public static float SqrMagnitude(Vector3 v)
{
return (v.x * v.x + v.y * v.y + v.z * v.z);
}
///
/// Scales one vector by another.
///
/// First three dimensional vector.
/// Second three dimensional vector.
/// One vector scaled by another.
public static Vector3 Scale(Vector3 a, Vector3 b)
{
return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
}
///
/// Returns the cross product between two vectors.
///
/// First three dimensional vector.
/// Second three dimensional vector.
/// Cross product between two vectors.
public static Vector3 Cross(Vector3 lhs, Vector3 rhs)
{
return new Vector3(lhs.y * rhs.z - lhs.z * rhs.y, lhs.z * rhs.x - lhs.x * rhs.z, lhs.x * rhs.y - lhs.y * rhs.x);
}
///
/// Normalizes the provided vector and returns the normalized copy.
///
/// Vector to normalize.
/// Normalized copy of the vector.
public static Vector3 Normalize(Vector3 value)
{
float num = value.Length;
if (num > 9.999999E-06)
return value / num;
return Zero;
}
///
/// Calculates the inner product of the two vectors.
///
/// First three dimensional vector.
/// Second three dimensional vector.
/// Inner product between the two vectors.
public static float Dot(Vector3 lhs, Vector3 rhs)
{
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
}
///
/// Calculates the distance between two points.
///
/// First three dimensional point.
/// Second three dimensional point.
/// Distance between the two points.
public static float Distance(Vector3 a, Vector3 b)
{
Vector3 vector3 = new Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
return MathEx.Sqrt(vector3.x * vector3.x + vector3.y * vector3.y + vector3.z * vector3.z);
}
///
/// Scales the components of the vector by specified scale factors.
///
/// Scale factors to multiply components by.
public void Scale(Vector3 scale)
{
x *= scale.x;
y *= scale.y;
z *= scale.z;
}
///
/// Normalizes the vector.
///
public void Normalize()
{
float num = Length;
if (num > 9.999999E-06)
this /= num;
else
this = Zero;
}
///
/// Calculates two vectors orthonormal to the first vector.
///
/// Normalized vector to calculate orthonormal vectors for.
/// First orthonormal vector.
/// Second orthonormal vector.
public static void OrthogonalComplement(Vector3 x, out Vector3 y, out Vector3 z)
{
if (MathEx.Abs(x.x) > MathEx.Abs(x.y))
y = new Vector3(-x.z, 0, x.x);
else
y = new Vector3(0, x.z, -x.y);
z = Cross(x, y);
Orthonormalize(ref x, ref y, ref z);
}
///
/// Performs Gram-Schmidt orthonormalization on the specified basis, making all the vectors
/// normal and orthogonal to each other.
///
/// First vector to orthogonalize.
/// Second vector to orthogonalize.
/// Third vector to orthogonalize.
public static void Orthonormalize(ref Vector3 x, ref Vector3 y, ref Vector3 z)
{
x.Normalize();
float dot0 = Vector3.Dot(x, y);
y -= dot0 * x;
y.Normalize();
float dot1 = Vector3.Dot(y, z);
dot0 = Vector3.Dot(x, z);
z -= dot0 * x + dot1 * y;
z.Normalize();
}
///
/// Returns the maximum of all the vector components as a new vector.
///
/// First vector.
/// Second vector.
/// Vector consisting of maximum components of the first and second vector.
public static Vector3 Max(Vector3 a, Vector3 b)
{
return new Vector3(MathEx.Max(a.x, b.x), MathEx.Max(a.y, b.y), MathEx.Max(a.z, b.z));
}
///
/// Returns the minimum of all the vector components as a new vector.
///
/// First vector.
/// Second vector.
/// Vector consisting of minimum components of the first and second vector.
public static Vector3 Min(Vector3 a, Vector3 b)
{
return new Vector3(MathEx.Min(a.x, b.x), MathEx.Min(a.y, b.y), MathEx.Min(a.z, b.z));
}
///
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode() << 2 ^ z.GetHashCode() >> 2;
}
///
public override bool Equals(object other)
{
if (!(other is Vector3))
return false;
Vector3 vec = (Vector3)other;
if (x.Equals(vec.x) && y.Equals(vec.y) && z.Equals(vec.z))
return true;
return false;
}
///
public override string ToString()
{
return "(" + x + ", " + y + ", " + z + ")";
}
}
/** @} */
}