#pragma once
#include "Common.h"
//
// 三维向量类
//
//
class Vector3
{
public:
float x, y, z;
public:
inline Vector3() :x(0.0f), y(0.0f), z(0.0f)
{}
inline Vector3(float fx, float fy, float fz) : x(fx), y(fy), z(fz)
{}
inline Vector3(float fs) : x(fs), y(fs), z(fs)
{}
inline Vector3(const Vector3& v) : x(v.x), y(v.y), z(v.z)
{}
inline void Set(const float fx, const float fy, const float fz)
{
x = fx;
y = fy;
z = fz;
}
inline void Set(const float *v)
{
assert(v != NULL);
x = *v;
y = *(v + 1);
z = *(v + 2);
}
inline void CopyTo(float *dst)
{
assert(NULL != dst);
*dst = x;
*(dst + 1) = y;
*(dst + 2) = z;
}
inline bool HasNaN()
{
return (IsNaN(x) || IsNaN(y) || IsNaN(z));
}
inline Vector3& operator=(const Vector3& rhv)
{
x = rhv.x;
y = rhv.y;
z = rhv.z;
return *this;
}
inline bool operator==(const Vector3& rhv)
{
return (Equal(x, rhv.x) && Equal(y, rhv.y) && Equal(z, rhv.z));
}
inline bool operator==(const Vector3& rhv) const
{
return (Equal(x, rhv.x) && Equal(y, rhv.y) && Equal(z, rhv.z));
}
inline bool operator!=(const Vector3& rhv)
{
return (!Equal(x, rhv.x) || !Equal(y, rhv.y) || !Equal(z, rhv.z));
}
inline bool operator!=(const Vector3& rhv) const
{
return (!Equal(x, rhv.x) || !Equal(y, rhv.y) || !Equal(z, rhv.z));
}
inline Vector3 operator+(const Vector3& rhv) const
{
return Vector3(
x + rhv.x,
y + rhv.y,
z + rhv.z
);
}
/**
* 加等
*/
inline Vector3 &operator+=(const Vector3& rhv)
{
x += rhv.x;
y += rhv.y;
z += rhv.z;
return *this;
}
inline Vector3 operator-(const Vector3& rhv) const
{
return Vector3(
x - rhv.x,
y - rhv.y,
z - rhv.z
);
}
inline Vector3 operator-() const
{
return Vector3(
-x,
-y,
-z
);
}
/**
* 减等
*/
inline Vector3 &operator-=(const Vector3& rhv)
{
x -= rhv.x;
y -= rhv.y;
z -= rhv.z;
return *this;
}
/**
*向量左乘
*/
inline Vector3 operator*(const Vector3& rhv) const
{
return Vector3(
x * rhv.x,
y * rhv.y,
z * rhv.z
);
}
/**
*标量左乘
*/
inline Vector3 operator*(const float scalar) const
{
return Vector3(
x * scalar,
y * scalar,
z * scalar
);
}
/**
*标量乘等
*/
inline Vector3 &operator*=(const float scalar)
{
x *= scalar;
y *= scalar;
z *= scalar;
return *this;
}
/**
*标量左乘
*/
inline friend Vector3 operator*(const float scalar, const Vector3& rhv)
{
return Vector3(scalar * rhv.x, scalar * rhv.y, scalar * rhv.z);
}
/**
*标量右除
*/
inline Vector3 operator/(const float scalar) const
{
assert(!Equal0(scalar));
float t = 1.0f / scalar;
return Vector3(
x * t,
y * t,
z * t
);
}
/**
*标量左除
*/
inline friend Vector3 operator/(const float scalar, const Vector3& rhv)
{
assert(!Equal0(rhv.x) && !Equal0(rhv.y) && !Equal0(rhv.z));
return Vector3(scalar / rhv.x, scalar / rhv.y, scalar / rhv.z);
}
/**
*返回向量的长度
*/
inline float Length() const
{
return Sqrt(x * x + y * y + z * z);
}
/**
* 自身单位化
*/
inline void Normalize()
{
float l = Sqrt(x * x + y * y + z * z);
if (l < EPSILON)
{
l = EPSILON;
}
float tmp = 1.0f / l;
x *= tmp;
y *= tmp;
z *= tmp;
}
/**
*当前向量与另外一个向量的点积
*/
inline float Dot(const Vector3& rhv) const
{
return x * rhv.x + y * rhv.y + z * rhv.z;
}
/**
*当前向量与另外一个向量的叉积
*/
inline Vector3 Cross(const Vector3& rhv) const
{
return Vector3(
y * rhv.z - z * rhv.y,
z * rhv.x - x * rhv.z,
x * rhv.y - y * rhv.x);
}
/**
* 假设当前向量指向反射平面的正向,即dot(v , normal) > 0
*/
inline Vector3 Reflect(const Vector3& normal) const
{
return Vector3(*this - (2 * (this->Dot(normal)) * normal));
}
friend std::ostream& operator << (std::ostream& os, Vector3& v)
{
os << "Vector3( " << v.x << " , " << v.y << " , " << v.z << ")";
return os;
}
};
/**
*非成员点积函数
*/
inline float Dot(const Vector3& a, const Vector3& b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
/**
*非成员叉积函数
*/
inline Vector3 Cross(const Vector3& a, const Vector3& b)
{
return Vector3(
a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x);
}
/**
*非成员长度函数
*/
inline float Length(const Vector3& v)
{
return v.Length();
}
/**
*非成员距离函数
*/
inline float Distance(const Vector3& a, const Vector3& b)
{
return Length(b - a);
}
/**
*向量线性插值函数,返回 v1 + (v2 - v1) * t
*/
inline Vector3 Lerp(const Vector3& v1, const Vector3& v2, const float t)
{
return v1 + (v2 - v1) * t;
}
/**
* 单位化
*/
inline Vector3 Normalize(const Vector3& v)
{
Vector3 nv = v;
nv.Normalize();
return nv;
}