General Purpose library for Freestanding C++ and POSIX systems
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

351 righe
5.7 KiB

  1. #pragma once
  2. #include "gp_config.hpp"
  3. #include "gp/algorithm/min_max.hpp"
  4. #include "gp/algorithm/repeat.hpp"
  5. #include "gp/math/integer_math.hpp"
  6. #if !defined(NO_FP_MATH)
  7. # include "gp/math/fp_math.hpp"
  8. #endif
  9. #include "gp/math/q_math.hpp"
  10. namespace gp {
  11. template<typename T>
  12. T lerp(T input, T low, T high) {
  13. return low + (high - low) * input;
  14. }
  15. template<typename T>
  16. T lextrap(T input, T low, T high) {
  17. return (input - low) / (high - low);
  18. }
  19. template<typename T, size_t fixed_passes = 16>
  20. T fixed_sqrt(T value) {
  21. gp_config::assertion(value >= 0, "trying to compute square root of negative number");
  22. if(value == 0) return 0;
  23. T ret = value / 2;
  24. T tmp;
  25. gp::repeat(fixed_passes, [&](){
  26. tmp = ret;
  27. ret = (value / tmp + tmp) / 2;
  28. });
  29. return ret;
  30. }
  31. template<typename T, size_t cap_passes = 16>
  32. T epsilon_sqrt(T value) {
  33. gp_config::assertion(value >= 0, "trying to compute square root of negative number");
  34. if(value == 0) return 0;
  35. T ret = value / 2;
  36. T tmp;
  37. constexpr T epsilon = gp_config::rendering::epsilon;
  38. size_t cnt = 0;
  39. while(
  40. !(
  41. (ret+epsilon)*ret > value
  42. && (ret-epsilon)*ret < value
  43. )
  44. && cnt < cap_passes
  45. ){
  46. tmp = ret;
  47. ret = (value / tmp + tmp) / 2;
  48. ++cnt;
  49. };
  50. return ret;
  51. }
  52. template<typename T, size_t cap_passes = 16>
  53. T stable_sqrt(T value) {
  54. gp_config::assertion(value >= 0, "trying to compute square root of negative number");
  55. if(value == 0) return 0;
  56. T ret = value / 2;
  57. T tmp;
  58. while(ret != tmp){
  59. tmp = ret;
  60. ret = (value / tmp + tmp) / 2;
  61. };
  62. return ret;
  63. }
  64. template<typename T = gp_config::rendering::default_type>
  65. struct vec2_g {
  66. T x;
  67. T y;
  68. vec2_g()
  69. : x{}
  70. , y{}
  71. {}
  72. vec2_g(
  73. T _x,
  74. T _y
  75. )
  76. : x{_x}
  77. , y{_y}
  78. {}
  79. vec2_g operator/(vec2_g rhs) {
  80. return {
  81. x / rhs.x,
  82. y / rhs.y
  83. };
  84. }
  85. vec2_g operator*(vec2_g rhs) {
  86. return {
  87. x * rhs.x,
  88. y * rhs.y
  89. };
  90. }
  91. vec2_g operator+(vec2_g oth) {
  92. return {x+oth.x, y+oth.y};
  93. }
  94. vec2_g operator-(vec2_g oth) {
  95. return {x-oth.x, y-oth.y};
  96. }
  97. vec2_g normalize() {
  98. T ilen = fast_isqrt(x*x+y*y);
  99. return {x*ilen, y*ilen};
  100. }
  101. T length() {
  102. return fixed_sqrt(x*x+y*y);
  103. }
  104. };
  105. template<typename T = gp_config::rendering::default_type>
  106. struct vec3_g {
  107. T x;
  108. T y;
  109. T z;
  110. T& r(){
  111. return x;
  112. }
  113. T& g(){
  114. return y;
  115. }
  116. T& b(){
  117. return z;
  118. }
  119. vec3_g()
  120. : x{}
  121. , y{}
  122. , z{}
  123. {}
  124. vec3_g(
  125. T _x,
  126. T _y,
  127. T _z
  128. )
  129. : x{_x}
  130. , y{_y}
  131. , z{_z}
  132. {}
  133. vec3_g(vec2_g<T> left, T right)
  134. : x{left.x}
  135. , y{left.y}
  136. , z{right}
  137. {}
  138. vec3_g(T left, vec2_g<T> right)
  139. : x{left}
  140. , y{right.x}
  141. , z{right.y}
  142. {}
  143. vec3_g operator/(vec3_g rhs) {
  144. return {
  145. x / rhs.x,
  146. y / rhs.y,
  147. z / rhs.z
  148. };
  149. }
  150. vec3_g operator*(vec3_g rhs) {
  151. return {
  152. x * rhs.x,
  153. y * rhs.y,
  154. z * rhs.z
  155. };
  156. }
  157. vec3_g operator+(vec3_g oth) {
  158. return {x+oth.x, y+oth.y, z+oth.z};
  159. }
  160. vec3_g operator-(vec3_g oth) {
  161. return {x-oth.x, y-oth.y, z-oth.z};
  162. }
  163. vec3_g normalize() {
  164. T ilen = fast_isqrt(x*x+y*y+z*z);
  165. return {x*ilen, y*ilen, z*ilen};
  166. }
  167. T length() {
  168. return fixed_sqrt(x*x+y*y+z*z);
  169. }
  170. };
  171. template<typename T = gp_config::rendering::default_type>
  172. struct vec4_g {
  173. T x;
  174. T y;
  175. T z;
  176. T w;
  177. T& r(){
  178. return x;
  179. }
  180. T& g(){
  181. return y;
  182. }
  183. T& b(){
  184. return z;
  185. }
  186. T& a(){
  187. return w;
  188. }
  189. vec4_g()
  190. : x{}
  191. , y{}
  192. , z{}
  193. , w{}
  194. {}
  195. vec4_g(
  196. T _x,
  197. T _y,
  198. T _z,
  199. T _w
  200. )
  201. : x{_x}
  202. , y{_y}
  203. , z{_z}
  204. , w{_w}
  205. {}
  206. vec4_g(T left, vec3_g<> right)
  207. : x{left}
  208. , y{right.x}
  209. , z{right.y}
  210. , w{right.z}
  211. {}
  212. vec4_g(vec3_g<> left, T right)
  213. : x{left.x}
  214. , y{left.y}
  215. , z{left.z}
  216. , w{right}
  217. {}
  218. vec4_g operator/(vec4_g rhs) {
  219. return {
  220. x / rhs.x,
  221. y / rhs.y,
  222. z / rhs.z,
  223. w / rhs.w
  224. };
  225. }
  226. vec4_g operator*(vec4_g rhs) {
  227. return {
  228. x * rhs.x,
  229. y * rhs.y,
  230. z * rhs.z,
  231. w * rhs.w
  232. };
  233. }
  234. vec4_g operator+(vec4_g oth) {
  235. return {x+oth.x, y+oth.y, z+oth.z, w+oth.w};
  236. }
  237. vec4_g operator-(vec4_g oth) {
  238. return {x-oth.x, y-oth.y, z-oth.w, z-oth.w};
  239. }
  240. vec4_g normalize() {
  241. T ilen = fast_isqrt(x*x+y*y+z*z+w*w);
  242. return {x*ilen, y*ilen, z*ilen, w*ilen};
  243. }
  244. T length() {
  245. return fixed_sqrt(x*x+y*y+z*z+w*w);
  246. }
  247. };
  248. template<typename T>
  249. auto sphere_sdf(vec3_g<T> center, T radius) {
  250. return [=](vec3_g<T> position) -> T const {
  251. auto p = position - center;
  252. return p.length() - radius;
  253. };
  254. }
  255. template<typename T, typename lhs, typename rhs>
  256. auto union_sdf(lhs _l, rhs _r) {
  257. return [=](vec3_g<T> position) -> T const {
  258. return gp::min(_l(position), _r(position));
  259. };
  260. }
  261. template<typename T, typename lhs, typename rhs>
  262. auto intersect_sdf(lhs _l, rhs _r) {
  263. return [=](vec3_g<T> position) -> T const {
  264. return gp::max(_l(position), _r(position));
  265. };
  266. }
  267. template<typename T, typename lhs, typename rhs>
  268. auto difference_sdf(lhs _l, rhs _r) {
  269. return [=](vec3_g<T> position) -> T const {
  270. return gp::max(_l(position), -_r(position));
  271. };
  272. }
  273. template<typename T>
  274. vec2_g<T> operator*(vec2_g<T> p, T v) {
  275. return {p.x*v, p.y*v};
  276. }
  277. template<typename T>
  278. vec3_g<T> operator*(vec3_g<T> p, T v) {
  279. return {p.x*v, p.y*v, p.z*v};
  280. }
  281. template<typename T>
  282. vec4_g<T> operator*(vec4_g<T> p, T v) {
  283. return {p.x*v, p.y*v, p.z*v, p.w*v};
  284. }
  285. template<typename T>
  286. vec2_g<T> operator*(T v, vec2_g<T> p) {
  287. return p*v;
  288. }
  289. template<typename T>
  290. vec3_g<T> operator*(T v, vec3_g<T> p) {
  291. return p*v;
  292. }
  293. template<typename T>
  294. vec4_g<T> operator*(T v, vec4_g<T> p) {
  295. return p*v;
  296. }
  297. }
  298. static_assert(sizeof(gp::vec3_g<int>) == sizeof(int)*3, "vec3_g has strange alignment");
  299. static_assert(sizeof(gp::vec4_g<int>) == sizeof(int)*4, "vec4_g has strange alignment");