Unravel Engine C++ Reference
Loading...
Searching...
No Matches
math.h
Go to the documentation of this file.
1#pragma once
2
3#include "bbox.h"
4#include "bsphere.h"
5#include "frustum.h"
6#include "math_types.h"
7#include "plane.h"
8#include "transform.hpp"
9#include <functional>
10
11namespace math
12{
13
14static inline std::vector<float> log_space(std::size_t start, std::size_t end, std::size_t count)
15{
16 std::vector<float> result;
17 result.reserve(count);
18 for(std::size_t i = 0; i <= count; ++i)
19 {
20 float f = start * glm::pow(float(end) / float(start), float(i) / float(count));
21 result.push_back(f);
22 }
23
24 return result;
25}
26
27// inline bool is_negative_float(const float& A)
28// {
29// return ((*(const std::uint32_t*)&A) >= std::uint32_t(0x80000000)); // Detects sign bit.
30// }
31
32// template<typename T>
33// inline T square(const T& t)
34// {
35// return t * t;
36// }
37
43// inline bool compute_projected_sphere_shaft(float light_x,
44// float light_z,
45// float radius,
46// const transform& proj,
47// const vec3& axis,
48// float axis_sign,
49// std::int32_t& in_out_min_x,
50// std::int32_t& in_out_max_x)
51// {
52// auto view_x = float(in_out_min_x);
53// auto view_size_x = float(in_out_max_x - in_out_min_x);
54
55// // Vertical planes: T = <Nx, 0, Nz, 0>
56// float discriminant = (square(light_x) - square(radius) + square(light_z)) * square(light_z);
57// if(discriminant >= 0)
58// {
59// float sqrt_discriminant = glm::sqrt(discriminant);
60// float inv_light_square = 1.0f / (square(light_x) + square(light_z));
61
62// float Nxa = (radius * light_x - sqrt_discriminant) * inv_light_square;
63// float Nxb = (radius * light_x + sqrt_discriminant) * inv_light_square;
64// float Nza = (radius - Nxa * light_x) / light_z;
65// float Nzb = (radius - Nxb * light_x) / light_z;
66// float Pza = light_z - radius * Nza;
67// float Pzb = light_z - radius * Nzb;
68
69// // Tangent a
70// if(Pza > 0)
71// {
72// float Pxa = -Pza * Nza / Nxa;
73// vec4 P = proj * vec4(axis.x * Pxa, axis.y * Pxa, Pza, 1);
74// float X = (dot(vec3(P), axis) / P.w + 1.0f * axis_sign) / 2.0f * axis_sign;
75// if(is_negative_float(Nxa) ^ is_negative_float(axis_sign))
76// {
77// in_out_max_x = glm::min<std::int32_t>(std::int32_t(glm::ceil(view_size_x * X + view_x)), in_out_max_x);
78// }
79// else
80// {
81// in_out_min_x = glm::max<std::int32_t>(std::int32_t(glm::floor(view_size_x * X + view_x)), in_out_min_x);
82// }
83// }
84
85// // Tangent b
86// if(Pzb > 0)
87// {
88// float Pxb = -Pzb * Nzb / Nxb;
89// vec4 P = proj * vec4(axis.x * Pxb, axis.y * Pxb, Pzb, 1);
90// float X = (dot(vec3(P), axis) / P.w + 1.0f * axis_sign) / 2.0f * axis_sign;
91// if(is_negative_float(Nxb) ^ is_negative_float(axis_sign))
92// {
93// in_out_max_x = glm::min<std::int32_t>(std::int32_t(glm::ceil(view_size_x * X + view_x)), in_out_max_x);
94// }
95// else
96// {
97// in_out_min_x = glm::max<std::int32_t>(std::int32_t(glm::floor(view_size_x * X + view_x)), in_out_min_x);
98// }
99// }
100// }
101
102// return in_out_min_x <= in_out_max_x;
103// }
104
105// //@return 0: not visible, 1:use scissor rect, 2: no scissor rect needed
106// inline std::uint32_t compute_projected_sphere_rect(std::int32_t& left,
107// std::int32_t& right,
108// std::int32_t& top,
109// std::int32_t& bottom,
110// const vec3& sphere_center,
111// float radius,
112// const math::vec3& view_origin,
113// const transform& view,
114// const transform& proj)
115// {
116// // Calculate a screen rectangle for the sphere's radius.
117// if(math::length2(sphere_center - view_origin) > math::square(radius))
118// {
119// math::vec3 lv = view.transform_coord(sphere_center);
120
121// if(!compute_projected_sphere_shaft(lv.x, lv.z, radius, proj, vec3(1.0f, 0.0f, 0.0f), 1.0f, left, right))
122// {
123// return 0;
124// }
125
126// if(!compute_projected_sphere_shaft(lv.y, lv.z, radius, proj, vec3(0.0f, 1.0f, 0.0f), -1.0f, top, bottom))
127// {
128// return 0;
129// }
130
131// return 1;
132// }
133// else
134// {
135// return 2;
136// }
137// }
138
139inline bool is_negative_float(const float& A)
140{
141 union {
142 float f;
143 std::uint32_t i;
144 } u;
145 u.f = A;
146 return (u.i & 0x80000000) != 0; // Detects sign bit.
147}
148
149template<typename T>
150inline T square(const T& t)
151{
152 return t * t;
153}
154
160inline bool compute_projected_sphere_shaft(float light_x,
161 float light_z,
162 float radius,
163 const glm::mat4& proj,
164 const glm::vec3& axis,
165 float axis_sign,
166 std::int32_t& in_out_min_x,
167 std::int32_t& in_out_max_x)
168{
169 auto view_x = float(in_out_min_x);
170 auto view_size_x = float(in_out_max_x - in_out_min_x);
171
172 // Vertical planes: T = <Nx, 0, Nz, 0>
173 float discriminant = (square(light_x) - square(radius) + square(light_z)) * square(light_z);
174 if(discriminant >= 0)
175 {
176 float sqrt_discriminant = glm::sqrt(discriminant);
177 float inv_light_square = 1.0f / (square(light_x) + square(light_z));
178
179 float Nxa = (radius * light_x - sqrt_discriminant) * inv_light_square;
180 float Nxb = (radius * light_x + sqrt_discriminant) * inv_light_square;
181 float Nza = (radius - Nxa * light_x) / light_z;
182 float Nzb = (radius - Nxb * light_x) / light_z;
183 float Pza = light_z - radius * Nza;
184 float Pzb = light_z - radius * Nzb;
185
186 // Tangent a
187 if(Pza > 0)
188 {
189 float Pxa = -Pza * Nza / Nxa;
190 glm::vec4 P = proj * glm::vec4(axis.x * Pxa, axis.y * Pxa, Pza, 1);
191 float X = (glm::dot(glm::vec3(P), axis) / P.w + 1.0f * axis_sign) / 2.0f * axis_sign;
192 if(is_negative_float(Nxa) ^ is_negative_float(axis_sign))
193 {
194 in_out_max_x = std::min<std::int32_t>(std::int32_t(glm::ceil(view_size_x * X + view_x)), in_out_max_x);
195 }
196 else
197 {
198 in_out_min_x = std::max<std::int32_t>(std::int32_t(glm::floor(view_size_x * X + view_x)), in_out_min_x);
199 }
200 }
201
202 // Tangent b
203 if(Pzb > 0)
204 {
205 float Pxb = -Pzb * Nzb / Nxb;
206 glm::vec4 P = proj * glm::vec4(axis.x * Pxb, axis.y * Pxb, Pzb, 1);
207 float X = (glm::dot(glm::vec3(P), axis) / P.w + 1.0f * axis_sign) / 2.0f * axis_sign;
208 if(is_negative_float(Nxb) ^ is_negative_float(axis_sign))
209 {
210 in_out_max_x = std::min<std::int32_t>(std::int32_t(glm::ceil(view_size_x * X + view_x)), in_out_max_x);
211 }
212 else
213 {
214 in_out_min_x = std::max<std::int32_t>(std::int32_t(glm::floor(view_size_x * X + view_x)), in_out_min_x);
215 }
216 }
217 }
218
219 return in_out_min_x <= in_out_max_x;
220}
221
222//@return 0: not visible, 1:use scissor rect, 2: no scissor rect needed
223inline std::uint32_t compute_projected_sphere_rect(std::int32_t& left,
224 std::int32_t& right,
225 std::int32_t& top,
226 std::int32_t& bottom,
227 const glm::vec3& sphere_center,
228 float radius,
229 const glm::vec3& view_origin,
230 const glm::mat4& view,
231 const glm::mat4& proj)
232{
233 // Calculate a screen rectangle for the sphere's radius.
234 if(glm::length2(sphere_center - view_origin) > square(radius))
235 {
236 glm::vec3 lv = glm::vec3(view * glm::vec4(sphere_center, 1.0f));
237
238 if(!compute_projected_sphere_shaft(lv.x, lv.z, radius, proj, glm::vec3(1.0f, 0.0f, 0.0f), 1.0f, left, right))
239 {
240 return 0;
241 }
242
243 if(!compute_projected_sphere_shaft(lv.y, lv.z, radius, proj, glm::vec3(0.0f, 1.0f, 0.0f), -1.0f, top, bottom))
244 {
245 return 0;
246 }
247
248 return 1;
249 }
250 else
251 {
252 return 2;
253 }
254}
255
256inline float halton(std::uint32_t Index, std::uint32_t Base)
257{
258 float Result = 0.0f;
259 float InvBase = 1.0f / Base;
260 float Fraction = InvBase;
261 while(Index > 0)
262 {
263 Result += (Index % Base) * Fraction;
264 Index /= Base;
265 Fraction *= InvBase;
266 }
267 return Result;
268}
269
270inline std::uint32_t power_of_n_round_down(std::uint32_t val, std::uint32_t n)
271{
272 std::uint32_t currentVal = n;
273 std::uint32_t iter = 1;
274 while(currentVal < val)
275 {
276 currentVal *= n;
277 ++iter;
278 }
279
280 return iter;
281}
282
283struct color
284{
285
286
287 static color white()
288 {
289 static color c(1.0f, 1.0f, 1.0f, 1.0f);
290 return c;
291 }
292 static color black()
293 {
294 static color c(0.0f, 0.0f, 0.0f, 1.0f);
295 return c;
296 }
298 {
299 static color c(0.0f, 0.0f, 0.0f, 0.0f);
300 return c;
301 }
302 static color red()
303 {
304 static color c(1.0f, 0.0f, 0.0f, 1.0f);
305 return c;
306 }
307 static color purple()
308 {
309 static color c(1.0f, 0.0f, 1.0f, 1.0f);
310 return c;
311 }
312
318 static color random(const char* seed)
319 {
320 return random(std::string(seed));
321 }
322
328 static color random(const std::string& seed)
329 {
330 // Use std::hash to convert string to numeric seed
331 std::hash<std::string> hasher;
332 std::size_t hash_value = hasher(seed);
333
334 // Simple linear congruential generator using the hash as seed
335 auto lcg = [](std::size_t& state) -> float {
336 state = (state * 1103515245u + 12345u) & 0x7fffffffu;
337 return static_cast<float>(state) / static_cast<float>(0x7fffffffu);
338 };
339
340 std::size_t state = hash_value;
341
342 // Generate hue in full range [0, 1)
343 float hue = lcg(state);
344
345 // Generate saturation with bias toward higher values for more vibrant colors
346 float saturation = 0.4f + 0.6f * lcg(state);
347
348 // Generate value/brightness with bias toward higher values for better visibility
349 float value = 0.6f + 0.4f * lcg(state);
350
351 return hsv(hue, saturation, value, 1.0f);
352 }
353
354 vec4 value{};
355
357 {
358 value.x = value.y = value.z = value.w = 0.0f;
359 }
360 color(int r, int g, int b, int a = 255)
361 {
362 float sc = 1.0f / 255.0f;
363 value.x = (float)r * sc;
364 value.y = (float)g * sc;
365 value.z = (float)b * sc;
366 value.w = (float)a * sc;
367 }
368 color(std::uint32_t rgba)
369 {
370 float sc = 1.0f / 255.0f;
371 value.x = (float)(rgba & 0xFF) * sc;
372 value.y = (float)((rgba >> 8) & 0xFF) * sc;
373 value.z = (float)((rgba >> 16) & 0xFF) * sc;
374 value.w = (float)(rgba >> 24) * sc;
375 }
376 color(float r, float g, float b, float a = 1.0f)
377 {
378 value.x = r;
379 value.y = g;
380 value.z = b;
381 value.w = a;
382 }
383 color(const vec4& col)
384 {
385 value = col;
386 }
387 inline operator std::uint32_t() const
388 {
389 return float4_to_u32(value);
390 }
391 inline operator vec4() const
392 {
393 return value;
394 }
395
396 inline void set_hsv(float h, float s, float v, float a = 1.0f)
397 {
398 hsv_to_rgb(h, s, v, value.x, value.y, value.z);
399 value.w = a;
400 }
401
402 static color hsv(float h, float s, float v, float a = 1.0f)
403 {
404 float r, g, b;
405 hsv_to_rgb(h, s, v, r, g, b);
406 return {r, g, b, a};
407 }
408
409 static vec4 u32_to_float4(std::uint32_t in)
410 {
411 float s = 1.0f / 255.0f;
412 return vec4((in & 0xFF) * s, ((in >> 8) & 0xFF) * s, ((in >> 16) & 0xFF) * s, (in >> 24) * s);
413 }
414
415 static std::uint32_t float4_to_u32(const vec4& in)
416 {
417 std::uint32_t out;
418 out = ((std::uint32_t)(saturate(in.x) * 255.0f));
419 out |= ((std::uint32_t)(saturate(in.y) * 255.0f)) << 8;
420 out |= ((std::uint32_t)(saturate(in.z) * 255.0f)) << 16;
421 out |= ((std::uint32_t)(saturate(in.w) * 255.0f)) << 24;
422 return out;
423 }
424
425 // Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]),
426 // from Foley & van Dam p592
427 // Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
428 static void rgb_to_hsv(float r, float g, float b, float& out_h, float& out_s, float& out_v)
429 {
430 float K = 0.f;
431 if(g < b)
432 {
433 const float tmp = g;
434 g = b;
435 b = tmp;
436 K = -1.f;
437 }
438 if(r < g)
439 {
440 const float tmp = r;
441 r = g;
442 g = tmp;
443 K = -2.f / 6.f - K;
444 }
445
446 const float chroma = r - (g < b ? g : b);
447 out_h = glm::abs(K + (g - b) / (6.f * chroma + 1e-20f));
448 out_s = chroma / (r + 1e-20f);
449 out_v = r;
450 }
451
452 // Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]),
453 // from Foley & van Dam p593
454 // also http://en.wikipedia.org/wiki/HSL_and_HSV
455 static void hsv_to_rgb(float h, float s, float v, float& out_r, float& out_g, float& out_b)
456 {
457 if(s == 0.0f)
458 {
459 // gray
460 out_r = out_g = out_b = v;
461 return;
462 }
463
464 h = glm::mod(h, 1.0f) / (60.0f / 360.0f);
465 auto i = int(h);
466 float f = h - float(i);
467 float p = v * (1.0f - s);
468 float q = v * (1.0f - s * f);
469 float t = v * (1.0f - s * (1.0f - f));
470
471 switch(i)
472 {
473 case 0:
474 out_r = v;
475 out_g = t;
476 out_b = p;
477 break;
478 case 1:
479 out_r = q;
480 out_g = v;
481 out_b = p;
482 break;
483 case 2:
484 out_r = p;
485 out_g = v;
486 out_b = t;
487 break;
488 case 3:
489 out_r = p;
490 out_g = q;
491 out_b = v;
492 break;
493 case 4:
494 out_r = t;
495 out_g = p;
496 out_b = v;
497 break;
498 case 5:
499 default:
500 out_r = v;
501 out_g = p;
502 out_b = q;
503 break;
504 }
505 }
506};
507} // namespace math
entt::handle b
entt::handle a
int count(const generator_t &generator) noexcept
Counts the number of steps left in the generator.
Definition utils.hpp:70
Definition bbox.cpp:5
std::uint32_t compute_projected_sphere_rect(std::int32_t &left, std::int32_t &right, std::int32_t &top, std::int32_t &bottom, const glm::vec3 &sphere_center, float radius, const glm::vec3 &view_origin, const glm::mat4 &view, const glm::mat4 &proj)
Definition math.h:223
std::uint32_t power_of_n_round_down(std::uint32_t val, std::uint32_t n)
Definition math.h:270
T square(const T &t)
Definition math.h:150
float halton(std::uint32_t Index, std::uint32_t Base)
Definition math.h:256
bool compute_projected_sphere_shaft(float light_x, float light_z, float radius, const glm::mat4 &proj, const glm::vec3 &axis, float axis_sign, std::int32_t &in_out_min_x, std::int32_t &in_out_max_x)
Definition math.h:160
bool is_negative_float(const float &A)
Definition math.h:139
auto start(seq_action action, const seq_scope_policy &scope_policy, hpp::source_location location) -> seq_id_t
Starts a new action.
Definition seq.cpp:8
static color red()
Definition math.h:302
color(const vec4 &col)
Definition math.h:383
static vec4 u32_to_float4(std::uint32_t in)
Definition math.h:409
void set_hsv(float h, float s, float v, float a=1.0f)
Definition math.h:396
static color random(const std::string &seed)
Generates a consistent random color based on a string seed.
Definition math.h:328
static color white()
Definition math.h:287
color(std::uint32_t rgba)
Definition math.h:368
vec4 value
Definition math.h:354
static color black()
Definition math.h:292
static void rgb_to_hsv(float r, float g, float b, float &out_h, float &out_s, float &out_v)
Definition math.h:428
static std::uint32_t float4_to_u32(const vec4 &in)
Definition math.h:415
static color purple()
Definition math.h:307
static color random(const char *seed)
Generates a consistent random color based on a string seed.
Definition math.h:318
static color transparent()
Definition math.h:297
static void hsv_to_rgb(float h, float s, float v, float &out_r, float &out_g, float &out_b)
Definition math.h:455
static color hsv(float h, float s, float v, float a=1.0f)
Definition math.h:402
color(int r, int g, int b, int a=255)
Definition math.h:360
color(float r, float g, float b, float a=1.0f)
Definition math.h:376