Loading com/include/com/reflection.hpp +91 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,10 @@ struct Reflection virtual TypeID typeID() const = 0; virtual ValuePtr copy() const = 0; virtual ValuePtr deep_copy() const { return copy(); } virtual bool equals(const ValuePtr& other) const = 0; protected: bool is_same_type(const ValuePtr& other) const { return other && other->typeID() == typeID(); } }; struct ValueBOOL : public Value Loading @@ -123,6 +127,10 @@ struct Reflection explicit ValueBOOL(bool const value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::BOOL; } ValuePtr copy() const override { return std::make_shared<ValueBOOL>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueBOOL>(other)->value == value; } bool value; }; Loading @@ -132,6 +140,11 @@ struct Reflection explicit ValueINT(std::int32_t const value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::INT; } ValuePtr copy() const override { return std::make_shared<ValueINT>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueINT>(other)->value == value; } std::int32_t value; }; Loading @@ -141,6 +154,10 @@ struct Reflection explicit ValueUINT(std::uint32_t const value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::UINT; } ValuePtr copy() const override { return std::make_shared<ValueUINT>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueUINT>(other)->value == value; } std::uint32_t value; }; Loading @@ -150,6 +167,10 @@ struct Reflection explicit ValueFLOAT(scalar const value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::FLOAT; } ValuePtr copy() const override { return std::make_shared<ValueFLOAT>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueFLOAT>(other)->value, value); } scalar value; }; Loading @@ -159,6 +180,10 @@ struct Reflection explicit ValueVEC2I(vec2i const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC2I; } ValuePtr copy() const override { return std::make_shared<ValueVEC2I>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC2I>(other)->value == value; } vec2i value; }; Loading @@ -168,6 +193,10 @@ struct Reflection explicit ValueVEC3I(vec3i const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC3I; } ValuePtr copy() const override { return std::make_shared<ValueVEC3I>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC3I>(other)->value == value; } vec3i value; }; Loading @@ -177,6 +206,10 @@ struct Reflection explicit ValueVEC4I(vec4i const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC4I; } ValuePtr copy() const override { return std::make_shared<ValueVEC4I>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC4I>(other)->value == value; } vec4i value; }; Loading @@ -186,6 +219,10 @@ struct Reflection explicit ValueVEC2U(vec2u const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC2U; } ValuePtr copy() const override { return std::make_shared<ValueVEC2U>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC2U>(other)->value == value; } vec2u value; }; Loading @@ -195,6 +232,10 @@ struct Reflection explicit ValueVEC3U(vec3u const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC3U; } ValuePtr copy() const override { return std::make_shared<ValueVEC3U>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC3U>(other)->value == value; } vec3u value; }; Loading @@ -204,6 +245,10 @@ struct Reflection explicit ValueVEC4U(vec4u const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC4U; } ValuePtr copy() const override { return std::make_shared<ValueVEC4U>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC4U>(other)->value == value; } vec4u value; }; Loading @@ -213,6 +258,10 @@ struct Reflection explicit ValueVEC2(vec2 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC2; } ValuePtr copy() const override { return std::make_shared<ValueVEC2>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueVEC2>(other)->value, value); } vec2 value; }; Loading @@ -222,6 +271,10 @@ struct Reflection explicit ValueVEC3(vec3 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC3; } ValuePtr copy() const override { return std::make_shared<ValueVEC3>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueVEC3>(other)->value, value); } vec3 value; }; Loading @@ -231,6 +284,10 @@ struct Reflection explicit ValueVEC4(vec4 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC4; } ValuePtr copy() const override { return std::make_shared<ValueVEC4>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueVEC4>(other)->value, value); } vec4 value; }; Loading @@ -240,6 +297,10 @@ struct Reflection explicit ValueMAT2X2(mat2x2 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::MAT2X2; } ValuePtr copy() const override { return std::make_shared<ValueMAT2X2>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueMAT2X2>(other)->value, value); } mat2x2 value; }; Loading @@ -249,6 +310,10 @@ struct Reflection explicit ValueMAT3X3(mat3x3 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::MAT3X3; } ValuePtr copy() const override { return std::make_shared<ValueMAT3X3>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueMAT3X3>(other)->value, value); } mat3x3 value; }; Loading @@ -258,6 +323,10 @@ struct Reflection explicit ValueMAT4X4(mat4x4 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::MAT4X4; } ValuePtr copy() const override { return std::make_shared<ValueMAT4X4>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueMAT4X4>(other)->value, value); } mat4x4 value; }; Loading @@ -267,6 +336,10 @@ struct Reflection explicit ValueQUAT(quat const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::QUAT; } ValuePtr copy() const override { return std::make_shared<ValueQUAT>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueQUAT>(other)->value, value); } quat value; }; Loading @@ -276,6 +349,10 @@ struct Reflection explicit ValueSTRING(std::string const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::STRING; } ValuePtr copy() const override { return std::make_shared<ValueSTRING>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueSTRING>(other)->value == value; } std::string value; }; Loading @@ -286,6 +363,10 @@ struct Reflection explicit ValueBYTES(BytesType const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::BYTES; } ValuePtr copy() const override { return std::make_shared<ValueBYTES>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueBYTES>(other)->value == value; } BytesType value; }; Loading @@ -296,6 +377,10 @@ struct Reflection explicit ValuePATH(ContextPath const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::PATH; } ValuePtr copy() const override { return std::make_shared<ValuePATH>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValuePATH>(other)->value == value; } ContextPath value; }; Loading @@ -305,6 +390,10 @@ struct Reflection explicit ValueITEM(ContextItem* const value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::ITEM; } ValuePtr copy() const override { return std::make_shared<ValueITEM>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueITEM>(other)->value == value; } ContextItem* value; }; Loading @@ -318,6 +407,7 @@ struct Reflection ArrayType& elements() { return m_elements; } ValuePtr copy() const override { return std::make_shared<ValueARRAY>(m_elements); } ValuePtr deep_copy() const override; bool equals(const ValuePtr& other) const override; private: ArrayType m_elements; }; Loading @@ -332,6 +422,7 @@ struct Reflection ObjectType& elements() { return m_elements; } ValuePtr copy() const override { return std::make_shared<ValueOBJECT>(m_elements); } ValuePtr deep_copy() const override; bool equals(const ValuePtr& other) const override; private: ObjectType m_elements; }; Loading com/src/reflection.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -158,6 +158,29 @@ Reflection::ValuePtr Reflection::ValueOBJECT::deep_copy() const return std::make_shared<ValueOBJECT>(elements); } bool Reflection::ValueARRAY::equals(const ValuePtr& other) const { if (!is_same_type(other)) return false; auto const& other_elements = std::static_pointer_cast<ValueARRAY>(other)->m_elements; if (m_elements.size() != other_elements.size()) return false; for (size_t i = 0; i < m_elements.size(); ++i) if (!m_elements[i]->equals(other_elements[i])) return false; return true; } bool Reflection::ValueOBJECT::equals(const ValuePtr& other) const { if (!is_same_type(other)) return false; auto const& other_elements = std::static_pointer_cast<ValueOBJECT>(other)->m_elements; if (m_elements.size() != other_elements.size()) return false; for (auto const& [key, val] : m_elements) { auto it = other_elements.find(key); if (it == other_elements.end() || !val->equals(it->second)) return false; } return true; } std::unordered_map<std::string, Reflection::Constructor> const& Reflection::constructors() { static std::unordered_map<std::string, Constructor> s_constructors{}; Loading math/include/math/math.hpp +36 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,42 @@ inline bool equal(vec4 const u, vec4 const v, scalar const epsilon = Num::epsilo equal(get<3>(u), get<3>(v), epsilon) ; } inline bool equal(mat2x2 const& a, mat2x2 const& b, scalar const epsilon = Num::epsilon) { auto const* pa = element_array_ptr(a); auto const* pb = element_array_ptr(b); for (int i = 0; i < 4; ++i) if (!equal(pa[i], pb[i], epsilon)) return false; return true; } inline bool equal(mat3x3 const& a, mat3x3 const& b, scalar const epsilon = Num::epsilon) { auto const* pa = element_array_ptr(a); auto const* pb = element_array_ptr(b); for (int i = 0; i < 9; ++i) if (!equal(pa[i], pb[i], epsilon)) return false; return true; } inline bool equal(mat4x4 const& a, mat4x4 const& b, scalar const epsilon = Num::epsilon) { auto const* pa = element_array_ptr(a); auto const* pb = element_array_ptr(b); for (int i = 0; i < 16; ++i) if (!equal(pa[i], pb[i], epsilon)) return false; return true; } inline bool equal(quat const& a, quat const& b, scalar const epsilon = Num::epsilon) { auto const* pa = element_array_ptr(a); auto const* pb = element_array_ptr(b); for (int i = 0; i < 4; ++i) if (!equal(pa[i], pb[i], epsilon)) return false; return true; } template<class T> constexpr const T& clamp(const T& v, const T& lo, const T& hi) { Loading Loading
com/include/com/reflection.hpp +91 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,10 @@ struct Reflection virtual TypeID typeID() const = 0; virtual ValuePtr copy() const = 0; virtual ValuePtr deep_copy() const { return copy(); } virtual bool equals(const ValuePtr& other) const = 0; protected: bool is_same_type(const ValuePtr& other) const { return other && other->typeID() == typeID(); } }; struct ValueBOOL : public Value Loading @@ -123,6 +127,10 @@ struct Reflection explicit ValueBOOL(bool const value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::BOOL; } ValuePtr copy() const override { return std::make_shared<ValueBOOL>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueBOOL>(other)->value == value; } bool value; }; Loading @@ -132,6 +140,11 @@ struct Reflection explicit ValueINT(std::int32_t const value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::INT; } ValuePtr copy() const override { return std::make_shared<ValueINT>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueINT>(other)->value == value; } std::int32_t value; }; Loading @@ -141,6 +154,10 @@ struct Reflection explicit ValueUINT(std::uint32_t const value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::UINT; } ValuePtr copy() const override { return std::make_shared<ValueUINT>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueUINT>(other)->value == value; } std::uint32_t value; }; Loading @@ -150,6 +167,10 @@ struct Reflection explicit ValueFLOAT(scalar const value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::FLOAT; } ValuePtr copy() const override { return std::make_shared<ValueFLOAT>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueFLOAT>(other)->value, value); } scalar value; }; Loading @@ -159,6 +180,10 @@ struct Reflection explicit ValueVEC2I(vec2i const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC2I; } ValuePtr copy() const override { return std::make_shared<ValueVEC2I>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC2I>(other)->value == value; } vec2i value; }; Loading @@ -168,6 +193,10 @@ struct Reflection explicit ValueVEC3I(vec3i const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC3I; } ValuePtr copy() const override { return std::make_shared<ValueVEC3I>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC3I>(other)->value == value; } vec3i value; }; Loading @@ -177,6 +206,10 @@ struct Reflection explicit ValueVEC4I(vec4i const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC4I; } ValuePtr copy() const override { return std::make_shared<ValueVEC4I>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC4I>(other)->value == value; } vec4i value; }; Loading @@ -186,6 +219,10 @@ struct Reflection explicit ValueVEC2U(vec2u const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC2U; } ValuePtr copy() const override { return std::make_shared<ValueVEC2U>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC2U>(other)->value == value; } vec2u value; }; Loading @@ -195,6 +232,10 @@ struct Reflection explicit ValueVEC3U(vec3u const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC3U; } ValuePtr copy() const override { return std::make_shared<ValueVEC3U>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC3U>(other)->value == value; } vec3u value; }; Loading @@ -204,6 +245,10 @@ struct Reflection explicit ValueVEC4U(vec4u const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC4U; } ValuePtr copy() const override { return std::make_shared<ValueVEC4U>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueVEC4U>(other)->value == value; } vec4u value; }; Loading @@ -213,6 +258,10 @@ struct Reflection explicit ValueVEC2(vec2 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC2; } ValuePtr copy() const override { return std::make_shared<ValueVEC2>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueVEC2>(other)->value, value); } vec2 value; }; Loading @@ -222,6 +271,10 @@ struct Reflection explicit ValueVEC3(vec3 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC3; } ValuePtr copy() const override { return std::make_shared<ValueVEC3>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueVEC3>(other)->value, value); } vec3 value; }; Loading @@ -231,6 +284,10 @@ struct Reflection explicit ValueVEC4(vec4 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::VEC4; } ValuePtr copy() const override { return std::make_shared<ValueVEC4>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueVEC4>(other)->value, value); } vec4 value; }; Loading @@ -240,6 +297,10 @@ struct Reflection explicit ValueMAT2X2(mat2x2 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::MAT2X2; } ValuePtr copy() const override { return std::make_shared<ValueMAT2X2>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueMAT2X2>(other)->value, value); } mat2x2 value; }; Loading @@ -249,6 +310,10 @@ struct Reflection explicit ValueMAT3X3(mat3x3 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::MAT3X3; } ValuePtr copy() const override { return std::make_shared<ValueMAT3X3>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueMAT3X3>(other)->value, value); } mat3x3 value; }; Loading @@ -258,6 +323,10 @@ struct Reflection explicit ValueMAT4X4(mat4x4 const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::MAT4X4; } ValuePtr copy() const override { return std::make_shared<ValueMAT4X4>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueMAT4X4>(other)->value, value); } mat4x4 value; }; Loading @@ -267,6 +336,10 @@ struct Reflection explicit ValueQUAT(quat const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::QUAT; } ValuePtr copy() const override { return std::make_shared<ValueQUAT>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && equal(std::static_pointer_cast<ValueQUAT>(other)->value, value); } quat value; }; Loading @@ -276,6 +349,10 @@ struct Reflection explicit ValueSTRING(std::string const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::STRING; } ValuePtr copy() const override { return std::make_shared<ValueSTRING>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueSTRING>(other)->value == value; } std::string value; }; Loading @@ -286,6 +363,10 @@ struct Reflection explicit ValueBYTES(BytesType const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::BYTES; } ValuePtr copy() const override { return std::make_shared<ValueBYTES>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueBYTES>(other)->value == value; } BytesType value; }; Loading @@ -296,6 +377,10 @@ struct Reflection explicit ValuePATH(ContextPath const& value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::PATH; } ValuePtr copy() const override { return std::make_shared<ValuePATH>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValuePATH>(other)->value == value; } ContextPath value; }; Loading @@ -305,6 +390,10 @@ struct Reflection explicit ValueITEM(ContextItem* const value_) : Value(), value{ value_ } {} TypeID typeID() const override { return TypeID::ITEM; } ValuePtr copy() const override { return std::make_shared<ValueITEM>(value); } bool equals(const ValuePtr& other) const override { return is_same_type(other) && std::static_pointer_cast<ValueITEM>(other)->value == value; } ContextItem* value; }; Loading @@ -318,6 +407,7 @@ struct Reflection ArrayType& elements() { return m_elements; } ValuePtr copy() const override { return std::make_shared<ValueARRAY>(m_elements); } ValuePtr deep_copy() const override; bool equals(const ValuePtr& other) const override; private: ArrayType m_elements; }; Loading @@ -332,6 +422,7 @@ struct Reflection ObjectType& elements() { return m_elements; } ValuePtr copy() const override { return std::make_shared<ValueOBJECT>(m_elements); } ValuePtr deep_copy() const override; bool equals(const ValuePtr& other) const override; private: ObjectType m_elements; }; Loading
com/src/reflection.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -158,6 +158,29 @@ Reflection::ValuePtr Reflection::ValueOBJECT::deep_copy() const return std::make_shared<ValueOBJECT>(elements); } bool Reflection::ValueARRAY::equals(const ValuePtr& other) const { if (!is_same_type(other)) return false; auto const& other_elements = std::static_pointer_cast<ValueARRAY>(other)->m_elements; if (m_elements.size() != other_elements.size()) return false; for (size_t i = 0; i < m_elements.size(); ++i) if (!m_elements[i]->equals(other_elements[i])) return false; return true; } bool Reflection::ValueOBJECT::equals(const ValuePtr& other) const { if (!is_same_type(other)) return false; auto const& other_elements = std::static_pointer_cast<ValueOBJECT>(other)->m_elements; if (m_elements.size() != other_elements.size()) return false; for (auto const& [key, val] : m_elements) { auto it = other_elements.find(key); if (it == other_elements.end() || !val->equals(it->second)) return false; } return true; } std::unordered_map<std::string, Reflection::Constructor> const& Reflection::constructors() { static std::unordered_map<std::string, Constructor> s_constructors{}; Loading
math/include/math/math.hpp +36 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,42 @@ inline bool equal(vec4 const u, vec4 const v, scalar const epsilon = Num::epsilo equal(get<3>(u), get<3>(v), epsilon) ; } inline bool equal(mat2x2 const& a, mat2x2 const& b, scalar const epsilon = Num::epsilon) { auto const* pa = element_array_ptr(a); auto const* pb = element_array_ptr(b); for (int i = 0; i < 4; ++i) if (!equal(pa[i], pb[i], epsilon)) return false; return true; } inline bool equal(mat3x3 const& a, mat3x3 const& b, scalar const epsilon = Num::epsilon) { auto const* pa = element_array_ptr(a); auto const* pb = element_array_ptr(b); for (int i = 0; i < 9; ++i) if (!equal(pa[i], pb[i], epsilon)) return false; return true; } inline bool equal(mat4x4 const& a, mat4x4 const& b, scalar const epsilon = Num::epsilon) { auto const* pa = element_array_ptr(a); auto const* pb = element_array_ptr(b); for (int i = 0; i < 16; ++i) if (!equal(pa[i], pb[i], epsilon)) return false; return true; } inline bool equal(quat const& a, quat const& b, scalar const epsilon = Num::epsilon) { auto const* pa = element_array_ptr(a); auto const* pb = element_array_ptr(b); for (int i = 0; i < 4; ++i) if (!equal(pa[i], pb[i], epsilon)) return false; return true; } template<class T> constexpr const T& clamp(const T& v, const T& lo, const T& hi) { Loading