X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Futil%2Fnumeric.h;h=32a6f4312b04abc975a96021912fff965f8502de;hb=c7bcebb62856ae5fdb23a13e6fa1052eae700ddf;hp=b4b8419188526965996e28f693f37b5ed96d8639;hpb=6d61375cc72bad5c569d25c253adca4e3701dd27;p=minetest.git diff --git a/src/util/numeric.h b/src/util/numeric.h index b4b841918..32a6f4312 100644 --- a/src/util/numeric.h +++ b/src/util/numeric.h @@ -17,51 +17,33 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef UTIL_NUMERIC_HEADER -#define UTIL_NUMERIC_HEADER - -#include "../irrlichttypes.h" -#include "../irr_v2d.h" -#include "../irr_v3d.h" -#include "../irr_aabb3d.h" -#include -#include -#include -#include - - -/* - * This class permits to cache getFacePosition call results - * This reduces CPU usage and vector calls - */ -class FacePositionCache -{ -public: - static std::vector getFacePositions(u16 d); -private: - static void generateFacePosition(u16 d); - static std::map > m_cache; -}; +#pragma once + +#include "basic_macros.h" +#include "constants.h" +#include "irrlichttypes.h" +#include "irr_v2d.h" +#include "irr_v3d.h" +#include "irr_aabb3d.h" +#include "SColor.h" +#include + +#define rangelim(d, min, max) ((d) < (min) ? (min) : ((d) > (max) ? (max) : (d))) +#define myfloor(x) ((x) < 0.0 ? (int)(x) - 1 : (int)(x)) +// The naive swap performs better than the xor version +#define SWAP(t, x, y) do { \ + t temp = x; \ + x = y; \ + y = temp; \ +} while (0) -class IndentationRaiser -{ -public: - IndentationRaiser(u16 *indentation) - { - m_indentation = indentation; - (*m_indentation)++; - } - ~IndentationRaiser() - { - (*m_indentation)--; - } -private: - u16 *m_indentation; -}; +// Maximum radius of a block. The magic number is +// sqrt(3.0) / 2.0 in literal form. +static constexpr const f32 BLOCK_MAX_RADIUS = 0.866025403784f * MAP_BLOCKSIZE * BS; inline s16 getContainerPos(s16 p, s16 d) { - return (p>=0 ? p : p-d+1) / d; + return (p >= 0 ? p : p - d + 1) / d; } inline v2s16 getContainerPos(v2s16 p, s16 d) @@ -144,36 +126,6 @@ inline bool isInArea(v3s16 p, v3s16 d) ); } -#define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d))) -#define myfloor(x) ((x) > 0.0 ? (int)(x) : (int)(x) - 1) - -inline v3s16 arealim(v3s16 p, s16 d) -{ - if(p.X < 0) - p.X = 0; - if(p.Y < 0) - p.Y = 0; - if(p.Z < 0) - p.Z = 0; - if(p.X > d-1) - p.X = d-1; - if(p.Y > d-1) - p.Y = d-1; - if(p.Z > d-1) - p.Z = d-1; - return p; -} - -#define ARRLEN(x) (sizeof(x) / sizeof((x)[0])) -#define CONTAINS(c, v) (std::find((c).begin(), (c).end(), (v)) != (c).end()) - -// The naive swap performs better than the xor version -#define SWAP(t, x, y) do { \ - t temp = x; \ - x = y; \ - y = temp; \ -} while (0) - inline void sortBoxVerticies(v3s16 &p1, v3s16 &p2) { if (p1.X > p2.X) SWAP(s16, p1.X, p2.X); @@ -183,6 +135,16 @@ inline void sortBoxVerticies(v3s16 &p1, v3s16 &p2) { SWAP(s16, p1.Z, p2.Z); } +inline v3s16 componentwise_min(const v3s16 &a, const v3s16 &b) +{ + return v3s16(MYMIN(a.X, b.X), MYMIN(a.Y, b.Y), MYMIN(a.Z, b.Z)); +} + +inline v3s16 componentwise_max(const v3s16 &a, const v3s16 &b) +{ + return v3s16(MYMAX(a.X, b.X), MYMAX(a.Y, b.Y), MYMAX(a.Z, b.Z)); +} + /** Returns \p f wrapped to the range [-360, 360] * @@ -226,6 +188,23 @@ inline float wrapDegrees_0_360(float f) } +/** Returns \p v3f wrapped to the range [0, 360] + */ +inline v3f wrapDegrees_0_360_v3f(v3f v) +{ + v3f value_v3f; + value_v3f.X = modulo360f(v.X); + value_v3f.Y = modulo360f(v.Y); + value_v3f.Z = modulo360f(v.Z); + + // Now that values are wrapped, use to get values for certain ranges + value_v3f.X = value_v3f.X < 0 ? value_v3f.X + 360 : value_v3f.X; + value_v3f.Y = value_v3f.Y < 0 ? value_v3f.Y + 360 : value_v3f.Y; + value_v3f.Z = value_v3f.Z < 0 ? value_v3f.Z + 360 : value_v3f.Z; + return value_v3f; +} + + /** Returns \p f wrapped to the range [-180, 180] */ inline float wrapDegrees_180(float f) @@ -276,11 +255,7 @@ u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed); bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 camera_fov, f32 range, f32 *distance_ptr=NULL); -/* - Some helper stuff -*/ -#define MYMIN(a,b) ((a)<(b)?(a):(b)) -#define MYMAX(a,b) ((a)>(b)?(a):(b)) +s16 adjustDist(s16 dist, float zoom_fov); /* Returns nearest 32-bit integer for given floating point number. @@ -288,7 +263,12 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, */ inline s32 myround(f32 f) { - return floor(f + 0.5); + return (s32)(f < 0.f ? (f - 0.5f) : (f + 0.5f)); +} + +inline constexpr f32 sqr(f32 f) +{ + return f * f; } /* @@ -296,11 +276,21 @@ inline s32 myround(f32 f) */ inline v3s16 floatToInt(v3f p, f32 d) { - v3s16 p2( - (p.X + (p.X>0 ? d/2 : -d/2))/d, - (p.Y + (p.Y>0 ? d/2 : -d/2))/d, - (p.Z + (p.Z>0 ? d/2 : -d/2))/d); - return p2; + return v3s16( + (p.X + (p.X > 0 ? d / 2 : -d / 2)) / d, + (p.Y + (p.Y > 0 ? d / 2 : -d / 2)) / d, + (p.Z + (p.Z > 0 ? d / 2 : -d / 2)) / d); +} + +/* + Returns integer position of node in given double precision position + */ +inline v3s16 doubleToInt(v3d p, double d) +{ + return v3s16( + (p.X + (p.X > 0 ? d / 2 : -d / 2)) / d, + (p.Y + (p.Y > 0 ? d / 2 : -d / 2)) / d, + (p.Z + (p.Z > 0 ? d / 2 : -d / 2)) / d); } /* @@ -308,34 +298,32 @@ inline v3s16 floatToInt(v3f p, f32 d) */ inline v3f intToFloat(v3s16 p, f32 d) { - v3f p2( + return v3f( (f32)p.X * d, (f32)p.Y * d, (f32)p.Z * d ); - return p2; } // Random helper. Usually d=BS -inline core::aabbox3d getNodeBox(v3s16 p, float d) -{ - return core::aabbox3d( - (float)p.X * d - 0.5*d, - (float)p.Y * d - 0.5*d, - (float)p.Z * d - 0.5*d, - (float)p.X * d + 0.5*d, - (float)p.Y * d + 0.5*d, - (float)p.Z * d + 0.5*d +inline aabb3f getNodeBox(v3s16 p, float d) +{ + return aabb3f( + (float)p.X * d - 0.5f * d, + (float)p.Y * d - 0.5f * d, + (float)p.Z * d - 0.5f * d, + (float)p.X * d + 0.5f * d, + (float)p.Y * d + 0.5f * d, + (float)p.Z * d + 0.5f * d ); } + class IntervalLimiter { public: - IntervalLimiter(): - m_accumulator(0) - { - } + IntervalLimiter() = default; + /* dtime: time from last call to this method wanted_interval: interval wanted @@ -346,15 +334,17 @@ class IntervalLimiter bool step(float dtime, float wanted_interval) { m_accumulator += dtime; - if(m_accumulator < wanted_interval) + if (m_accumulator < wanted_interval) return false; m_accumulator -= wanted_interval; return true; } -protected: - float m_accumulator; + +private: + float m_accumulator = 0.0f; }; + /* Splits a list into "pages". For example, the list [1,2,3,4,5] split into two pages would be [1,2,3],[4,5]. This function computes the @@ -370,29 +360,21 @@ class IntervalLimiter */ inline void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxindex) { - if(length < 1 || pagecount < 1 || page < 1 || page > pagecount) - { + if (length < 1 || pagecount < 1 || page < 1 || page > pagecount) { // Special cases or invalid parameters minindex = maxindex = 0; - } - else if(pagecount <= length) - { + } else if(pagecount <= length) { // Less pages than entries in the list: // Each page contains at least one entry minindex = (length * (page-1) + (pagecount-1)) / pagecount; maxindex = (length * page + (pagecount-1)) / pagecount; - } - else - { + } else { // More pages than entries in the list: // Make sure the empty pages are at the end - if(page < length) - { + if (page < length) { minindex = page-1; maxindex = page; - } - else - { + } else { minindex = 0; maxindex = 0; } @@ -401,14 +383,14 @@ inline void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxi inline float cycle_shift(float value, float by = 0, float max = 1) { - if (value + by < 0) return max + by + value; + if (value + by < 0) return value + by + max; if (value + by > max) return value + by - max; return value + by; } inline bool is_power_of_two(u32 n) { - return n != 0 && (n & (n-1)) == 0; + return n != 0 && (n & (n - 1)) == 0; } // Compute next-higher power of 2 efficiently, e.g. for power-of-2 texture sizes. @@ -423,4 +405,44 @@ inline u32 npot2(u32 orig) { return orig + 1; } -#endif +// Gradual steps towards the target value in a wrapped (circular) system +// using the shorter of both ways +template +inline void wrappedApproachShortest(T ¤t, const T target, const T stepsize, + const T maximum) +{ + T delta = target - current; + if (delta < 0) + delta += maximum; + + if (delta > stepsize && maximum - delta > stepsize) { + current += (delta < maximum / 2) ? stepsize : -stepsize; + if (current >= maximum) + current -= maximum; + } else { + current = target; + } +} + +void setPitchYawRollRad(core::matrix4 &m, const v3f &rot); + +inline void setPitchYawRoll(core::matrix4 &m, const v3f &rot) +{ + setPitchYawRollRad(m, rot * core::DEGTORAD64); +} + +v3f getPitchYawRollRad(const core::matrix4 &m); + +inline v3f getPitchYawRoll(const core::matrix4 &m) +{ + return getPitchYawRollRad(m) * core::RADTODEG64; +} + +// Muliply the RGB value of a color linearly, and clamp to black/white +inline irr::video::SColor multiplyColorValue(const irr::video::SColor &color, float mod) +{ + return irr::video::SColor(color.getAlpha(), + core::clamp(color.getRed() * mod, 0, 255), + core::clamp(color.getGreen() * mod, 0, 255), + core::clamp(color.getBlue() * mod, 0, 255)); +}