/*
Vector.cpp
Written by Matthew Fisher

The Vec3 struct represents a 3-dimensional (x, y, z) real ordered triplet.  It is used constantly everywhere.
The Vec4 struct represents a 4-dimensional (x, y, z, w) real ordered triplet.  It is used mostly for matrix multiplication.

Most of the Vec3 and Vec4 functions and overloaded operators are self-explanitory and are not commented.
*/

#ifndef __SPACEVECTOR_CPP
#define __SPACEVECTOR_CPP

#include "Vector.h"

Vec3::Vec3()
{

}

Vec3::Vec3(float _x, float _y, float _z)
{
    x = _x;
    y = _y;
    z = _z;
}

Vec3::Vec3(const Vec3 &V)
{
    x = V.x;
    y = V.y;
    z = V.z;
}

Vec3::Vec3(const RGBColor &c)
{
    x = c.r / 255.0f;
    y = c.g / 255.0f;
    z = c.b / 255.0f;
}

__forceinline Vec3& Vec3::operator = (const Vec3 &V)
{
    x = V.x;
    y = V.y;
    z = V.z;
    return *this;
}

__forceinline void Vec3::StdRandomVector()
{
    x = float(rand()) / RAND_MAX * 2.0f - 1.0f;
    y = float(rand()) / RAND_MAX * 2.0f - 1.0f;
    z = float(rand()) / RAND_MAX * 2.0f - 1.0f;
}

__forceinline void Vec3::StdRandomNormal()
{
    StdRandomVector();
    Normalize();
}

__forceinline float Vec3::Length()
{
    return sqrtf(x*x+y*y+z*z);
}

__forceinline float Vec3::LengthSq()
{
    return x*x+y*y+z*z;
}

__forceinline void Vec3::Normalize()
{
    float Len = Length();
    //MyAssert(Len != 0.0f);
    x /= Len;
    y /= Len;
    z /= Len;
}

__forceinline Vec3::operator D3DXVECTOR3() const
{
    D3DXVECTOR3 V(x, y, z);
    return V;
}

__forceinline void Vec3Cross(Vec3 &Target, const Vec3 &Left, const Vec3 &Right)
{
    Vec3 Temp;
    Temp.x = Left.y * Right.z - Left.z * Right.y;
    Temp.y = Left.z * Right.x - Left.x * Right.z;
    Temp.z = Left.x * Right.y - Left.y * Right.x;
    Target = Temp;
}

__forceinline void Vec3TriNormal(Vec3 &Target, const Vec3 &V1, const Vec3 &V2, const Vec3 &V3)
{
    Vec3 Diff1 = V2 - V1;
    Vec3 Diff2 = V3 - V1;
    Vec3Cross(Target, Diff1, Diff2);
    Target.Normalize();
}

__forceinline float Vec3Dot(const Vec3 &Left, const Vec3 &Right)
{
    return (Left.x * Right.x + Left.y * Right.y + Left.z * Right.z);
}

__forceinline void Vec3Lerp(Vec3 &Target, const Vec3 &Left, const Vec3 &Right, float s)
{
    Target = Left + s * (Right - Left);
}

__forceinline void Vec3Maximize(Vec3 &Target, const Vec3 &Left, const Vec3 &Right)
{
    Vec3 Target2 = Right;
    if(Left.x > Right.x) Target2.x = Left.x;
    if(Left.y > Right.y) Target2.y = Left.y;
    if(Left.z > Right.z) Target2.z = Left.z;
    Target = Target2;
}

__forceinline void Vec3Minimize(Vec3 &Target, const Vec3 &Left, const Vec3 &Right)
{
    Vec3 Target2 = Right;
    if(Left.x < Right.x) Target2.x = Left.x;
    if(Left.y < Right.y) Target2.y = Left.y;
    if(Left.z < Right.z) Target2.z = Left.z;
    Target = Target2;
}

__forceinline Vec3 operator * (const Vec3 &Left, float Right)
{
    Vec3 Return;
    Return.x = Left.x * Right;
    Return.y = Left.y * Right;
    Return.z = Left.z * Right;
    return Return;
}

__forceinline Vec3 operator * (float Right, const Vec3 &Left)
{
    Vec3 Return;
    Return.x = Left.x * Right;
    Return.y = Left.y * Right;
    Return.z = Left.z * Right;
    return Return;
}

__forceinline Vec3 operator / (const Vec3 &Left, float Right)
{
    Vec3 Return;
    Return.x = Left.x / Right;
    Return.y = Left.y / Right;
    Return.z = Left.z / Right;
    return Return;
}

__forceinline Vec3 operator + (const Vec3 &Left, const Vec3 &Right)
{
    Vec3 Return;
    Return.x = Left.x + Right.x;
    Return.y = Left.y + Right.y;
    Return.z = Left.z + Right.z;
    return Return;
}

__forceinline Vec3 operator - (const Vec3 &Left, const Vec3 &Right)
{
    Vec3 Return;
    Return.x = Left.x - Right.x;
    Return.y = Left.y - Right.y;
    Return.z = Left.z - Right.z;
    return Return;
}

__forceinline Vec3& Vec3::operator *= (float Right)
{
    x *= Right;
    y *= Right;
    z *= Right;
    return *this;
}

__forceinline Vec3& Vec3::operator /= (float Right)
{
    x /= Right;
    y /= Right;
    z /= Right;
    return *this;
}

__forceinline Vec3& Vec3::operator += (const Vec3 &Right)
{
    x += Right.x;
    y += Right.y;
    z += Right.z;
    return *this;
}

__forceinline Vec3& Vec3::operator -= (const Vec3 &Right)
{
    x -= Right.x;
    y -= Right.y;
    z -= Right.z;
    return *this;
}

Vec3 Vec3::ComponentSquare()
{
    //return Vec3(x*x, y*y, z*z);
    return Vec3(fabsf(x), fabsf(y), fabsf(z));
}

__forceinline Vec3 operator - (const Vec3 &V)
{
    Vec3 Result;
    Result.x = -V.x;
    Result.y = -V.y;
    Result.z = -V.z;
    return Result;
}

Vec4::Vec4()
{

}

Vec4::Vec4(float _x, float _y, float _z, float _w)
{
    x = _x;
    y = _y;
    z = _z;
    w = _w;
}

Vec4::Vec4(const Vec4 &V)
{
    x = V.x;
    y = V.y;
    z = V.z;
    w = V.w;
}

Vec4& Vec4::operator = (const Vec4 &V)
{
    x = V.x;
    y = V.y;
    z = V.z;
    w = V.w;
    return *this;
}

float Vec4::Length()
{
    return sqrtf(x*x+y*y+z*z+w*w);
}

float Vec4::LengthSq()
{
    return x*x+y*y+z*z+w*w;
}

void Vec4::Normalize()
{
    float Len = Length();
    x /= Len;
    y /= Len;
    z /= Len;
    w /= Len;
}

float Vec4Dot(const Vec4 &Left, const Vec4 &Right)
{
    return (Left.x * Right.x + Left.y * Right.y + Left.z * Right.z + Left.w * Right.w);
}

void Vec4Lerp(Vec4 &Target, const Vec4 &Left, const Vec4 &Right, float s)
{
    Target = Left + s * (Right - Left);
}

void Vec4Maximize(Vec4 &Target, const Vec4 &Left, const Vec4 &Right)
{
    Target = Right;
    if(Left.x > Right.x) Target.x = Left.x;
    if(Left.y > Right.y) Target.y = Left.y;
    if(Left.z > Right.z) Target.z = Left.z;
    if(Left.w > Right.w) Target.w = Left.w;
}

void Vec4Minimize(Vec4 &Target, const Vec4 &Left, const Vec4 &Right)
{
    Target = Right;
    if(Left.x < Right.x) Target.x = Left.x;
    if(Left.y < Right.y) Target.y = Left.y;
    if(Left.z < Right.z) Target.z = Left.z;
    if(Left.w < Right.w) Target.w = Left.w;
}

Vec4 operator * (const Vec4 &Left, float Right)
{
    Vec4 Return;
    Return.x = Left.x * Right;
    Return.y = Left.y * Right;
    Return.z = Left.z * Right;
    Return.w = Left.w * Right;
    return Return;
}

Vec4 operator * (float Right, const Vec4 &Left)
{
    Vec4 Return;
    Return.x = Left.x * Right;
    Return.y = Left.y * Right;
    Return.z = Left.z * Right;
    Return.w = Left.w * Right;
    return Return;
}

Vec4 operator / (const Vec4 &Left, float Right)
{
    Vec4 Return;
    Return.x = Left.x / Right;
    Return.y = Left.y / Right;
    Return.z = Left.z / Right;
    Return.w = Left.w / Right;
    return Return;
}

Vec4 operator + (const Vec4 &Left, const Vec4 &Right)
{
    Vec4 Return;
    Return.x = Left.x + Right.x;
    Return.y = Left.y + Right.y;
    Return.z = Left.z + Right.z;
    Return.w = Left.w + Right.w;
    return Return;
}

Vec4 operator - (const Vec4 &Left, const Vec4 &Right)
{
    Vec4 Return;
    Return.x = Left.x - Right.x;
    Return.y = Left.y - Right.y;
    Return.z = Left.z - Right.z;
    Return.w = Left.w - Right.w;
    return Return;
}

Vec4& Vec4::operator *= (float Right)
{
    x *= Right;
    y *= Right;
    z *= Right;
    w *= Right;
    return *this;
}

Vec4& Vec4::operator /= (float Right)
{
    x /= Right;
    y /= Right;
    z /= Right;
    w /= Right;
    return *this;
}

Vec4& Vec4::operator += (const Vec4 &Right)
{
    x += Right.x;
    y += Right.y;
    z += Right.z;
    w += Right.w;
    return *this;
}

Vec4& Vec4::operator -= (const Vec4 &Right)
{
    x -= Right.x;
    y -= Right.y;
    z -= Right.z;
    w -= Right.w;
    return *this;
}

__forceinline Vec4 operator - (const Vec4 &V)
{
    Vec4 Result;
    Result.x = -V.x;
    Result.y = -V.y;
    Result.z = -V.z;
    Result.w = -V.w;
    return Result;
}

istream& operator >> (istream &is, Vec3 &v)
{
    is >> v.x >> v.y >> v.z;
    return is;
}

ostream& operator << (ostream &os, const Vec3 &v)
{
    os << v.x << ' ' << v.y << ' ' << v.z;
    return os;
}

ostream& operator << (ostream &os, const Vec4 &v)
{
    os << v.x << ' ' << v.y << ' ' << v.z << ' ' << v.w;
    return os;
}

float AngleBetween(const Vec3 &Left, const Vec3 &Right)
{
    //the cosine of the angle between two vectors is the dot product of the two vectors after normalization
    Vec3 V1 = Left, V2 = Right;
    V1.Normalize();
    V2.Normalize();
    float Dot = Vec3Dot(V1, V2);
    if(fabsf(Dot) >= 1.0f) Dot = 0.999f;
    return acosf(Dot);
}

#endif

Top