|
|
- #pragma once
- #include "gp_config.hpp"
- #include "gp/math/integer_math.hpp"
- #include "gp/math/q_math.hpp"
- #if !defined(NO_FP_MATH)
- # include "gp/math/fp_math.hpp"
- #endif
- #include "gp/algorithm/repeat.hpp"
- #include "gp/algorithm/min_max.hpp"
-
- namespace gp {
- template<typename T>
- T lerp(T input, T low, T high) {
- return low + (high - low) * input;
- }
- template<typename T>
- T lextrap(T input, T low, T high) {
- return (input - low) / (high - low);
- }
-
- template<typename T, size_t fixed_passes = 16>
- T fixed_sqrt(T value) {
- gp_config::assertion(value >= 0, "trying to compute square root of negative number");
- if(value == 0) return 0;
- T ret = value / 2;
- T tmp;
-
- gp::repeat(fixed_passes, [&](){
- tmp = ret;
- ret = (value / tmp + tmp) / 2;
- });
-
- return ret;
- }
-
- template<typename T, size_t cap_passes = 16>
- T epsilon_sqrt(T value) {
- gp_config::assertion(value >= 0, "trying to compute square root of negative number");
- if(value == 0) return 0;
- T ret = value / 2;
- T tmp;
- constexpr T epsilon = gp_config::rendering::epsilon;
- size_t cnt = 0;
- while(
- !(
- (ret+epsilon)*ret > value
- && (ret-epsilon)*ret < value
- )
- && cnt < cap_passes
- ){
- tmp = ret;
- ret = (value / tmp + tmp) / 2;
- ++cnt;
- };
-
- return ret;
- }
-
- template<typename T, size_t cap_passes = 16>
- T stable_sqrt(T value) {
- gp_config::assertion(value >= 0, "trying to compute square root of negative number");
- if(value == 0) return 0;
- T ret = value / 2;
- T tmp;
- while(ret != tmp){
- tmp = ret;
- ret = (value / tmp + tmp) / 2;
- };
-
- return ret;
- }
-
- template<typename T = gp_config::rendering::default_type>
- struct vec2_g {
- T x;
- T y;
-
- vec2_g()
- : x{}
- , y{}
- {}
-
- vec2_g(
- T _x,
- T _y
- )
- : x{_x}
- , y{_y}
- {}
-
- vec2_g operator/(vec2_g rhs) {
- return {
- x / rhs.x,
- y / rhs.y
- };
- }
-
- vec2_g operator*(vec2_g rhs) {
- return {
- x * rhs.x,
- y * rhs.y
- };
- }
-
- vec2_g operator+(vec2_g oth) {
- return {x+oth.x, y+oth.y};
- }
-
- vec2_g operator-(vec2_g oth) {
- return {x-oth.x, y-oth.y};
- }
-
- vec2_g normalize() {
- T ilen = fast_isqrt(x*x+y*y);
- return {x*ilen, y*ilen};
- }
-
- T length() {
- return fixed_sqrt(x*x+y*y);
- }
- };
-
- template<typename T = gp_config::rendering::default_type>
- struct vec3_g {
- T x;
- T y;
- T z;
-
- T& r(){
- return x;
- }
- T& g(){
- return y;
- }
- T& b(){
- return z;
- }
-
- vec3_g()
- : x{}
- , y{}
- , z{}
- {}
-
- vec3_g(
- T _x,
- T _y,
- T _z
- )
- : x{_x}
- , y{_y}
- , z{_z}
- {}
-
- vec3_g(vec2_g<T> left, T right)
- : x{left.x}
- , y{left.y}
- , z{right}
- {}
-
- vec3_g(T left, vec2_g<T> right)
- : x{left}
- , y{right.x}
- , z{right.y}
- {}
-
- vec3_g operator/(vec3_g rhs) {
- return {
- x / rhs.x,
- y / rhs.y,
- z / rhs.z
- };
- }
-
- vec3_g operator*(vec3_g rhs) {
- return {
- x * rhs.x,
- y * rhs.y,
- z * rhs.z
- };
- }
-
- vec3_g operator+(vec3_g oth) {
- return {x+oth.x, y+oth.y, z+oth.z};
- }
-
- vec3_g operator-(vec3_g oth) {
- return {x-oth.x, y-oth.y, z-oth.z};
- }
-
- vec3_g normalize() {
- T ilen = fast_isqrt(x*x+y*y+z*z);
- return {x*ilen, y*ilen, z*ilen};
- }
-
- T length() {
- return fixed_sqrt(x*x+y*y+z*z);
- }
- };
-
- template<typename T = gp_config::rendering::default_type>
- struct vec4_g {
- T x;
- T y;
- T z;
- T w;
-
- T& r(){
- return x;
- }
- T& g(){
- return y;
- }
- T& b(){
- return z;
- }
- T& a(){
- return w;
- }
-
- vec4_g()
- : x{}
- , y{}
- , z{}
- , w{}
- {}
-
- vec4_g(
- T _x,
- T _y,
- T _z,
- T _w
- )
- : x{_x}
- , y{_y}
- , z{_z}
- , w{_w}
- {}
-
- vec4_g(T left, vec3_g<> right)
- : x{left}
- , y{right.x}
- , z{right.y}
- , w{right.z}
- {}
-
- vec4_g(vec3_g<> left, T right)
- : x{left.x}
- , y{left.y}
- , z{left.z}
- , w{right}
- {}
-
- vec4_g operator/(vec4_g rhs) {
- return {
- x / rhs.x,
- y / rhs.y,
- z / rhs.z,
- w / rhs.w
- };
- }
-
- vec4_g operator*(vec4_g rhs) {
- return {
- x * rhs.x,
- y * rhs.y,
- z * rhs.z,
- w * rhs.w
- };
- }
-
- vec4_g operator+(vec4_g oth) {
- return {x+oth.x, y+oth.y, z+oth.z, w+oth.w};
- }
-
- vec4_g operator-(vec4_g oth) {
- return {x-oth.x, y-oth.y, z-oth.w, z-oth.w};
- }
-
- vec4_g normalize() {
- T ilen = fast_isqrt(x*x+y*y+z*z+w*w);
- return {x*ilen, y*ilen, z*ilen, w*ilen};
- }
-
- T length() {
- return fixed_sqrt(x*x+y*y+z*z+w*w);
- }
- };
-
- template<typename T>
- auto sphere_sdf(vec3_g<T> center, T radius) {
- return [=](vec3_g<T> position) -> T const {
- auto p = position - center;
- return p.length() - radius;
- };
- }
-
- template<typename T, typename lhs, typename rhs>
- auto union_sdf(lhs _l, rhs _r) {
- return [=](vec3_g<T> position) -> T const {
- return gp::min(_l(position), _r(position));
- };
- }
-
- template<typename T, typename lhs, typename rhs>
- auto intersect_sdf(lhs _l, rhs _r) {
- return [=](vec3_g<T> position) -> T const {
- return gp::max(_l(position), _r(position));
- };
- }
-
- template<typename T, typename lhs, typename rhs>
- auto difference_sdf(lhs _l, rhs _r) {
- return [=](vec3_g<T> position) -> T const {
- return gp::max(_l(position), -_r(position));
- };
- }
-
- template<typename T>
- vec2_g<T> operator*(vec2_g<T> p, T v) {
- return {p.x*v, p.y*v};
- }
-
- template<typename T>
- vec3_g<T> operator*(vec3_g<T> p, T v) {
- return {p.x*v, p.y*v, p.z*v};
- }
-
- template<typename T>
- vec4_g<T> operator*(vec4_g<T> p, T v) {
- return {p.x*v, p.y*v, p.z*v, p.w*v};
- }
-
- template<typename T>
- vec2_g<T> operator*(T v, vec2_g<T> p) {
- return p*v;
- }
-
- template<typename T>
- vec3_g<T> operator*(T v, vec3_g<T> p) {
- return p*v;
- }
-
- template<typename T>
- vec4_g<T> operator*(T v, vec4_g<T> p) {
- return p*v;
- }
- }
-
- static_assert(sizeof(gp::vec3_g<int>) == sizeof(int)*3, "vec3_g has strange alignment");
- static_assert(sizeof(gp::vec4_g<int>) == sizeof(int)*4, "vec4_g has strange alignment");
|