Luanti 5.10.0-dev
 
Loading...
Searching...
No Matches
numeric.h
Go to the documentation of this file.
1// Luanti
2// SPDX-License-Identifier: LGPL-2.1-or-later
3// Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5#pragma once
6
7#include "basic_macros.h"
8#include "constants.h"
9#include "irrlichttypes.h"
10#include "irr_v2d.h"
11#include "irr_v3d.h"
12#include "irr_aabb3d.h"
13#include "SColor.h"
14#include <matrix4.h>
15#include <cmath>
16#include <algorithm>
17
18#define rangelim(d, min, max) ((d) < (min) ? (min) : ((d) > (max) ? (max) : (d)))
19#define myfloor(x) ((x) < 0.0 ? (int)(x) - 1 : (int)(x))
20// The naive swap performs better than the xor version
21#define SWAP(t, x, y) do { \
22 t temp = x; \
23 x = y; \
24 y = temp; \
25} while (0)
26
27// Maximum radius of a block. The magic number is
28// sqrt(3.0) / 2.0 in literal form.
29static constexpr const f32 BLOCK_MAX_RADIUS = 0.866025403784f * MAP_BLOCKSIZE * BS;
30
31inline s16 getContainerPos(s16 p, s16 d)
32{
33 return (p >= 0 ? p : p - d + 1) / d;
34}
35
37{
38 return v2s16(
39 getContainerPos(p.X, d),
40 getContainerPos(p.Y, d)
41 );
42}
43
45{
46 return v3s16(
47 getContainerPos(p.X, d),
48 getContainerPos(p.Y, d),
49 getContainerPos(p.Z, d)
50 );
51}
52
54{
55 return v2s16(
56 getContainerPos(p.X, d.X),
57 getContainerPos(p.Y, d.Y)
58 );
59}
60
62{
63 return v3s16(
64 getContainerPos(p.X, d.X),
65 getContainerPos(p.Y, d.Y),
66 getContainerPos(p.Z, d.Z)
67 );
68}
69
70inline void getContainerPosWithOffset(s16 p, s16 d, s16 &container, s16 &offset)
71{
72 container = (p >= 0 ? p : p - d + 1) / d;
73 offset = p & (d - 1);
74}
75
76inline void getContainerPosWithOffset(const v2s16 &p, s16 d, v2s16 &container, v2s16 &offset)
77{
78 getContainerPosWithOffset(p.X, d, container.X, offset.X);
79 getContainerPosWithOffset(p.Y, d, container.Y, offset.Y);
80}
81
82inline void getContainerPosWithOffset(const v3s16 &p, s16 d, v3s16 &container, v3s16 &offset)
83{
84 getContainerPosWithOffset(p.X, d, container.X, offset.X);
85 getContainerPosWithOffset(p.Y, d, container.Y, offset.Y);
86 getContainerPosWithOffset(p.Z, d, container.Z, offset.Z);
87}
88
89
90inline bool isInArea(v3s16 p, s16 d)
91{
92 return (
93 p.X >= 0 && p.X < d &&
94 p.Y >= 0 && p.Y < d &&
95 p.Z >= 0 && p.Z < d
96 );
97}
98
99inline bool isInArea(v2s16 p, s16 d)
100{
101 return (
102 p.X >= 0 && p.X < d &&
103 p.Y >= 0 && p.Y < d
104 );
105}
106
107inline bool isInArea(v3s16 p, v3s16 d)
108{
109 return (
110 p.X >= 0 && p.X < d.X &&
111 p.Y >= 0 && p.Y < d.Y &&
112 p.Z >= 0 && p.Z < d.Z
113 );
114}
115
116inline void sortBoxVerticies(v3s16 &p1, v3s16 &p2) {
117 if (p1.X > p2.X)
118 SWAP(s16, p1.X, p2.X);
119 if (p1.Y > p2.Y)
120 SWAP(s16, p1.Y, p2.Y);
121 if (p1.Z > p2.Z)
122 SWAP(s16, p1.Z, p2.Z);
123}
124
125inline v3s16 componentwise_min(const v3s16 &a, const v3s16 &b)
126{
127 return v3s16(MYMIN(a.X, b.X), MYMIN(a.Y, b.Y), MYMIN(a.Z, b.Z));
128}
129
130inline v3s16 componentwise_max(const v3s16 &a, const v3s16 &b)
131{
132 return v3s16(MYMAX(a.X, b.X), MYMAX(a.Y, b.Y), MYMAX(a.Z, b.Z));
133}
134
136struct MeshGrid {
138
139 u32 getCellVolume() const { return cell_size * cell_size * cell_size; }
140
142 s16 getCellPos(s16 p) const
143 {
144 return (p - (p < 0) * (cell_size - 1)) / cell_size;
145 }
146
148 v3s16 getCellPos(v3s16 block_pos) const
149 {
150 return v3s16(getCellPos(block_pos.X), getCellPos(block_pos.Y), getCellPos(block_pos.Z));
151 }
152
154 s16 getMeshPos(s16 p) const
155 {
156 return getCellPos(p) * cell_size;
157 }
158
161 {
162 return v3s16(getMeshPos(p.X), getMeshPos(p.Y), getMeshPos(p.Z));
163 }
164
166 bool isMeshPos(v3s16 &p) const
167 {
168 return p.X % cell_size == 0
169 && p.Y % cell_size == 0
170 && p.Z % cell_size == 0;
171 }
172
175 u16 getOffsetIndex(v3s16 offset) const
176 {
177 return (offset.Z * cell_size + offset.Y) * cell_size + offset.X;
178 }
179};
180
188inline float modulo360f(float f)
189{
190 return fmodf(f, 360.0f);
191}
192
193
196inline float wrapDegrees_0_360(float f)
197{
198 float value = modulo360f(f);
199 return value < 0 ? value + 360 : value;
200}
201
202
206{
207 v3f value_v3f;
208 value_v3f.X = modulo360f(v.X);
209 value_v3f.Y = modulo360f(v.Y);
210 value_v3f.Z = modulo360f(v.Z);
211
212 // Now that values are wrapped, use to get values for certain ranges
213 value_v3f.X = value_v3f.X < 0 ? value_v3f.X + 360 : value_v3f.X;
214 value_v3f.Y = value_v3f.Y < 0 ? value_v3f.Y + 360 : value_v3f.Y;
215 value_v3f.Z = value_v3f.Z < 0 ? value_v3f.Z + 360 : value_v3f.Z;
216 return value_v3f;
217}
218
219
222inline float wrapDegrees_180(float f)
223{
224 float value = modulo360f(f + 180);
225 if (value < 0)
226 value += 360;
227 return value - 180;
228}
229
230/*
231 Pseudo-random (VC++ rand() sucks)
232*/
233#define MYRAND_RANGE 0xffffffff
234u32 myrand();
235void mysrand(unsigned int seed);
236void myrand_bytes(void *out, size_t len);
237int myrand_range(int min, int max);
238float myrand_range(float min, float max);
239float myrand_float();
240
241// Implements a C++11 UniformRandomBitGenerator using the above functions
243 typedef u32 result_type;
244 static constexpr result_type min() { return 0; }
245 static constexpr result_type max() { return MYRAND_RANGE; }
247 return myrand();
248 }
249};
250
251/*
252 Miscellaneous functions
253*/
254
255inline u32 get_bits(u32 x, u32 pos, u32 len)
256{
257 u32 mask = (1 << len) - 1;
258 return (x >> pos) & mask;
259}
260
261inline void set_bits(u32 *x, u32 pos, u32 len, u32 val)
262{
263 u32 mask = (1 << len) - 1;
264 *x &= ~(mask << pos);
265 *x |= (val & mask) << pos;
266}
267
268inline u32 calc_parity(u32 v)
269{
270 v ^= v >> 16;
271 v ^= v >> 8;
272 v ^= v >> 4;
273 v &= 0xf;
274 return (0x6996 >> v) & 1;
275}
276
277u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed);
278
279bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
280 f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
281
282s16 adjustDist(s16 dist, float zoom_fov);
283
284/*
285 Returns nearest 32-bit integer for given floating point number.
286 <cmath> and <math.h> in VC++ don't provide round().
287*/
288inline s32 myround(f32 f)
289{
290 return (s32)(f < 0.f ? (f - 0.5f) : (f + 0.5f));
291}
292
293inline constexpr f32 sqr(f32 f)
294{
295 return f * f;
296}
297
298/*
299 Returns integer position of node in given floating point position
300*/
301inline v3s16 floatToInt(v3f p, f32 d)
302{
303 return v3s16(
304 (p.X + (p.X > 0 ? d / 2 : -d / 2)) / d,
305 (p.Y + (p.Y > 0 ? d / 2 : -d / 2)) / d,
306 (p.Z + (p.Z > 0 ? d / 2 : -d / 2)) / d);
307}
308
309/*
310 Returns integer position of node in given double precision position
311 */
312inline v3s16 doubleToInt(v3d p, double d)
313{
314 return v3s16(
315 (p.X + (p.X > 0 ? d / 2 : -d / 2)) / d,
316 (p.Y + (p.Y > 0 ? d / 2 : -d / 2)) / d,
317 (p.Z + (p.Z > 0 ? d / 2 : -d / 2)) / d);
318}
319
320/*
321 Returns floating point position of node in given integer position
322*/
323inline v3f intToFloat(v3s16 p, f32 d)
324{
325 return v3f(
326 (f32)p.X * d,
327 (f32)p.Y * d,
328 (f32)p.Z * d
329 );
330}
331
332// Random helper. Usually d=BS
333inline aabb3f getNodeBox(v3s16 p, float d)
334{
335 return aabb3f(
336 (float)p.X * d - 0.5f * d,
337 (float)p.Y * d - 0.5f * d,
338 (float)p.Z * d - 0.5f * d,
339 (float)p.X * d + 0.5f * d,
340 (float)p.Y * d + 0.5f * d,
341 (float)p.Z * d + 0.5f * d
342 );
343}
344
345
347{
348public:
349 IntervalLimiter() = default;
350
356 bool step(float dtime, float wanted_interval)
357 {
358 m_accumulator += dtime;
359 if (m_accumulator < wanted_interval)
360 return false;
361 m_accumulator -= wanted_interval;
362 return true;
363 }
364
365private:
366 float m_accumulator = 0.0f;
367};
368
369
370/*
371 Splits a list into "pages". For example, the list [1,2,3,4,5] split
372 into two pages would be [1,2,3],[4,5]. This function computes the
373 minimum and maximum indices of a single page.
374
375 length: Length of the list that should be split
376 page: Page number, 1 <= page <= pagecount
377 pagecount: The number of pages, >= 1
378 minindex: Receives the minimum index (inclusive).
379 maxindex: Receives the maximum index (exclusive).
380
381 Ensures 0 <= minindex <= maxindex <= length.
382*/
383inline void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxindex)
384{
385 if (length < 1 || pagecount < 1 || page < 1 || page > pagecount) {
386 // Special cases or invalid parameters
387 minindex = maxindex = 0;
388 } else if(pagecount <= length) {
389 // Less pages than entries in the list:
390 // Each page contains at least one entry
391 minindex = (length * (page-1) + (pagecount-1)) / pagecount;
392 maxindex = (length * page + (pagecount-1)) / pagecount;
393 } else {
394 // More pages than entries in the list:
395 // Make sure the empty pages are at the end
396 if (page < length) {
397 minindex = page-1;
398 maxindex = page;
399 } else {
400 minindex = 0;
401 maxindex = 0;
402 }
403 }
404}
405
406inline float cycle_shift(float value, float by = 0, float max = 1)
407{
408 if (value + by < 0) return value + by + max;
409 if (value + by > max) return value + by - max;
410 return value + by;
411}
412
413inline bool is_power_of_two(u32 n)
414{
415 return n != 0 && (n & (n - 1)) == 0;
416}
417
418// Compute next-higher power of 2 efficiently, e.g. for power-of-2 texture sizes.
419// Public Domain: https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
420inline u32 npot2(u32 orig) {
421 orig--;
422 orig |= orig >> 1;
423 orig |= orig >> 2;
424 orig |= orig >> 4;
425 orig |= orig >> 8;
426 orig |= orig >> 16;
427 return orig + 1;
428}
429
430// Distance between two values in a wrapped (circular) system
431template<typename T>
432inline unsigned wrappedDifference(T a, T b, const T maximum)
433{
434 if (a > b)
435 std::swap(a, b);
436 // now b >= a
437 unsigned s = b - a, l = static_cast<unsigned>(maximum - b) + a + 1;
438 return std::min(s, l);
439}
440
441// Gradual steps towards the target value in a wrapped (circular) system
442// using the shorter of both ways
443template<typename T>
444inline void wrappedApproachShortest(T &current, const T target, const T stepsize,
445 const T maximum)
446{
447 T delta = target - current;
448 if (delta < 0)
449 delta += maximum;
450
451 if (delta > stepsize && maximum - delta > stepsize) {
452 current += (delta < maximum / 2) ? stepsize : -stepsize;
453 if (current >= maximum)
454 current -= maximum;
455 } else {
456 current = target;
457 }
458}
459
460void setPitchYawRollRad(core::matrix4 &m, v3f rot);
461
462inline void setPitchYawRoll(core::matrix4 &m, v3f rot)
463{
464 setPitchYawRollRad(m, rot * core::DEGTORAD);
465}
466
467v3f getPitchYawRollRad(const core::matrix4 &m);
468
469inline v3f getPitchYawRoll(const core::matrix4 &m)
470{
471 return getPitchYawRollRad(m) * core::RADTODEG;
472}
473
474// Muliply the RGB value of a color linearly, and clamp to black/white
475inline irr::video::SColor multiplyColorValue(const irr::video::SColor &color, float mod)
476{
477 return irr::video::SColor(color.getAlpha(),
478 core::clamp<u32>(color.getRed() * mod, 0, 255),
479 core::clamp<u32>(color.getGreen() * mod, 0, 255),
480 core::clamp<u32>(color.getBlue() * mod, 0, 255));
481}
482
483template <typename T> inline T numericAbsolute(T v) { return v < 0 ? T(-v) : v; }
484template <typename T> inline T numericSign(T v) { return T(v < 0 ? -1 : (v == 0 ? 0 : 1)); }
485
487{
488 return v3f(
489 numericAbsolute(v.X),
490 numericAbsolute(v.Y),
491 numericAbsolute(v.Z)
492 );
493}
494
495inline v3f vecSign(v3f v)
496{
497 return v3f(
498 numericSign(v.X),
499 numericSign(v.Y),
500 numericSign(v.Z)
501 );
502}
#define MYMIN(a, b)
Definition basic_macros.h:9
#define MYMAX(a, b)
Definition basic_macros.h:11
Definition numeric.h:347
float m_accumulator
Definition numeric.h:366
IntervalLimiter()=default
bool step(float dtime, float wanted_interval)
Definition numeric.h:356
#define BS
Definition constants.h:61
#define MAP_BLOCKSIZE
Definition constants.h:64
core::aabbox3d< f32 > aabb3f
Definition irr_aabb3d.h:11
core::vector2d< s16 > v2s16
Definition irr_v2d.h:12
core::vector3d< double > v3d
Definition irr_v3d.h:12
core::vector3d< s16 > v3s16
Definition irr_v3d.h:13
core::vector3df v3f
Definition irr_v3d.h:11
s16 getContainerPos(s16 p, s16 d)
Definition numeric.h:31
v3s16 componentwise_max(const v3s16 &a, const v3s16 &b)
Definition numeric.h:130
v3f getPitchYawRollRad(const core::matrix4 &m)
Definition numeric.cpp:196
v3s16 componentwise_min(const v3s16 &a, const v3s16 &b)
Definition numeric.h:125
bool isInArea(v3s16 p, s16 d)
Definition numeric.h:90
void wrappedApproachShortest(T &current, const T target, const T stepsize, const T maximum)
Definition numeric.h:444
T numericAbsolute(T v)
Definition numeric.h:483
v3s16 floatToInt(v3f p, f32 d)
Definition numeric.h:301
u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed)
Definition numeric.cpp:54
T numericSign(T v)
Definition numeric.h:484
float wrapDegrees_0_360(float f)
Returns f wrapped to the range [0, 360].
Definition numeric.h:196
u32 npot2(u32 orig)
Definition numeric.h:420
void setPitchYawRoll(core::matrix4 &m, v3f rot)
Definition numeric.h:462
v3f getPitchYawRoll(const core::matrix4 &m)
Definition numeric.h:469
constexpr f32 sqr(f32 f)
Definition numeric.h:293
v3f wrapDegrees_0_360_v3f(v3f v)
Returns v3f wrapped to the range [0, 360].
Definition numeric.h:205
s16 adjustDist(s16 dist, float zoom_fov)
Definition numeric.cpp:170
void set_bits(u32 *x, u32 pos, u32 len, u32 val)
Definition numeric.h:261
void setPitchYawRollRad(core::matrix4 &m, v3f rot)
Definition numeric.cpp:175
irr::video::SColor multiplyColorValue(const irr::video::SColor &color, float mod)
Definition numeric.h:475
u32 myrand()
Definition numeric.cpp:19
v3f intToFloat(v3s16 p, f32 d)
Definition numeric.h:323
u32 get_bits(u32 x, u32 pos, u32 len)
Definition numeric.h:255
float cycle_shift(float value, float by=0, float max=1)
Definition numeric.h:406
bool is_power_of_two(u32 n)
Definition numeric.h:413
bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 camera_fov, f32 range, f32 *distance_ptr=NULL)
Definition numeric.cpp:102
static constexpr const f32 BLOCK_MAX_RADIUS
Definition numeric.h:29
unsigned wrappedDifference(T a, T b, const T maximum)
Definition numeric.h:432
float modulo360f(float f)
Returns f wrapped to the range [-360, 360].
Definition numeric.h:188
v3s16 doubleToInt(v3d p, double d)
Definition numeric.h:312
#define MYRAND_RANGE
Definition numeric.h:233
float wrapDegrees_180(float f)
Returns f wrapped to the range [-180, 180].
Definition numeric.h:222
aabb3f getNodeBox(v3s16 p, float d)
Definition numeric.h:333
void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxindex)
Definition numeric.h:383
v3f vecAbsolute(v3f v)
Definition numeric.h:486
void sortBoxVerticies(v3s16 &p1, v3s16 &p2)
Definition numeric.h:116
void getContainerPosWithOffset(s16 p, s16 d, s16 &container, s16 &offset)
Definition numeric.h:70
#define SWAP(t, x, y)
Definition numeric.h:21
void mysrand(unsigned int seed)
Definition numeric.cpp:24
v3f vecSign(v3f v)
Definition numeric.h:495
float myrand_float()
Definition numeric.cpp:34
s32 myround(f32 f)
Definition numeric.h:288
int myrand_range(int min, int max)
Definition numeric.cpp:40
u32 calc_parity(u32 v)
Definition numeric.h:268
void myrand_bytes(void *out, size_t len)
Definition numeric.cpp:29
Describes a grid with given step, oirginating at (0,0,0)
Definition numeric.h:136
bool isMeshPos(v3s16 &p) const
Returns true if p is an origin of a cell in the grid.
Definition numeric.h:166
v3s16 getMeshPos(v3s16 p) const
Returns coordinates of the origin of the grid cell containing p.
Definition numeric.h:160
u16 cell_size
Definition numeric.h:137
s16 getCellPos(s16 p) const
returns coordinate of mesh cell given coordinate of a map block
Definition numeric.h:142
u32 getCellVolume() const
Definition numeric.h:139
v3s16 getCellPos(v3s16 block_pos) const
returns position of mesh cell in the grid given position of a map block
Definition numeric.h:148
s16 getMeshPos(s16 p) const
returns closest step of the grid smaller than p
Definition numeric.h:154
u16 getOffsetIndex(v3s16 offset) const
Returns index of the given offset in a grid cell All offset coordinates must be smaller than the size...
Definition numeric.h:175
Definition numeric.h:242
static constexpr result_type max()
Definition numeric.h:245
u32 result_type
Definition numeric.h:243
static constexpr result_type min()
Definition numeric.h:244
result_type operator()()
Definition numeric.h:246
static std::string p(std::string path)
Definition test_filesys.cpp:53