struct Vector3f
{
float x, y, z;
static inline Vector3f Make(float i_fX, float i_fY, float i_fZ) { Vector3f tmp; tmp.x = i_fX; tmp.y = i_fY; tmp.z = i_fZ; return tmp; }
inline Vector3f& operator = (const Vector3f& v) { x = v.x; y = v.y; z = v.z; return *this; }
inline Vector3f& operator += (const Vector3f& v) { x += v.x; y += v.y; z += v.z; return *this; }
inline Vector3f& operator -= (const Vector3f& v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
inline Vector3f& operator *= (const float f ) { x *= f; y *= f; z *= f; return *this; }
inline Vector3f& operator *= (const Vector3f& v) { *this = Cross(*this, v); return *this; }
inline Vector3f& operator /= (const float f ) { x /= f; y /= f; z /= f; return *this; }
inline friend const Vector3f operator + (const Vector3f& v) { return v; }
inline friend const Vector3f operator - (const Vector3f& v) { return v*(-1.0f); }
inline friend const Vector3f operator + (const Vector3f& v, const Vector3f& u) { return Vector3f::Make(v.x+u.x, v.y+u.y, v.z+u.z); }
inline friend const Vector3f operator - (const Vector3f& v, const Vector3f& u) { return Vector3f::Make(v.x-u.x, v.y-u.y, v.z-u.z); }
inline friend const Vector3f operator * (const Vector3f& v, const Vector3f& u) { return Cross(v,u); }
inline friend float operator % (const Vector3f& v, const Vector3f& u) { return Dot(v,u); }
inline friend const Vector3f operator * (const float f, const Vector3f& v) { return Vector3f::Make(v.x*f, v.y*f, v.z*f); }
inline friend const Vector3f operator * (const Vector3f& v, const float f) { return Vector3f::Make(v.x*f, v.y*f, v.z*f); }
inline friend const Vector3f operator / (const Vector3f& v, const float f) { return Vector3f::Make(v.x/f, v.y/f, v.z/f); }
inline friend bool operator == (const Vector3f& v, const Vector3f& u ) { return ((v.x==u.x)&&(v.y==u.y)&&(v.z==u.z)); }
inline friend bool operator != (const Vector3f& v, const Vector3f& u ) { return !((v.x==u.x)&&(v.y==u.y)&&(v.z==u.z)); }
inline Vector3f& Set(const float xx, const float yy, const float zz) { x = xx; y = yy; z = zz; return *this; }
inline Vector3f& Set() { x = y = z = 0.0f; return *this; }
inline Vector3f& Reset() { x = y = z = 0.0f; return *this; }
inline float Abs() const { return static_cast<float>(sqrt(x*x+y*y+z*z)); }
inline float Abs2() const { return (x*x+y*y+z*z); }
inline float Gamma() const { return 1.0f / static_cast<float>(sqrt( 1.0f - x*x - y*y - z*z )); }
inline float UGamma() const { return static_cast<float>(sqrt( 1.0 + x*x + y*y + z*z )); }
inline float Dist(const Vector3f& p2) const { Vector3f p = (*this)-p2; return(static_cast<float>(sqrt(p.x*p.x + p.y*p.y + p.z*p.z))); }
inline float Dist2(const Vector3f& p2) const { Vector3f p = (*this)-p2; return(static_cast<float>((p.x*p.x + p.y*p.y + p.z*p.z))); }
inline Vector3f& Normalize(float radius = 1.0f) { float l = radius / static_cast<float>(sqrt(x*x + y*y + z*z)); (*this)*=l; return *this; }
inline const Vector3f v2uv() const { float f = 1.0f / static_cast<float>(sqrt( 1.0f - x*x - y*y - z*z )); return Vector3f::Make( f*x, f*y, f*z ); }
inline const Vector3f uv2v() const { float f = 1.0f / static_cast<float>(sqrt( 1.0f + x*x + y*y + z*z )); return Vector3f::Make( f*x, f*y, f*z ); }
inline friend const Vector3f Cross(const Vector3f& a, const Vector3f& b) { return Vector3f::Make( 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 friend const Vector3f Diagonal(const Vector3f& v, const Vector3f& u) { return Vector3f::Make(v.x*u.x, v.y*u.y, v.z*u.z); }
inline friend float Dot(const Vector3f& a, const Vector3f& b) { return ( a.x*b.x + a.y*b.y + a.z*b.z ); }
inline friend float Abs(const Vector3f& v) { return v.Abs(); }
inline friend float Abs2(const Vector3f& v) { return v.Abs2(); }
inline friend float Dist(const Vector3f& v, const Vector3f& u) { return v.Dist(u); }
inline friend float Dist2(const Vector3f& v, const Vector3f& u) { return v.Dist2(u); }
inline Vector3f& ToVersors() { x = (x!=0.0f) ? 1.0f : 0.0f; y = (y!=0.0f) ? 1.0f : 0.0f; z = (z!=0.0f) ? 1.0f : 0.0f; return *this; }
inline Vector3f& InvertVersors() { x = 1.0f - x; y = 1.0f - y; z = 1.0f - z; return *this; }
inline const Vector3f ProjectionOnPlane(const Vector3f& PLn, const Vector3f& PLV0) const { float sb, sn, sd; Vector3f B; sn = -Dot( PLn, (*this - PLV0)); sd = Dot(PLn, PLn); sb = sn / sd; B = (*this) + sb * PLn; return B; }
inline void SetLength(float l) { float len = static_cast<float>(sqrt(x*x + y*y + z*z)); x *= l/len; y *= l/len; z *= l/len; }
inline Vector3f& AllAbs() { x = fabsf(x); y = fabsf(y); z = fabsf(z); return *this; }
};