diff --git a/src/maths/util.hpp b/src/maths/util.hpp index 92d02d826..cb58212eb 100644 --- a/src/maths/util.hpp +++ b/src/maths/util.hpp @@ -162,4 +162,19 @@ namespace util { return a + glm::ivec3(glm::round(glm::vec3(vec) * t)); } + + template + bool is_nan_or_inf(const glm::vec& vector) { + return glm::any(glm::isnan(vector)) || glm::any(glm::isinf(vector)); + } + + template + bool is_nan_or_inf(const glm::mat& matrix) { + for (int i = 0; i < n; i++) { + if (is_nan_or_inf(matrix[i])) { + return true; + } + } + return false; + } } diff --git a/src/objects/Transform.cpp b/src/objects/Transform.cpp index 8779e2201..1d6a8b621 100644 --- a/src/objects/Transform.cpp +++ b/src/objects/Transform.cpp @@ -1,6 +1,7 @@ #include "Transform.hpp" #include "data/dv_util.hpp" +#include "maths/util.hpp" #include @@ -31,3 +32,28 @@ void Transform::deserialize(const dv::value& root) { dv::get_vec(root, "size", size); dv::get_mat(root, "rot", rot); } + +bool Transform::checkValue(const glm::vec3& vector) { + if (util::is_nan_or_inf(vector)) { +#ifndef NDEBUG + throw std::invalid_argument( + "invalid vector: " + std::to_string(vector.x) + ", " + + std::to_string(vector.y) + ", " + std::to_string(vector.z) + ); +#else + return false; +#endif + } + return true; +} + +bool Transform::checkValue(const glm::mat3& matrix) { + if (util::is_nan_or_inf(matrix)) { +#ifndef NDEBUG + throw std::invalid_argument("invalid matrix (contains nan or inf)"); +#else + return false; +#endif + } + return true; +} diff --git a/src/objects/Transform.hpp b/src/objects/Transform.hpp index b948bd297..37ff18665 100644 --- a/src/objects/Transform.hpp +++ b/src/objects/Transform.hpp @@ -2,6 +2,7 @@ #define GLM_ENABLE_EXPERIMENTAL +#include #include #include #include @@ -24,11 +25,17 @@ struct Transform { void refresh(); inline void setRot(const glm::mat3& m) { + if (!checkValue(m)) { + return; + } rot = m; dirty = true; } inline void setSize(const glm::vec3& v) { + if (!checkValue(v)) { + return; + } if (glm::distance2(displaySize, v) >= EPSILON) { dirty = true; } @@ -36,9 +43,15 @@ struct Transform { } inline void setPos(const glm::vec3& v) { + if (!checkValue(v)) { + return; + } if (glm::distance2(displayPos, v) >= EPSILON) { dirty = true; } pos = v; } + + static bool checkValue(const glm::vec3& v); + static bool checkValue(const glm::mat3& v); };