// This code is in the public domain -- castanyo@yahoo.es #pragma once #include "nvcore/nvcore.h" namespace nv { class Vector2 { public: typedef Vector2 const & Arg; Vector2(); explicit Vector2(float f); Vector2(float x, float y); Vector2(Vector2::Arg v); //template explicit Vector2(const T & v) : x(v.x), y(v.y) {} //template operator T() const { return T(x, y); } const Vector2 & operator=(Vector2::Arg v); const float * ptr() const; void set(float x, float y); Vector2 operator-() const; void operator+=(Vector2::Arg v); void operator-=(Vector2::Arg v); void operator*=(float s); void operator*=(Vector2::Arg v); union { struct { float x, y; }; float component[2]; }; }; class Vector3 { public: typedef Vector3 const & Arg; Vector3(); explicit Vector3(float x); //explicit Vector3(int x) : x(float(x)), y(float(x)), z(float(x)) {} Vector3(float x, float y, float z); Vector3(Vector2::Arg v, float z); Vector3(Vector3::Arg v); //template explicit Vector3(const T & v) : x(v.x), y(v.y), z(v.z) {} //template operator T() const { return T(x, y, z); } const Vector3 & operator=(Vector3::Arg v); Vector2 xy() const; const float * ptr() const; void set(float x, float y, float z); Vector3 operator-() const; void operator+=(Vector3::Arg v); void operator-=(Vector3::Arg v); void operator*=(float s); void operator/=(float s); void operator*=(Vector3::Arg v); void operator/=(Vector3::Arg v); union { struct { float x, y, z; }; float component[3]; }; }; class Vector4 { public: typedef Vector4 const & Arg; Vector4(); explicit Vector4(float x); Vector4(float x, float y, float z, float w); Vector4(Vector2::Arg v, float z, float w); Vector4(Vector2::Arg v, Vector2::Arg u); Vector4(Vector3::Arg v, float w); Vector4(Vector4::Arg v); // Vector4(const Quaternion & v); //template explicit Vector4(const T & v) : x(v.x), y(v.y), z(v.z), w(v.w) {} //template operator T() const { return T(x, y, z, w); } const Vector4 & operator=(Vector4::Arg v); Vector2 xy() const; Vector2 zw() const; Vector3 xyz() const; const float * ptr() const; void set(float x, float y, float z, float w); Vector4 operator-() const; void operator+=(Vector4::Arg v); void operator-=(Vector4::Arg v); void operator*=(float s); void operator/=(float s); void operator*=(Vector4::Arg v); void operator/=(Vector4::Arg v); union { struct { float x, y, z, w; }; float component[4]; }; }; } // nv namespace // If we had these functions, they would be ambiguous, the compiler would not know which one to pick: //template Vector2 to(const T & v) { return Vector2(v.x, v.y); } //template Vector3 to(const T & v) { return Vector3(v.x, v.y, v.z); } //template Vector4 to(const T & v) { return Vector4(v.x, v.y, v.z, v.z); } // We could use a cast operator so that we could infer the expected type, but that doesn't work the same way in all compilers and produces horrible error messages. // Instead we simply have explicit casts: template T to(const nv::Vector2 & v) { NV_COMPILER_CHECK(sizeof(T) == sizeof(nv::Vector2)); return T(v.x, v.y); } template T to(const nv::Vector3 & v) { NV_COMPILER_CHECK(sizeof(T) == sizeof(nv::Vector3)); return T(v.x, v.y, v.z); } template T to(const nv::Vector4 & v) { NV_COMPILER_CHECK(sizeof(T) == sizeof(nv::Vector4)); return T(v.x, v.y, v.z, v.w); }