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 "color.h"
10#include "gradient.h"
11#include <functional>
12
13namespace math
14{
15
16static inline std::vector<float> log_space(std::size_t start, std::size_t end, std::size_t count)
17{
18 std::vector<float> result;
19 result.reserve(count);
20 for(std::size_t i = 0; i <= count; ++i)
21 {
22 float f = start * glm::pow(float(end) / float(start), float(i) / float(count));
23 result.push_back(f);
24 }
25
26 return result;
27}
28
29// inline bool is_negative_float(const float& A)
30// {
31// return ((*(const std::uint32_t*)&A) >= std::uint32_t(0x80000000)); // Detects sign bit.
32// }
33
34// template<typename T>
35// inline T square(const T& t)
36// {
37// return t * t;
38// }
39
45// inline bool compute_projected_sphere_shaft(float light_x,
46// float light_z,
47// float radius,
48// const transform& proj,
49// const vec3& axis,
50// float axis_sign,
51// std::int32_t& in_out_min_x,
52// std::int32_t& in_out_max_x)
53// {
54// auto view_x = float(in_out_min_x);
55// auto view_size_x = float(in_out_max_x - in_out_min_x);
56
57// // Vertical planes: T = <Nx, 0, Nz, 0>
58// float discriminant = (square(light_x) - square(radius) + square(light_z)) * square(light_z);
59// if(discriminant >= 0)
60// {
61// float sqrt_discriminant = glm::sqrt(discriminant);
62// float inv_light_square = 1.0f / (square(light_x) + square(light_z));
63
64// float Nxa = (radius * light_x - sqrt_discriminant) * inv_light_square;
65// float Nxb = (radius * light_x + sqrt_discriminant) * inv_light_square;
66// float Nza = (radius - Nxa * light_x) / light_z;
67// float Nzb = (radius - Nxb * light_x) / light_z;
68// float Pza = light_z - radius * Nza;
69// float Pzb = light_z - radius * Nzb;
70
71// // Tangent a
72// if(Pza > 0)
73// {
74// float Pxa = -Pza * Nza / Nxa;
75// vec4 P = proj * vec4(axis.x * Pxa, axis.y * Pxa, Pza, 1);
76// float X = (dot(vec3(P), axis) / P.w + 1.0f * axis_sign) / 2.0f * axis_sign;
77// if(is_negative_float(Nxa) ^ is_negative_float(axis_sign))
78// {
79// in_out_max_x = glm::min<std::int32_t>(std::int32_t(glm::ceil(view_size_x * X + view_x)), in_out_max_x);
80// }
81// else
82// {
83// in_out_min_x = glm::max<std::int32_t>(std::int32_t(glm::floor(view_size_x * X + view_x)), in_out_min_x);
84// }
85// }
86
87// // Tangent b
88// if(Pzb > 0)
89// {
90// float Pxb = -Pzb * Nzb / Nxb;
91// vec4 P = proj * vec4(axis.x * Pxb, axis.y * Pxb, Pzb, 1);
92// float X = (dot(vec3(P), axis) / P.w + 1.0f * axis_sign) / 2.0f * axis_sign;
93// if(is_negative_float(Nxb) ^ is_negative_float(axis_sign))
94// {
95// in_out_max_x = glm::min<std::int32_t>(std::int32_t(glm::ceil(view_size_x * X + view_x)), in_out_max_x);
96// }
97// else
98// {
99// in_out_min_x = glm::max<std::int32_t>(std::int32_t(glm::floor(view_size_x * X + view_x)), in_out_min_x);
100// }
101// }
102// }
103
104// return in_out_min_x <= in_out_max_x;
105// }
106
107// //@return 0: not visible, 1:use scissor rect, 2: no scissor rect needed
108// inline std::uint32_t compute_projected_sphere_rect(std::int32_t& left,
109// std::int32_t& right,
110// std::int32_t& top,
111// std::int32_t& bottom,
112// const vec3& sphere_center,
113// float radius,
114// const math::vec3& view_origin,
115// const transform& view,
116// const transform& proj)
117// {
118// // Calculate a screen rectangle for the sphere's radius.
119// if(math::length2(sphere_center - view_origin) > math::square(radius))
120// {
121// math::vec3 lv = view.transform_coord(sphere_center);
122
123// if(!compute_projected_sphere_shaft(lv.x, lv.z, radius, proj, vec3(1.0f, 0.0f, 0.0f), 1.0f, left, right))
124// {
125// return 0;
126// }
127
128// if(!compute_projected_sphere_shaft(lv.y, lv.z, radius, proj, vec3(0.0f, 1.0f, 0.0f), -1.0f, top, bottom))
129// {
130// return 0;
131// }
132
133// return 1;
134// }
135// else
136// {
137// return 2;
138// }
139// }
140
141inline bool is_negative_float(const float& A)
142{
143 union {
144 float f;
145 std::uint32_t i;
146 } u;
147 u.f = A;
148 return (u.i & 0x80000000) != 0; // Detects sign bit.
149}
150
151template<typename T>
152inline T square(const T& t)
153{
154 return t * t;
155}
156
162inline bool compute_projected_sphere_shaft(float light_x,
163 float light_z,
164 float radius,
165 const glm::mat4& proj,
166 const glm::vec3& axis,
167 float axis_sign,
168 std::int32_t& in_out_min_x,
169 std::int32_t& in_out_max_x)
170{
171 auto view_x = float(in_out_min_x);
172 auto view_size_x = float(in_out_max_x - in_out_min_x);
173
174 // Vertical planes: T = <Nx, 0, Nz, 0>
175 float discriminant = (square(light_x) - square(radius) + square(light_z)) * square(light_z);
176 if(discriminant >= 0)
177 {
178 float sqrt_discriminant = glm::sqrt(discriminant);
179 float inv_light_square = 1.0f / (square(light_x) + square(light_z));
180
181 float Nxa = (radius * light_x - sqrt_discriminant) * inv_light_square;
182 float Nxb = (radius * light_x + sqrt_discriminant) * inv_light_square;
183 float Nza = (radius - Nxa * light_x) / light_z;
184 float Nzb = (radius - Nxb * light_x) / light_z;
185 float Pza = light_z - radius * Nza;
186 float Pzb = light_z - radius * Nzb;
187
188 // Tangent a
189 if(Pza > 0)
190 {
191 float Pxa = -Pza * Nza / Nxa;
192 glm::vec4 P = proj * glm::vec4(axis.x * Pxa, axis.y * Pxa, Pza, 1);
193 float X = (glm::dot(glm::vec3(P), axis) / P.w + 1.0f * axis_sign) / 2.0f * axis_sign;
194 if(is_negative_float(Nxa) ^ is_negative_float(axis_sign))
195 {
196 in_out_max_x = std::min<std::int32_t>(std::int32_t(glm::ceil(view_size_x * X + view_x)), in_out_max_x);
197 }
198 else
199 {
200 in_out_min_x = std::max<std::int32_t>(std::int32_t(glm::floor(view_size_x * X + view_x)), in_out_min_x);
201 }
202 }
203
204 // Tangent b
205 if(Pzb > 0)
206 {
207 float Pxb = -Pzb * Nzb / Nxb;
208 glm::vec4 P = proj * glm::vec4(axis.x * Pxb, axis.y * Pxb, Pzb, 1);
209 float X = (glm::dot(glm::vec3(P), axis) / P.w + 1.0f * axis_sign) / 2.0f * axis_sign;
210 if(is_negative_float(Nxb) ^ is_negative_float(axis_sign))
211 {
212 in_out_max_x = std::min<std::int32_t>(std::int32_t(glm::ceil(view_size_x * X + view_x)), in_out_max_x);
213 }
214 else
215 {
216 in_out_min_x = std::max<std::int32_t>(std::int32_t(glm::floor(view_size_x * X + view_x)), in_out_min_x);
217 }
218 }
219 }
220
221 return in_out_min_x <= in_out_max_x;
222}
223
224//@return 0: not visible, 1:use scissor rect, 2: no scissor rect needed
225inline std::uint32_t compute_projected_sphere_rect(std::int32_t& left,
226 std::int32_t& right,
227 std::int32_t& top,
228 std::int32_t& bottom,
229 const glm::vec3& sphere_center,
230 float radius,
231 const glm::vec3& view_origin,
232 const glm::mat4& view,
233 const glm::mat4& proj)
234{
235 // Calculate a screen rectangle for the sphere's radius.
236 if(glm::length2(sphere_center - view_origin) > square(radius))
237 {
238 glm::vec3 lv = glm::vec3(view * glm::vec4(sphere_center, 1.0f));
239
240 if(!compute_projected_sphere_shaft(lv.x, lv.z, radius, proj, glm::vec3(1.0f, 0.0f, 0.0f), 1.0f, left, right))
241 {
242 return 0;
243 }
244
245 if(!compute_projected_sphere_shaft(lv.y, lv.z, radius, proj, glm::vec3(0.0f, 1.0f, 0.0f), -1.0f, top, bottom))
246 {
247 return 0;
248 }
249
250 return 1;
251 }
252 else
253 {
254 return 2;
255 }
256}
257
258inline float halton(std::uint32_t Index, std::uint32_t Base)
259{
260 float Result = 0.0f;
261 float InvBase = 1.0f / Base;
262 float Fraction = InvBase;
263 while(Index > 0)
264 {
265 Result += (Index % Base) * Fraction;
266 Index /= Base;
267 Fraction *= InvBase;
268 }
269 return Result;
270}
271
272inline std::uint32_t power_of_n_round_down(std::uint32_t val, std::uint32_t n)
273{
274 std::uint32_t currentVal = n;
275 std::uint32_t iter = 1;
276 while(currentVal < val)
277 {
278 currentVal *= n;
279 ++iter;
280 }
281
282 return iter;
283}
284
285} // namespace math
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:225
std::uint32_t power_of_n_round_down(std::uint32_t val, std::uint32_t n)
Definition math.h:272
T square(const T &t)
Definition math.h:152
float halton(std::uint32_t Index, std::uint32_t Base)
Definition math.h:258
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:162
bool is_negative_float(const float &A)
Definition math.h:141
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