154 lines
4.2 KiB
C++
154 lines
4.2 KiB
C++
|
#pragma once
|
||
|
|
||
|
#include <cstddef>
|
||
|
#include <math.h>
|
||
|
|
||
|
#define do_op(o, r, i) \
|
||
|
inline void operator o##= (const r & rhs) { for(unsigned n=0; n<(i); n++) c[n] o##= rhs.c[n]; } \
|
||
|
inline void operator o##= (T d) { for(unsigned n=0; n<(i); n++) c[n] o##= d; } \
|
||
|
inline r operator o (const r & rhs) const { r tmp(*this); tmp o##= rhs; return tmp; } \
|
||
|
inline r operator o (T d) const { r tmp(*this); tmp o##= d; return tmp; }
|
||
|
|
||
|
#define do_ops(c, i) \
|
||
|
do_op(*, c, i); \
|
||
|
do_op(/, c, i); \
|
||
|
do_op(+, c, i); \
|
||
|
do_op(-, c, i);
|
||
|
|
||
|
template <std::size_t n, std::floating_point T = float>
|
||
|
struct vec {
|
||
|
T c[n];
|
||
|
};
|
||
|
|
||
|
template <std::size_t n, std::floating_point T>
|
||
|
vec<n, T> operator*(const T lhs, const vec<n, T>& rhs)
|
||
|
{ return rhs * lhs; }
|
||
|
|
||
|
template<std::floating_point T>
|
||
|
struct vec<2, T> {
|
||
|
union {
|
||
|
T c[2];
|
||
|
struct {
|
||
|
T x, y;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
vec(T x, T y) : c{x,y} {}
|
||
|
vec(T f) : vec(f,f) {}
|
||
|
vec() : vec(0,0) {}
|
||
|
|
||
|
do_ops(vec, 2);
|
||
|
|
||
|
inline vec<2,T> operator-(void) const { return {-x, -y}; }
|
||
|
|
||
|
inline T operator^(const vec<2,T>& rhs) const
|
||
|
{ return x * rhs.x + y * rhs.y; }
|
||
|
|
||
|
/* Return normalised (unit) vector. */
|
||
|
inline vec<2,T> norm() const
|
||
|
{ return *this / len(); }
|
||
|
|
||
|
inline T len() const
|
||
|
{ return sqrtf(x*x + y*y); }
|
||
|
|
||
|
inline T lensquared() const
|
||
|
{ return x*x + y*y; }
|
||
|
|
||
|
/* Return vector reflected around `n'. Expects `this' and `n' to be unit. */
|
||
|
inline vec<2,T> ref(const vec<2,T>& n) const
|
||
|
{ return n * ((*this ^ n) * 2) - *this;}
|
||
|
|
||
|
inline vec<2,T> refract(const vec<2,T>& n, T ior_ratio) const
|
||
|
{
|
||
|
return n * sqrtf(1 - powf(ior_ratio, 2) * (1 - powf(*this ^ n, 2))) + (*this - n * (*this ^ n)) * ior_ratio;
|
||
|
}
|
||
|
|
||
|
inline vec<2,T> refract(const vec<2,T>& n, T ior_incident, T ior_refract) const
|
||
|
{ return refract(n, ior_incident / ior_refract); }
|
||
|
|
||
|
inline vec<2,T> clamp(const vec<2,T>& from, const vec<2,T>& to) const
|
||
|
{ return { fmin(fmax(x, from.x), to.x),
|
||
|
fmin(fmax(y, from.y), to.y) }; }
|
||
|
|
||
|
inline vec<2,T> exp() const
|
||
|
{ return { ::exp(x), ::exp(y) }; }
|
||
|
|
||
|
inline vec<2,T> htan(T exposure = 0) const
|
||
|
{
|
||
|
return { powf((tanh(x + exposure) + 1) / 2, 2.2), powf((tanh(y + exposure) + 1) / 2, 2.2) };
|
||
|
return { tanh(x + exposure), tanh(y + exposure) };
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<std::floating_point T>
|
||
|
struct vec<3, T> {
|
||
|
union {
|
||
|
T c[3];
|
||
|
struct {
|
||
|
T x, y, z;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
vec(T x, T y, T z) : c{x,y,z} {}
|
||
|
vec(T f) : vec(f,f,f) {}
|
||
|
vec() : vec(0,0,0) {}
|
||
|
|
||
|
do_ops(vec, 3);
|
||
|
|
||
|
inline vec<3,T> operator-(void) const { return {-x, -y, -z}; }
|
||
|
|
||
|
inline T operator^(const vec& rhs) const
|
||
|
{ return x * rhs.x + y * rhs.y + z * rhs.z; }
|
||
|
|
||
|
/* Return normalised (unit) vector. */
|
||
|
inline vec<3,T> norm() const
|
||
|
{ return *this / len(); }
|
||
|
|
||
|
inline T len() const
|
||
|
{ return sqrtf(x*x + y*y + z*z); }
|
||
|
|
||
|
inline T lensquared() const
|
||
|
{ return x*x + y*y + z*z; }
|
||
|
|
||
|
/* Return vec<3,T>tor reflected around `n'. Expects `this' and `n' to be unit. */
|
||
|
inline vec<3,T> ref(const vec<3,T>& n) const
|
||
|
{ return n * ((*this ^ n) * 2) - *this;}
|
||
|
|
||
|
/* Cross product. */
|
||
|
inline vec<3,T> cross(const vec<3,T>& b) const
|
||
|
{ return { y*b.z - z*b.y,
|
||
|
x*b.z - z*b.x,
|
||
|
x*b.y - y*b.x }; }
|
||
|
|
||
|
inline vec<3,T> refract(const vec<3,T>& n, T ior_ratio) const
|
||
|
{
|
||
|
return n * sqrtf(1 - powf(ior_ratio, 2) * (1 - powf(*this ^ n, 2))) + (*this - n * (*this ^ n)) * ior_ratio;
|
||
|
}
|
||
|
|
||
|
inline vec<3,T> refract(const vec<3,T>& n, T ior_incident, T ior_refract) const
|
||
|
{ return refract(n, ior_incident / ior_refract); }
|
||
|
|
||
|
inline vec<3,T> clamp(const vec<3,T>& from, const vec<3,T>& to) const
|
||
|
{ return { fmin(fmax(x, from.x), to.x),
|
||
|
fmin(fmax(y, from.y), to.y),
|
||
|
fmin(fmax(z, from.z), to.z) }; }
|
||
|
|
||
|
inline vec<3,T> exp() const
|
||
|
{ return { ::exp(x), ::exp(y), ::exp(z) }; }
|
||
|
|
||
|
inline vec<3,T> htan(T exposure = 0) const
|
||
|
{
|
||
|
return { powf((tanh(x + exposure) + 1) / 2, 2.2), powf((tanh(y + exposure) + 1) / 2, 2.2), powf((tanh(z + exposure) + 1) / 2, 2.2) };
|
||
|
return { tanh(x + exposure), tanh(y + exposure), tanh(z + exposure) };
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#undef do_ops
|
||
|
#undef do_op
|
||
|
|
||
|
#define V3_FMT "v3(%.2f, %.2f, %.2f)"
|
||
|
#define V3_ARG(v) (v).x, (v).y, (v).z
|
||
|
|
||
|
#define V2_FMT "v2(%.2f, %.2f)"
|
||
|
#define V2_ARG(v) (v).x, (v).y
|