#pragma once #include #include struct vec2 { float x, y; }; // Constructors void ?{}( vec2 & v, float x, float y) { v.[x, y] = [x, y]; } void ?{}(vec2& vec, zero_t) with (vec) { x = y = 0; } void ?{}(vec2& vec, float val) with (vec) { x = y = val; } void ?{}(vec2& vec, vec2& other) with (vec) { [x,y] = other.[x,y]; } // Assignment void ?=?(vec2& vec, const vec2& other) with (vec) { [x,y] = other.[x,y]; } // Primitive mathematical operations // Subtraction vec2 ?-?(const vec2& u, const vec2& v) { return [u.x - v.x, u.y - v.y]; } vec2& ?-=?(vec2& u, const vec2& v) { u = u - v; return u; } vec2 -?(const vec2& v) with (v) { return [-x, -y]; } // Addition vec2 ?+?(const vec2& u, const vec2& v) { return [u.x + v.x, u.y + v.y]; } vec2& ?+=?(vec2& u, const vec2& v) { u = u + v; return u; } // Scalar Multiplication vec2 ?*?(const vec2& v, float scalar) with (v) { return [x * scalar, y * scalar]; } vec2& ?*=?(vec2& v, float scalar) with (v) { v = v * scalar; return v; } vec2 ?*?(float scalar, const vec2& v) { return v * scalar; } // Scalar Division vec2 ?/?(const vec2& v, float scalar) with (v) { return [x / scalar, y / scalar]; } vec2& ?/=?(vec2& v, float scalar) with (v) { v = v / scalar; return v; } // Relational Operators bool ?==?(const vec2& u, const vec2& v) with (u) { return x == v.x && y == v.y; } bool ?!=?(const vec2& u, const vec2& v) { return !(u == v); } // Printing the vector (ostream) forall( dtype ostype | ostream( ostype ) ) { ostype & ?|?( ostype & os, const vec2& v) with (v) { if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) ); fmt( os, "<%g,%g>", x, y); return os; } void ?|?( ostype & os, const vec2& v ) { (ostype &)(os | v); ends( os ); } } /* //---------------------- Geometric Functions ---------------------- */ /* // These functions implement the Geometric Functions section of GLSL for 2D vectors*/ static inline float dot(const vec2& u, const vec2& v) { return u.x * v.x + u.y * v.y; } static inline float length(const vec2& v) { return sqrt(dot(v, v)); } static inline float distance(const vec2& v1, const vec2& v2) { return length(v1 - v2); } static inline vec2 normalize(const vec2& v) { return v / sqrt(dot(v, v)); } // Project vector u onto vector v static inline vec2 project(const vec2& u, const vec2& v) { vec2 v_norm = normalize(v); return v_norm * dot(u, v_norm); } // Reflect incident vector v with respect to surface with normal n static inline vec2 reflect(const vec2& v, const vec2& n) { return v - 2 * project(v, n); } // Refract incident vector v with respect to surface with normal n // eta is the ratio of indices of refraction between starting material and // entering material (i.e., from air to water, eta = 1/1.33) static inline vec2 refract(const vec2& v, const vec2& n, float eta) { float dotValue = dot(n, v); float k = 1 - eta * eta * (1 - dotValue * dotValue); if (k < 0) { return 0; } return eta * v - (eta * dotValue + sqrt(k)) * n; } // Used to render perturbed surfaces by ensuring that a perturbed normal // is pointing in the same direction as the geometric normal of the // surface. // n is the perturbed vector that we want to align // i is the incident vector // ng is the geometric normal of the surface static inline vec2 faceforward(const vec2& n, const vec2& i, float ng) { return dot(n, i) < 0 ? ng : -ng; }