#pragma once #include namespace q { template struct vec3 { union { struct { T x, y, z; }; struct { T r, g, b; }; }; vec3() = default; vec3(T s): x(s), y(s), z(s) {} vec3(T _x, T _y, T _z) : x(_x), y(_y), z(_z) {} void normalize() { T m = length(*this); (*this).x /= m; (*this).y /= m; (*this).z /= m; } }; template vec3 operator*(const vec3& a, const vec3& b) { return vec3(a.x * b.x, a.y * b.y, a.z * b.z); } template vec3 operator/(const vec3& a, const vec3& b) { return vec3(a.x / b.x, a.y / b.y, a.z / b.z); } template vec3 operator+(const vec3 a, const vec3& b) { return vec3(a.x + b.x, a.y + b.y, a.z + b.z); } template vec3 operator-(const vec3 a, const vec3& b) { return vec3(a.x - b.x, a.y - b.y, a.z - b.z); } template T dot(const vec3& a, const vec3& b) { return a.x * b.x + a.y * b.y + a.z * b.z; } template T length(const vec3& a) { return std::sqrt(dot(a, a)); } template vec3 cross(const vec3& a, const vec3& b) { return vec3( a.y * b.z - a.z * b.y, \ a.z * b.x - a.x * b.z, \ a.x * b.y - a.y * b.x ); } template std::ostream& operator<<(std::ostream& o, const vec3& v) { return o << "{ " << v.x << ", " << v.y << ", " << v.z << " }"; } typedef vec3 vec3i; typedef vec3 vec3f; typedef vec3 vec3d; };