3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "basic_macros.h"
23 #include "irrlichttypes.h"
26 #include "irr_aabb3d.h"
30 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d) > (max) ? (max) : (d)))
31 #define myfloor(x) ((x) < 0.0 ? (int)(x) - 1 : (int)(x))
32 // The naive swap performs better than the xor version
33 #define SWAP(t, x, y) do { \
40 inline s16
getContainerPos(s16 p
, s16 d
)
42 return (p
>= 0 ? p
: p
- d
+ 1) / d
;
45 inline v2s16
getContainerPos(v2s16 p
, s16 d
)
48 getContainerPos(p
.X
, d
),
49 getContainerPos(p
.Y
, d
)
53 inline v3s16
getContainerPos(v3s16 p
, s16 d
)
56 getContainerPos(p
.X
, d
),
57 getContainerPos(p
.Y
, d
),
58 getContainerPos(p
.Z
, d
)
62 inline v2s16
getContainerPos(v2s16 p
, v2s16 d
)
65 getContainerPos(p
.X
, d
.X
),
66 getContainerPos(p
.Y
, d
.Y
)
70 inline v3s16
getContainerPos(v3s16 p
, v3s16 d
)
73 getContainerPos(p
.X
, d
.X
),
74 getContainerPos(p
.Y
, d
.Y
),
75 getContainerPos(p
.Z
, d
.Z
)
79 inline void getContainerPosWithOffset(s16 p
, s16 d
, s16
&container
, s16
&offset
)
81 container
= (p
>= 0 ? p
: p
- d
+ 1) / d
;
85 inline void getContainerPosWithOffset(const v2s16
&p
, s16 d
, v2s16
&container
, v2s16
&offset
)
87 getContainerPosWithOffset(p
.X
, d
, container
.X
, offset
.X
);
88 getContainerPosWithOffset(p
.Y
, d
, container
.Y
, offset
.Y
);
91 inline void getContainerPosWithOffset(const v3s16
&p
, s16 d
, v3s16
&container
, v3s16
&offset
)
93 getContainerPosWithOffset(p
.X
, d
, container
.X
, offset
.X
);
94 getContainerPosWithOffset(p
.Y
, d
, container
.Y
, offset
.Y
);
95 getContainerPosWithOffset(p
.Z
, d
, container
.Z
, offset
.Z
);
99 inline bool isInArea(v3s16 p
, s16 d
)
102 p
.X
>= 0 && p
.X
< d
&&
103 p
.Y
>= 0 && p
.Y
< d
&&
108 inline bool isInArea(v2s16 p
, s16 d
)
111 p
.X
>= 0 && p
.X
< d
&&
116 inline bool isInArea(v3s16 p
, v3s16 d
)
119 p
.X
>= 0 && p
.X
< d
.X
&&
120 p
.Y
>= 0 && p
.Y
< d
.Y
&&
121 p
.Z
>= 0 && p
.Z
< d
.Z
125 inline void sortBoxVerticies(v3s16
&p1
, v3s16
&p2
) {
127 SWAP(s16
, p1
.X
, p2
.X
);
129 SWAP(s16
, p1
.Y
, p2
.Y
);
131 SWAP(s16
, p1
.Z
, p2
.Z
);
134 inline v3s16
componentwise_min(const v3s16
&a
, const v3s16
&b
)
136 return v3s16(MYMIN(a
.X
, b
.X
), MYMIN(a
.Y
, b
.Y
), MYMIN(a
.Z
, b
.Z
));
139 inline v3s16
componentwise_max(const v3s16
&a
, const v3s16
&b
)
141 return v3s16(MYMAX(a
.X
, b
.X
), MYMAX(a
.Y
, b
.Y
), MYMAX(a
.Z
, b
.Z
));
145 /** Returns \p f wrapped to the range [-360, 360]
147 * See test.cpp for example cases.
149 * \note This is also used in cases where degrees wrapped to the range [0, 360]
150 * is innapropriate (e.g. pitch needs negative values)
152 * \internal functionally equivalent -- although precision may vary slightly --
153 * to fmodf((f), 360.0f) however empirical tests indicate that this approach is
156 inline float modulo360f(float f
)
171 fraction
= f
- whole
;
174 return sign
* (whole
+ fraction
);
178 /** Returns \p f wrapped to the range [0, 360]
180 inline float wrapDegrees_0_360(float f
)
182 float value
= modulo360f(f
);
183 return value
< 0 ? value
+ 360 : value
;
187 /** Returns \p v3f wrapped to the range [0, 360]
189 inline v3f
wrapDegrees_0_360_v3f(v3f v
)
192 value_v3f
.X
= modulo360f(v
.X
);
193 value_v3f
.Y
= modulo360f(v
.Y
);
194 value_v3f
.Z
= modulo360f(v
.Z
);
196 // Now that values are wrapped, use to get values for certain ranges
197 value_v3f
.X
= value_v3f
.X
< 0 ? value_v3f
.X
+ 360 : value_v3f
.X
;
198 value_v3f
.Y
= value_v3f
.Y
< 0 ? value_v3f
.Y
+ 360 : value_v3f
.Y
;
199 value_v3f
.Z
= value_v3f
.Z
< 0 ? value_v3f
.Z
+ 360 : value_v3f
.Z
;
204 /** Returns \p f wrapped to the range [-180, 180]
206 inline float wrapDegrees_180(float f
)
208 float value
= modulo360f(f
+ 180);
215 Pseudo-random (VC++ rand() sucks)
217 #define MYRAND_RANGE 0xffffffff
219 void mysrand(unsigned int seed
);
220 void myrand_bytes(void *out
, size_t len
);
221 int myrand_range(int min
, int max
);
224 Miscellaneous functions
227 inline u32
get_bits(u32 x
, u32 pos
, u32 len
)
229 u32 mask
= (1 << len
) - 1;
230 return (x
>> pos
) & mask
;
233 inline void set_bits(u32
*x
, u32 pos
, u32 len
, u32 val
)
235 u32 mask
= (1 << len
) - 1;
236 *x
&= ~(mask
<< pos
);
237 *x
|= (val
& mask
) << pos
;
240 inline u32
calc_parity(u32 v
)
246 return (0x6996 >> v
) & 1;
249 u64
murmur_hash_64_ua(const void *key
, int len
, unsigned int seed
);
251 bool isBlockInSight(v3s16 blockpos_b
, v3f camera_pos
, v3f camera_dir
,
252 f32 camera_fov
, f32 range
, f32
*distance_ptr
=NULL
);
254 s16
adjustDist(s16 dist
, float zoom_fov
);
257 Returns nearest 32-bit integer for given floating point number.
258 <cmath> and <math.h> in VC++ don't provide round().
260 inline s32
myround(f32 f
)
262 return (s32
)(f
< 0.f
? (f
- 0.5f
) : (f
+ 0.5f
));
265 inline constexpr f32
sqr(f32 f
)
271 Returns integer position of node in given floating point position
273 inline v3s16
floatToInt(v3f p
, f32 d
)
276 (p
.X
+ (p
.X
> 0 ? d
/ 2 : -d
/ 2)) / d
,
277 (p
.Y
+ (p
.Y
> 0 ? d
/ 2 : -d
/ 2)) / d
,
278 (p
.Z
+ (p
.Z
> 0 ? d
/ 2 : -d
/ 2)) / d
);
282 Returns integer position of node in given double precision position
284 inline v3s16
doubleToInt(v3d p
, double d
)
287 (p
.X
+ (p
.X
> 0 ? d
/ 2 : -d
/ 2)) / d
,
288 (p
.Y
+ (p
.Y
> 0 ? d
/ 2 : -d
/ 2)) / d
,
289 (p
.Z
+ (p
.Z
> 0 ? d
/ 2 : -d
/ 2)) / d
);
293 Returns floating point position of node in given integer position
295 inline v3f
intToFloat(v3s16 p
, f32 d
)
304 // Random helper. Usually d=BS
305 inline aabb3f
getNodeBox(v3s16 p
, float d
)
308 (float)p
.X
* d
- 0.5f
* d
,
309 (float)p
.Y
* d
- 0.5f
* d
,
310 (float)p
.Z
* d
- 0.5f
* d
,
311 (float)p
.X
* d
+ 0.5f
* d
,
312 (float)p
.Y
* d
+ 0.5f
* d
,
313 (float)p
.Z
* d
+ 0.5f
* d
318 class IntervalLimiter
321 IntervalLimiter() = default;
324 dtime: time from last call to this method
325 wanted_interval: interval wanted
327 true: action should be skipped
328 false: action should be done
330 bool step(float dtime
, float wanted_interval
)
332 m_accumulator
+= dtime
;
333 if (m_accumulator
< wanted_interval
)
335 m_accumulator
-= wanted_interval
;
340 float m_accumulator
= 0.0f
;
345 Splits a list into "pages". For example, the list [1,2,3,4,5] split
346 into two pages would be [1,2,3],[4,5]. This function computes the
347 minimum and maximum indices of a single page.
349 length: Length of the list that should be split
350 page: Page number, 1 <= page <= pagecount
351 pagecount: The number of pages, >= 1
352 minindex: Receives the minimum index (inclusive).
353 maxindex: Receives the maximum index (exclusive).
355 Ensures 0 <= minindex <= maxindex <= length.
357 inline void paging(u32 length
, u32 page
, u32 pagecount
, u32
&minindex
, u32
&maxindex
)
359 if (length
< 1 || pagecount
< 1 || page
< 1 || page
> pagecount
) {
360 // Special cases or invalid parameters
361 minindex
= maxindex
= 0;
362 } else if(pagecount
<= length
) {
363 // Less pages than entries in the list:
364 // Each page contains at least one entry
365 minindex
= (length
* (page
-1) + (pagecount
-1)) / pagecount
;
366 maxindex
= (length
* page
+ (pagecount
-1)) / pagecount
;
368 // More pages than entries in the list:
369 // Make sure the empty pages are at the end
380 inline float cycle_shift(float value
, float by
= 0, float max
= 1)
382 if (value
+ by
< 0) return value
+ by
+ max
;
383 if (value
+ by
> max
) return value
+ by
- max
;
387 inline bool is_power_of_two(u32 n
)
389 return n
!= 0 && (n
& (n
- 1)) == 0;
392 // Compute next-higher power of 2 efficiently, e.g. for power-of-2 texture sizes.
393 // Public Domain: https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
394 inline u32
npot2(u32 orig
) {
404 // Gradual steps towards the target value in a wrapped (circular) system
405 // using the shorter of both ways
407 inline void wrappedApproachShortest(T
¤t
, const T target
, const T stepsize
,
410 T delta
= target
- current
;
414 if (delta
> stepsize
&& maximum
- delta
> stepsize
) {
415 current
+= (delta
< maximum
/ 2) ? stepsize
: -stepsize
;
416 if (current
>= maximum
)
423 void setPitchYawRollRad(core::matrix4
&m
, const v3f
&rot
);
425 inline void setPitchYawRoll(core::matrix4
&m
, const v3f
&rot
)
427 setPitchYawRollRad(m
, rot
* core::DEGTORAD64
);
430 v3f
getPitchYawRollRad(const core::matrix4
&m
);
432 inline v3f
getPitchYawRoll(const core::matrix4
&m
)
434 return getPitchYawRollRad(m
) * core::RADTODEG64
;
437 // Muliply the RGB value of a color linearly, and clamp to black/white
438 inline irr::video::SColor
multiplyColorValue(const irr::video::SColor
&color
, float mod
)
440 return irr::video::SColor(color
.getAlpha(),
441 core::clamp
<u32
>(color
.getRed() * mod
, 0, 255),
442 core::clamp
<u32
>(color
.getGreen() * mod
, 0, 255),
443 core::clamp
<u32
>(color
.getBlue() * mod
, 0, 255));