Moved some utility functions

- sort goes to math funcs
- math funcs specializations for vector types go to vector files
- use ZN macros in a few more places
This commit is contained in:
Marc Gilleron 2022-04-14 21:22:22 +01:00
parent 1e380c14fb
commit e9af708c3b
12 changed files with 105 additions and 94 deletions

View File

@ -2,6 +2,7 @@
#define VOXEL_GRAPH_RUNTIME_H
#include "../../util/math/interval.h"
#include "../../util/math/vector3f.h"
#include "../../util/math/vector3i.h"
#include "../../util/span.h"
#include "code_gen_helper.h"

View File

@ -217,7 +217,7 @@ CellTextureDatas<NVoxels> select_textures_4_per_voxel(const FixedArray<unsigned
// Sort indices to avoid cases that are ambiguous for blending, like 1,2,3,4 and 2,1,3,4
// TODO maybe we could require this sorting to be done up front?
// Or maybe could be done after meshing so we do it less times?
sort(cell_textures.indices[0], cell_textures.indices[1], cell_textures.indices[2], cell_textures.indices[3]);
math::sort(cell_textures.indices[0], cell_textures.indices[1], cell_textures.indices[2], cell_textures.indices[3]);
cell_textures.packed_indices = pack_bytes(cell_textures.indices);

View File

@ -27,7 +27,7 @@ private:
MutexLock lock(mutex);
auto it = blocks.find(block);
// Must not add twice
CRASH_COND(it != blocks.end());
ZN_ASSERT(it == blocks.end());
blocks.insert(block);
}
@ -35,7 +35,7 @@ private:
MutexLock lock(mutex);
auto it = blocks.find(block);
// Must exist
CRASH_COND(it == blocks.end());
ZN_ASSERT(it != blocks.end());
blocks.erase(it);
}
};
@ -78,7 +78,7 @@ private:
inline unsigned int get_pool_index_from_size(size_t size) const {
#ifdef DEBUG_ENABLED
// `get_next_power_of_two_32` takes unsigned int
CRASH_COND(size > std::numeric_limits<unsigned int>::max());
ZN_ASSERT(size <= std::numeric_limits<unsigned int>::max());
#endif
return math::get_shift_from_power_of_two_32(math::get_next_power_of_two_32(size));
}

View File

@ -2,7 +2,6 @@
#define HEADER_VOXEL_UTILITY_H
#include "span.h"
#include <utility>
#include <vector>
namespace zylann {
@ -90,22 +89,6 @@ size_t find_duplicate(Span<const T> items) {
return items.size();
}
template <typename T>
inline void sort(T &a, T &b) {
if (a > b) {
std::swap(a, b);
}
}
template <typename T>
inline void sort(T &a, T &b, T &c, T &d) {
sort(a, b);
sort(c, d);
sort(a, c);
sort(b, d);
sort(b, c);
}
// Tests if POD items in an array are all the same.
// Better tailored for more than hundred items that have power-of-two size.
template <typename Item_T>

View File

@ -2,44 +2,10 @@
#define VOXEL_MATH_FUNCS_H
#include "../errors.h"
#include "vector2f.h"
#include "vector3f.h"
#include <core/math/vector3.h>
#include <core/math/vector3i.h>
#include <core/math/math_funcs.h>
namespace zylann::math {
// Trilinear interpolation between corner values of a cube.
//
// 6---------------7
// /| /|
// / | / |
// 5---------------4 |
// | | | |
// | | | |
// | | | |
// | 2------------|--3 Y
// | / | / | Z
// |/ |/ |/
// 1---------------0 X----o
//
template <typename T>
inline T interpolate(const T v0, const T v1, const T v2, const T v3, const T v4, const T v5, const T v6, const T v7,
Vector3f position) {
const float one_min_x = 1.f - position.x;
const float one_min_y = 1.f - position.y;
const float one_min_z = 1.f - position.z;
const float one_min_x_one_min_y = one_min_x * one_min_y;
const float x_one_min_y = position.x * one_min_y;
T res = one_min_z * (v0 * one_min_x_one_min_y + v1 * x_one_min_y + v4 * one_min_x * position.y);
res += position.z * (v3 * one_min_x_one_min_y + v2 * x_one_min_y + v7 * one_min_x * position.y);
res += position.x * position.y * (v5 * one_min_z + v6 * position.z);
return res;
}
template <typename T>
inline T min(const T a, const T b) {
return a < b ? a : b;
@ -146,7 +112,7 @@ inline T squared(const T x) {
// 6 | 2 | 2
inline int floordiv(int x, int d) {
#ifdef DEBUG_ENABLED
CRASH_COND(d <= 0);
ZN_ASSERT(d > 0);
#endif
if (x < 0) {
return (x - d + 1) / d;
@ -200,18 +166,6 @@ inline double fract(double x) {
return x - Math::floor(x);
}
inline Vector3 fract(const Vector3 &p) {
return Vector3(fract(p.x), fract(p.y), fract(p.z));
}
inline bool is_valid_size(const Vector3 &s) {
return s.x >= 0 && s.y >= 0 && s.z >= 0;
}
inline bool is_valid_size(const Vector3i &s) {
return s.x >= 0 && s.y >= 0 && s.z >= 0;
}
inline bool is_power_of_two(size_t x) {
return x != 0 && (x & (x - 1)) == 0;
}
@ -241,7 +195,7 @@ inline unsigned int get_shift_from_power_of_two_32(unsigned int pot) {
return i;
}
}
CRASH_NOW_MSG("Input was not a valid power of two");
ZN_CRASH_MSG("Input was not a valid power of two");
return 0;
}
@ -254,29 +208,10 @@ inline size_t alignup(size_t a, size_t align) {
return (a + align - 1) & ~(align - 1);
}
inline bool has_nan(const Vector3 &v) {
return Math::is_nan(v.x) || Math::is_nan(v.y) || Math::is_nan(v.z);
}
// inline bool is_power_of_two(int i) {
// return i & (i - 1);
// }
// Float version of Geometry::is_point_in_triangle()
inline bool is_point_in_triangle(const Vector2f &s, const Vector2f &a, const Vector2f &b, const Vector2f &c) {
const Vector2f an = a - s;
const Vector2f bn = b - s;
const Vector2f cn = c - s;
const bool orientation = an.cross(bn) > 0;
if ((bn.cross(cn) > 0) != orientation) {
return false;
}
return (cn.cross(an) > 0) == orientation;
}
// Float equivalent of Math::snapped, which only comes in `double` variant in Godot.
inline float snappedf(float p_value, float p_step) {
if (p_step != 0) {
@ -285,6 +220,22 @@ inline float snappedf(float p_value, float p_step) {
return p_value;
}
template <typename T>
inline void sort(T &a, T &b) {
if (a > b) {
std::swap(a, b);
}
}
template <typename T>
inline void sort(T &a, T &b, T &c, T &d) {
sort(a, b);
sort(c, d);
sort(a, c);
sort(b, d);
sort(b, c);
}
} // namespace zylann::math
#endif // VOXEL_MATH_FUNCS_H

View File

@ -2,6 +2,7 @@
#define VOXEL_MATH_SDF_H
#include "interval.h"
#include "vector3.h"
#include <core/math/vector2.h>
namespace zylann::math {

View File

@ -75,6 +75,24 @@ inline Vector2f operator*(float p_scalar, const Vector2f &v) {
return v * p_scalar;
}
namespace math {
// Float version of Geometry::is_point_in_triangle()
inline bool is_point_in_triangle(const Vector2f &s, const Vector2f &a, const Vector2f &b, const Vector2f &c) {
const Vector2f an = a - s;
const Vector2f bn = b - s;
const Vector2f cn = c - s;
const bool orientation = an.cross(bn) > 0;
if ((bn.cross(cn) > 0) != orientation) {
return false;
}
return (cn.cross(an) > 0) == orientation;
}
} // namespace math
} // namespace zylann
#endif // ZYLANN_VECTOR2F_H

18
util/math/vector3.h Normal file
View File

@ -0,0 +1,18 @@
#include "funcs.h"
#include <core/math/vector3.h>
namespace zylann::math {
inline Vector3 fract(const Vector3 &p) {
return Vector3(fract(p.x), fract(p.y), fract(p.z));
}
inline bool is_valid_size(const Vector3 &s) {
return s.x >= 0 && s.y >= 0 && s.z >= 0;
}
inline bool has_nan(const Vector3 &v) {
return Math::is_nan(v.x) || Math::is_nan(v.y) || Math::is_nan(v.z);
}
} // namespace zylann::math

View File

@ -177,6 +177,39 @@ inline Vector3f operator*(float p_scalar, const Vector3f &v) {
return v * p_scalar;
}
namespace math {
// Trilinear interpolation between corner values of a cube.
//
// 6---------------7
// /| /|
// / | / |
// 5---------------4 |
// | | | |
// | | | |
// | | | |
// | 2------------|--3 Y
// | / | / | Z
// |/ |/ |/
// 1---------------0 X----o
//
template <typename T>
inline T interpolate(const T v0, const T v1, const T v2, const T v3, const T v4, const T v5, const T v6, const T v7,
Vector3f position) {
const float one_min_x = 1.f - position.x;
const float one_min_y = 1.f - position.y;
const float one_min_z = 1.f - position.z;
const float one_min_x_one_min_y = one_min_x * one_min_y;
const float x_one_min_y = position.x * one_min_y;
T res = one_min_z * (v0 * one_min_x_one_min_y + v1 * x_one_min_y + v4 * one_min_x * position.y);
res += position.z * (v3 * one_min_x_one_min_y + v2 * x_one_min_y + v7 * one_min_x * position.y);
res += position.x * position.y * (v5 * one_min_z + v6 * position.z);
return res;
}
} // namespace math
} // namespace zylann
#endif // ZYLANN_VECTOR3F_H

View File

@ -5,6 +5,7 @@
#include "funcs.h"
#include <core/math/vector3.h>
#include <core/math/vector3i.h>
#include <core/templates/hashfuncs.h>
#include <iosfwd>
@ -294,9 +295,9 @@ inline Vector3i from_cast(const Vector3 &f) {
}
inline void sort_min_max(Vector3i &a, Vector3i &b) {
zylann::sort(a.x, b.x);
zylann::sort(a.y, b.y);
zylann::sort(a.z, b.z);
math::sort(a.x, b.x);
math::sort(a.y, b.y);
math::sort(a.z, b.z);
}
// Returning a 64-bit integer because volumes can quickly overflow INT_MAX (like 1300^3),
@ -345,6 +346,10 @@ inline bool is_unit_vector(const Vector3i v) {
return Math::abs(v.x) + Math::abs(v.y) + Math::abs(v.z) == 1;
}
inline bool is_valid_size(const Vector3i &s) {
return s.x >= 0 && s.y >= 0 && s.z >= 0;
}
} // namespace zylann::Vector3iUtil
inline Vector3i operator<<(const Vector3i &a, int b) {

View File

@ -1,5 +1,6 @@
#include "fast_noise_2.h"
#include "../math/funcs.h"
#include "../math/vector3.h"
#include <core/io/image.h>
namespace zylann {

View File

@ -1,7 +1,7 @@
#ifndef VOXEL_VIEWER_REF_COUNT_H
#define VOXEL_VIEWER_REF_COUNT_H
#include <core/error/error_macros.h>
#include "errors.h"
namespace zylann {
@ -14,7 +14,7 @@ public:
}
inline void remove() {
ERR_FAIL_COND_MSG(_count == 0, "Trying to decrease refcount when it's already zero");
ZN_ASSERT_RETURN_MSG(_count != 0, "Trying to decrease refcount when it's already zero");
--_count;
}