#pragma once #include /* #include */ struct vec2_f { float x, y; }; static inline { // Constructors void ?{}(vec2_f& v, float x, float y) { v.[x, y] = [x, y]; } void ?{}(vec2_f& vec, zero_t) with (vec) { x = y = 0; } void ?{}(vec2_f& vec, float val) with (vec) { x = y = val; } void ?{}(vec2_f& vec, const vec2_f& other) with (vec) { [x,y] = other.[x,y]; } // Assignment void ?=?(vec2_f& vec, const vec2_f& other) with (vec) { [x,y] = other.[x,y]; } void ?=?(vec2_f& vec, zero_t) with (vec) { [x,y] = [0,0]; } // Primitive mathematical operations // Subtraction vec2_f ?-?(const vec2_f& u, const vec2_f& v) { return [u.x - v.x, u.y - v.y]; } vec2_f& ?-=?(vec2_f& u, const vec2_f& v) { u = u - v; return u; } vec2_f -?(const vec2_f& v) with (v) { return [-x, -y]; } // Addition vec2_f ?+?(const vec2_f& u, const vec2_f& v) { return [u.x + v.x, u.y + v.y]; } vec2_f& ?+=?(vec2_f& u, const vec2_f& v) { u = u + v; return u; } // Scalar Multiplication vec2_f ?*?(const vec2_f& v, float scalar) with (v) { return [x * scalar, y * scalar]; } vec2_f ?*?(float scalar, const vec2_f& v) { return v * scalar; } vec2_f& ?*=?(vec2_f& v, float scalar) with (v) { v = v * scalar; return v; } // Scalar Division vec2_f ?/?(const vec2_f& v, float scalar) with (v) { return [x / scalar, y / scalar]; } vec2_f& ?/=?(vec2_f& v, float scalar) with (v) { v = v / scalar; return v; } // Relational Operators bool ?==?(const vec2_f& u, const vec2_f& v) with (u) { return x == v.x && y == v.y; } bool ?!=?(const vec2_f& u, const vec2_f& v) { return !(u == v); } /* // Printing the vector (ostream) */ /* forall( dtype ostype | ostream( ostype ) ) { */ /* ostype & ?|?( ostype & os, const vec2_f& v) with (v) { */ /* if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) ); */ /* fmt( os, "<%g,%g>", x, y); */ /* return os; */ /* } */ /* void ?|?( ostype & os, const vec2_f& v ) { */ /* (ostype &)(os | v); ends( os ); */ /* } */ /* } */ //---------------------- Geometric Functions ---------------------- // These functions implement the Geometric Functions section of GLSL for 2D vectors float dot(const vec2_f& u, const vec2_f& v) { return u.x * v.x + u.y * v.y; } float length(const vec2_f& v) { return sqrt(dot(v, v)); } float length_squared(const vec2_f& v) { return dot(v, v); } float distance(const vec2_f& v1, const vec2_f& v2) { return length(v1 - v2); } vec2_f normalize(const vec2_f& v) { return v / sqrt(dot(v, v)); } // Project vector u onto vector v vec2_f project(const vec2_f& u, const vec2_f& v) { vec2_f v_norm = normalize(v); return v_norm * dot(u, v_norm); } // Reflect incident vector v with respect to surface with normal n vec2_f reflect(const vec2_f& v, const vec2_f& 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) vec2_f refract(const vec2_f& v, const vec2_f& n, float eta) { float dotValue = dot(n, v); float k = 1 - eta \ 2 * (1 - dotValue \ 2); if (k < 0) { return 0; } return eta * v - (eta * dotValue + sqrt(k)) * n; } // Given a perturbed normal and a geometric normal, // flip the perturbed normal if the geometric normal is pointing away // from the observer. // n is the perturbed vector that we want to align // i is the incident vector // ng is the geometric normal of the surface vec2_f faceforward(const vec2_f& n, const vec2_f& i, const vec2_f& ng) { return dot(ng, i) < 0 ? n : -n; } }