added nodiscard messages

This commit is contained in:
2026-05-22 09:00:32 +03:00
parent 37128d18e7
commit 848202cbd8
5 changed files with 187 additions and 145 deletions
+49 -49
View File
@@ -59,7 +59,7 @@ namespace omath
clear();
}
[[nodiscard]]
[[nodiscard("You must use store ordering")]]
consteval static MatStoreType get_store_ordering() noexcept
{
return StoreType;
@@ -94,13 +94,13 @@ namespace omath
m_data = other.m_data;
}
[[nodiscard]]
[[nodiscard("You must use element reference")]]
constexpr Type& operator[](const size_t row, const size_t col)
{
return at(row, col);
}
[[nodiscard]]
[[nodiscard("You must use element reference")]]
constexpr const Type& operator[](const size_t row, const size_t col) const
{
return at(row, col);
@@ -111,25 +111,25 @@ namespace omath
m_data = std::move(other.m_data);
}
[[nodiscard]]
[[nodiscard("You must use row count")]]
static constexpr size_t row_count() noexcept
{
return Rows;
}
[[nodiscard]]
[[nodiscard("You must use column count")]]
static constexpr size_t columns_count() noexcept
{
return Columns;
}
[[nodiscard]]
[[nodiscard("You must use matrix size")]]
static constexpr MatSize size() noexcept
{
return {Rows, Columns};
}
[[nodiscard]]
[[nodiscard("You must use element reference")]]
constexpr const Type& at(const size_t row_index, const size_t column_index) const
{
#if !defined(NDEBUG) && defined(OMATH_SUPRESS_SAFETY_CHECKS)
@@ -149,12 +149,12 @@ namespace omath
}
}
[[nodiscard]] constexpr Type& at(const size_t row_index, const size_t column_index)
[[nodiscard("You must use element reference")]] constexpr Type& at(const size_t row_index, const size_t column_index)
{
return const_cast<Type&>(std::as_const(*this).at(row_index, column_index));
}
[[nodiscard]]
[[nodiscard("You must use sum of elements")]]
constexpr Type sum() const noexcept
{
return std::accumulate(m_data.begin(), m_data.end(), static_cast<Type>(0));
@@ -171,7 +171,7 @@ namespace omath
}
// Operator overloading for multiplication with another Mat
template<size_t OtherColumns> [[nodiscard]]
template<size_t OtherColumns> [[nodiscard("You must use result matrix")]]
constexpr Mat<Rows, OtherColumns, Type, StoreType>
operator*(const Mat<Columns, OtherColumns, Type, StoreType>& other) const
{
@@ -202,7 +202,7 @@ namespace omath
return *this = *this * other;
}
[[nodiscard]]
[[nodiscard("You must use result matrix")]]
constexpr Mat operator*(const Type& value) const noexcept
{
Mat result(*this);
@@ -216,7 +216,7 @@ namespace omath
return *this;
}
[[nodiscard]]
[[nodiscard("You must use result matrix")]]
constexpr Mat operator/(const Type& value) const noexcept
{
Mat result(*this);
@@ -240,7 +240,7 @@ namespace omath
return *this;
}
[[nodiscard]]
[[nodiscard("You must use transposed matrix")]]
constexpr Mat<Columns, Rows, Type, StoreType> transposed() const noexcept
{
Mat<Columns, Rows, Type, StoreType> transposed;
@@ -251,7 +251,7 @@ namespace omath
return transposed;
}
[[nodiscard]]
[[nodiscard("You must use determinant")]]
constexpr Type determinant() const
{
static_assert(Rows == Columns, "Determinant is only defined for square matrices.");
@@ -276,7 +276,7 @@ namespace omath
std::unreachable();
}
[[nodiscard]]
[[nodiscard("You must use stripped matrix")]]
constexpr Mat<Rows - 1, Columns - 1, Type, StoreType> strip(const size_t row, const size_t column) const
{
static_assert(Rows - 1 > 0 && Columns - 1 > 0);
@@ -297,32 +297,32 @@ namespace omath
return result;
}
[[nodiscard]]
[[nodiscard("You must use minor")]]
constexpr Type minor(const size_t row, const size_t column) const
{
return strip(row, column).determinant();
}
[[nodiscard]]
[[nodiscard("You must use algebraic complement")]]
constexpr Type alg_complement(const size_t row, const size_t column) const
{
const auto minor_value = minor(row, column);
return (row + column + 2) % 2 == 0 ? minor_value : -minor_value;
}
[[nodiscard]]
[[nodiscard("You must use raw array")]]
constexpr const std::array<Type, Rows * Columns>& raw_array() const
{
return m_data;
}
[[nodiscard]]
[[nodiscard("You must use raw array")]]
constexpr std::array<Type, Rows * Columns>& raw_array()
{
return m_data;
}
[[nodiscard]]
[[nodiscard("You must use string representation")]]
std::string to_string() const noexcept
{
std::ostringstream oss;
@@ -344,14 +344,14 @@ namespace omath
return oss.str();
}
[[nodiscard]]
[[nodiscard("You must use wide string representation")]]
std::wstring to_wstring() const noexcept
{
const auto ascii_string = to_string();
return {ascii_string.cbegin(), ascii_string.cend()};
}
[[nodiscard]]
[[nodiscard("You must use UTF-8 string representation")]]
// ReSharper disable once CppInconsistentNaming
std::u8string to_u8string() const noexcept
{
@@ -359,20 +359,20 @@ namespace omath
return {ascii_string.cbegin(), ascii_string.cend()};
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator==(const Mat& mat) const
{
return m_data == mat.m_data;
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator!=(const Mat& mat) const
{
return !operator==(mat);
}
// Static methods that return fixed-size matrices
[[nodiscard]]
[[nodiscard("You must use screen matrix")]]
constexpr static Mat<4, 4> to_screen_mat(const Type& screen_width, const Type& screen_height) noexcept
{
return {
@@ -383,7 +383,7 @@ namespace omath
};
}
[[nodiscard]]
[[nodiscard("You must use inverted matrix")]]
constexpr std::optional<Mat> inverted() const
{
const auto det = determinant();
@@ -406,7 +406,7 @@ namespace omath
private:
std::array<Type, Rows * Columns> m_data;
template<size_t OtherColumns> [[nodiscard]]
template<size_t OtherColumns> [[nodiscard("You must use result matrix")]]
constexpr Mat<Rows, OtherColumns, Type, MatStoreType::ROW_MAJOR>
cache_friendly_multiply_row_major(const Mat<Columns, OtherColumns, Type, MatStoreType::ROW_MAJOR>& other) const
{
@@ -421,7 +421,7 @@ namespace omath
return result;
}
template<size_t OtherColumns> [[nodiscard]]
template<size_t OtherColumns> [[nodiscard("You must use result matrix")]]
constexpr Mat<Rows, OtherColumns, Type, MatStoreType::COLUMN_MAJOR> cache_friendly_multiply_col_major(
const Mat<Columns, OtherColumns, Type, MatStoreType::COLUMN_MAJOR>& other) const
{
@@ -436,7 +436,7 @@ namespace omath
return result;
}
#ifdef OMATH_USE_AVX2
template<size_t OtherColumns> [[nodiscard]]
template<size_t OtherColumns> [[nodiscard("You must use result matrix")]]
constexpr Mat<Rows, OtherColumns, Type, MatStoreType::COLUMN_MAJOR>
avx_multiply_col_major(const Mat<Columns, OtherColumns, Type, MatStoreType::COLUMN_MAJOR>& other) const
{
@@ -506,7 +506,7 @@ namespace omath
return result;
}
template<size_t OtherColumns> [[nodiscard]]
template<size_t OtherColumns> [[nodiscard("You must use result matrix")]]
constexpr Mat<Rows, OtherColumns, Type, MatStoreType::ROW_MAJOR>
avx_multiply_row_major(const Mat<Columns, OtherColumns, Type, MatStoreType::ROW_MAJOR>& other) const
{
@@ -577,20 +577,20 @@ namespace omath
#endif
};
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR> [[nodiscard]]
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR> [[nodiscard("You must use row matrix")]]
constexpr static Mat<1, 4, Type, St> mat_row_from_vector(const Vector3<Type>& vector) noexcept
{
return {{vector.x, vector.y, vector.z, 1}};
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR> [[nodiscard]]
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR> [[nodiscard("You must use column matrix")]]
constexpr static Mat<4, 1, Type, St> mat_column_from_vector(const Vector3<Type>& vector) noexcept
{
return {{vector.x}, {vector.y}, {vector.z}, {1}};
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
[[nodiscard("You must use translation matrix")]]
constexpr Mat<4, 4, Type, St> mat_translation(const Vector3<Type>& diff) noexcept
{
return
@@ -602,7 +602,7 @@ namespace omath
};
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
[[nodiscard("You must use scale matrix")]]
constexpr Mat<4, 4, Type, St> mat_scale(const Vector3<Type>& scale) noexcept
{
return {
@@ -614,14 +614,14 @@ namespace omath
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
[[nodiscard("You must use extracted origin")]]
constexpr Vector3<Type> mat_extract_origin(const Mat<4, 4, Type, St>& mat) noexcept
{
return {mat.at(0, 3), mat.at(1, 3), mat.at(2, 3)};
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
[[nodiscard("You must use extracted scale")]]
Vector3<Type> mat_extract_scale(const Mat<4, 4, Type, St>& mat) noexcept
{
auto column_length = [](const Type x, const Type y, const Type z) {
@@ -643,7 +643,7 @@ namespace omath
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
requires std::is_floating_point_v<Type>
[[nodiscard]]
[[nodiscard("You must use extracted rotation")]]
Vector3<Type> mat_extract_rotation_zyx(const Mat<4, 4, Type, St>& mat) noexcept
{
const auto scale = mat_extract_scale(mat);
@@ -661,7 +661,7 @@ namespace omath
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
[[nodiscard]]
[[nodiscard("You must use rotation matrix")]]
Mat<4, 4, Type, St> mat_rotation_axis_x(const Angle& angle) noexcept
{
return
@@ -674,7 +674,7 @@ namespace omath
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
[[nodiscard]]
[[nodiscard("You must use rotation matrix")]]
Mat<4, 4, Type, St> mat_rotation_axis_y(const Angle& angle) noexcept
{
return
@@ -687,7 +687,7 @@ namespace omath
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
[[nodiscard]]
[[nodiscard("You must use rotation matrix")]]
Mat<4, 4, Type, St> mat_rotation_axis_z(const Angle& angle) noexcept
{
return
@@ -700,7 +700,7 @@ namespace omath
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
[[nodiscard("You must use camera view matrix")]]
static Mat<4, 4, Type, St> mat_camera_view(const Vector3<Type>& forward, const Vector3<Type>& right,
const Vector3<Type>& up, const Vector3<Type>& camera_origin) noexcept
{
@@ -715,7 +715,7 @@ namespace omath
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
[[nodiscard]]
[[nodiscard("You must use perspective matrix")]]
Mat<4, 4, Type, St> mat_perspective_left_handed_vertical_fov(const Type field_of_view, const Type aspect_ratio,
const Type near, const Type far) noexcept
{
@@ -737,7 +737,7 @@ namespace omath
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
[[nodiscard]]
[[nodiscard("You must use perspective matrix")]]
Mat<4, 4, Type, St> mat_perspective_right_handed_vertical_fov(const Type field_of_view, const Type aspect_ratio,
const Type near, const Type far) noexcept
{
@@ -762,7 +762,7 @@ namespace omath
// X and Y scales derived as: X = 1 / tan(hfov/2), Y = aspect / tan(hfov/2).
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
[[nodiscard]]
[[nodiscard("You must use perspective matrix")]]
Mat<4, 4, Type, St> mat_perspective_left_handed_horizontal_fov(const Type horizontal_fov,
const Type aspect_ratio, const Type near,
const Type far) noexcept
@@ -787,7 +787,7 @@ namespace omath
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
[[nodiscard]]
[[nodiscard("You must use perspective matrix")]]
Mat<4, 4, Type, St> mat_perspective_right_handed_horizontal_fov(const Type horizontal_fov,
const Type aspect_ratio, const Type near,
const Type far) noexcept
@@ -811,7 +811,7 @@ namespace omath
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
[[nodiscard]]
[[nodiscard("You must use ortho matrix")]]
Mat<4, 4, Type, St> mat_ortho_left_handed(const Type left, const Type right, const Type bottom, const Type top,
const Type near, const Type far) noexcept
{
@@ -836,7 +836,7 @@ namespace omath
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR,
NDCDepthRange DepthRange = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
[[nodiscard]]
[[nodiscard("You must use ortho matrix")]]
Mat<4, 4, Type, St> mat_ortho_right_handed(const Type left, const Type right, const Type bottom, const Type top,
const Type near, const Type far) noexcept
{
@@ -883,14 +883,14 @@ template<size_t Rows, size_t Columns, class Type, omath::MatStoreType StoreType>
struct std::formatter<omath::Mat<Rows, Columns, Type, StoreType>> // NOLINT(*-dcl58-cpp)
{
using MatType = omath::Mat<Rows, Columns, Type, StoreType>;
[[nodiscard]]
[[nodiscard("You must use parse iterator")]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
template<class FormatContext>
[[nodiscard]]
[[nodiscard("You must use format iterator")]]
static auto format(const MatType& mat, FormatContext& ctx)
{
if constexpr (std::is_same_v<typename FormatContext::char_type, char>)
+40 -28
View File
@@ -28,7 +28,7 @@ namespace omath
template<class CastedType>
requires std::is_arithmetic_v<CastedType>
[[nodiscard]] constexpr explicit operator Vector2<CastedType>() const noexcept
[[nodiscard("You must use casted vector")]] constexpr explicit operator Vector2<CastedType>() const noexcept
{
return {static_cast<CastedType>(x), static_cast<CastedType>(y)};
}
@@ -37,13 +37,13 @@ namespace omath
}
// Equality operators
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
constexpr bool operator==(const Vector2& other) const noexcept
{
return x == other.x && y == other.y;
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
constexpr bool operator!=(const Vector2& other) const noexcept
{
return !(*this == other);
@@ -115,45 +115,51 @@ namespace omath
}
// Basic vector operations
[[nodiscard]] Type distance_to(const Vector2& other) const noexcept
[[nodiscard("You must use distance")]]
Type distance_to(const Vector2& other) const noexcept
{
return std::sqrt(distance_to_sqr(other));
}
[[nodiscard]] constexpr Type distance_to_sqr(const Vector2& other) const noexcept
[[nodiscard("You must use squared distance")]]
constexpr Type distance_to_sqr(const Vector2& other) const noexcept
{
return (x - other.x) * (x - other.x) + (y - other.y) * (y - other.y);
}
[[nodiscard]] constexpr Type dot(const Vector2& other) const noexcept
[[nodiscard("You must use dot product")]]
constexpr Type dot(const Vector2& other) const noexcept
{
return x * other.x + y * other.y;
}
#ifndef _MSC_VER
[[nodiscard]] constexpr Type length() const noexcept
[[nodiscard("You must use length")]] constexpr Type length() const noexcept
{
return std::hypot(this->x, this->y);
}
[[nodiscard]] constexpr Vector2 normalized() const noexcept
[[nodiscard("You must use normalized vector")]] constexpr Vector2 normalized() const noexcept
{
const Type len = length();
return len > 0.f ? *this / len : *this;
}
#else
[[nodiscard]] Type length() const noexcept
[[nodiscard("You must use length")]]
Type length() const noexcept
{
return std::hypot(x, y);
}
[[nodiscard]] Vector2 normalized() const noexcept
[[nodiscard("You must use normalized vector")]]
Vector2 normalized() const noexcept
{
const Type len = length();
return len > static_cast<Type>(0) ? *this / len : *this;
}
#endif
[[nodiscard]] constexpr Type length_sqr() const noexcept
[[nodiscard("You must use squared length")]]
constexpr Type length_sqr() const noexcept
{
return x * x + y * y;
}
@@ -166,79 +172,85 @@ namespace omath
return *this;
}
[[nodiscard]] constexpr Vector2 operator-() const noexcept
[[nodiscard("You must use negated vector")]]
constexpr Vector2 operator-() const noexcept
{
return {-x, -y};
}
// Binary arithmetic operators
[[nodiscard]] constexpr Vector2 operator+(const Vector2& other) const noexcept
[[nodiscard("You must use result vector")]]
constexpr Vector2 operator+(const Vector2& other) const noexcept
{
return {x + other.x, y + other.y};
}
[[nodiscard]] constexpr Vector2 operator-(const Vector2& other) const noexcept
[[nodiscard("You must use result vector")]]
constexpr Vector2 operator-(const Vector2& other) const noexcept
{
return {x - other.x, y - other.y};
}
[[nodiscard]] constexpr Vector2 operator*(const Type& value) const noexcept
[[nodiscard("You must use result vector")]]
constexpr Vector2 operator*(const Type& value) const noexcept
{
return {x * value, y * value};
}
[[nodiscard]] constexpr Vector2 operator/(const Type& value) const noexcept
[[nodiscard("You must use result vector")]]
constexpr Vector2 operator/(const Type& value) const noexcept
{
return {x / value, y / value};
}
// Sum of elements
[[nodiscard]] constexpr Type sum() const noexcept
[[nodiscard("You must use sum of elements")]]
constexpr Type sum() const noexcept
{
return x + y;
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator<(const Vector2& other) const noexcept
{
return length() < other.length();
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator>(const Vector2& other) const noexcept
{
return length() > other.length();
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator<=(const Vector2& other) const noexcept
{
return length() <= other.length();
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator>=(const Vector2& other) const noexcept
{
return length() >= other.length();
}
[[nodiscard]]
[[nodiscard("You must use tuple")]]
constexpr std::tuple<Type, Type> as_tuple() const noexcept
{
return std::make_tuple(x, y);
}
[[nodiscard]]
[[nodiscard("You must use array")]]
constexpr std::array<Type, 2> as_array() const noexcept
{
return {x, y};
}
#ifdef OMATH_IMGUI_INTEGRATION
[[nodiscard]]
[[nodiscard("You must use ImVec2")]]
constexpr ImVec2 to_im_vec2() const noexcept
{
return {static_cast<float>(this->x), static_cast<float>(this->y)};
}
[[nodiscard]]
[[nodiscard("You must use vector from ImVec2")]]
static Vector2 from_im_vec2(const ImVec2& other) noexcept
{
return {static_cast<Type>(other.x), static_cast<Type>(other.y)};
@@ -249,7 +261,7 @@ namespace omath
template<> struct std::hash<omath::Vector2<float>>
{
[[nodiscard]]
[[nodiscard("You must use hash value")]]
std::size_t operator()(const omath::Vector2<float>& vec) const noexcept
{
std::size_t hash = 0;
@@ -265,14 +277,14 @@ template<> struct std::hash<omath::Vector2<float>>
template<class Type>
struct std::formatter<omath::Vector2<Type>> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
[[nodiscard("You must use parse iterator")]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
template<class FormatContext>
[[nodiscard]]
[[nodiscard("You must use format iterator")]]
static auto format(const omath::Vector2<Type>& vec, FormatContext& ctx)
{
if constexpr (std::is_same_v<typename FormatContext::char_type, char>)
+59 -37
View File
@@ -32,17 +32,20 @@ namespace omath
template<class CastedType>
requires std::is_arithmetic_v<CastedType>
[[nodiscard]] constexpr explicit operator Vector3<CastedType>() const noexcept
[[nodiscard("You must use casted vector")]]
constexpr explicit operator Vector3<CastedType>() const noexcept
{
return {static_cast<CastedType>(this->x), static_cast<CastedType>(this->y),
static_cast<CastedType>(this->z)};
}
[[nodiscard]] constexpr bool operator==(const Vector3& other) const noexcept
[[nodiscard("You must use comparison result")]]
constexpr bool operator==(const Vector3& other) const noexcept
{
return Vector2<Type>::operator==(other) && (other.z == z);
}
[[nodiscard]] constexpr bool operator!=(const Vector3& other) const noexcept
[[nodiscard("You must use comparison result")]]
constexpr bool operator!=(const Vector3& other) const noexcept
{
return !(*this == other);
}
@@ -119,117 +122,134 @@ namespace omath
return *this;
}
[[nodiscard]] constexpr Type distance_to_sqr(const Vector3& other) const noexcept
[[nodiscard("You must use squared distance")]]
constexpr Type distance_to_sqr(const Vector3& other) const noexcept
{
return (*this - other).length_sqr();
}
[[nodiscard]] constexpr Type dot(const Vector3& other) const noexcept
[[nodiscard("You must use dot product")]]
constexpr Type dot(const Vector3& other) const noexcept
{
return Vector2<Type>::dot(other) + z * other.z;
}
#ifndef _MSC_VER
[[nodiscard]] constexpr Type length() const
[[nodiscard("You must use length")]] constexpr Type length() const
{
return std::hypot(this->x, this->y, z);
}
[[nodiscard]] constexpr Type length_2d() const
[[nodiscard("You must use 2D length")]] constexpr Type length_2d() const
{
return Vector2<Type>::length();
}
[[nodiscard]] Type distance_to(const Vector3& other) const
[[nodiscard("You must use distance")]] Type distance_to(const Vector3& other) const
{
return (*this - other).length();
}
[[nodiscard]] constexpr Vector3 normalized() const
[[nodiscard("You must use normalized vector")]] constexpr Vector3 normalized() const
{
const Type length_value = this->length();
return length_value != 0 ? *this / length_value : *this;
}
#else
[[nodiscard]] Type length() const noexcept
[[nodiscard("You must use length")]]
Type length() const noexcept
{
return std::hypot(this->x, this->y, z);
}
[[nodiscard]] Vector3 normalized() const noexcept
[[nodiscard("You must use normalized vector")]]
Vector3 normalized() const noexcept
{
const Type len = this->length();
return len != static_cast<Type>(0) ? *this / len : *this;
}
[[nodiscard]] Type length_2d() const noexcept
[[nodiscard("You must use 2D length")]]
Type length_2d() const noexcept
{
return Vector2<Type>::length();
}
[[nodiscard]] Type distance_to(const Vector3& v_other) const noexcept
[[nodiscard("You must use distance")]]
Type distance_to(const Vector3& v_other) const noexcept
{
return (*this - v_other).length();
}
#endif
[[nodiscard]] constexpr Type length_sqr() const noexcept
[[nodiscard("You must use squared length")]]
constexpr Type length_sqr() const noexcept
{
return Vector2<Type>::length_sqr() + z * z;
}
[[nodiscard]] constexpr Vector3 operator-() const noexcept
[[nodiscard("You must use negated vector")]]
constexpr Vector3 operator-() const noexcept
{
return {-this->x, -this->y, -z};
}
[[nodiscard]] constexpr Vector3 operator+(const Vector3& other) const noexcept
[[nodiscard("You must use result vector")]]
constexpr Vector3 operator+(const Vector3& other) const noexcept
{
return {this->x + other.x, this->y + other.y, z + other.z};
}
[[nodiscard]] constexpr Vector3 operator-(const Vector3& other) const noexcept
[[nodiscard("You must use result vector")]]
constexpr Vector3 operator-(const Vector3& other) const noexcept
{
return {this->x - other.x, this->y - other.y, z - other.z};
}
[[nodiscard]] constexpr Vector3 operator*(const Type& value) const noexcept
[[nodiscard("You must use result vector")]]
constexpr Vector3 operator*(const Type& value) const noexcept
{
return {this->x * value, this->y * value, z * value};
}
[[nodiscard]] constexpr Vector3 operator*(const Vector3& other) const noexcept
[[nodiscard("You must use result vector")]]
constexpr Vector3 operator*(const Vector3& other) const noexcept
{
return {this->x * other.x, this->y * other.y, z * other.z};
}
[[nodiscard]] constexpr Vector3 operator/(const Type& value) const noexcept
[[nodiscard("You must use result vector")]]
constexpr Vector3 operator/(const Type& value) const noexcept
{
return {this->x / value, this->y / value, z / value};
}
[[nodiscard]] constexpr Vector3 operator/(const Vector3& other) const noexcept
[[nodiscard("You must use result vector")]]
constexpr Vector3 operator/(const Vector3& other) const noexcept
{
return {this->x / other.x, this->y / other.y, z / other.z};
}
[[nodiscard]] constexpr Vector3 cross(const Vector3& other) const noexcept
[[nodiscard("You must use cross product")]]
constexpr Vector3 cross(const Vector3& other) const noexcept
{
return {this->y * other.z - z * other.y, z * other.x - this->x * other.z,
this->x * other.y - this->y * other.x};
}
[[nodiscard]] constexpr Type sum() const noexcept
[[nodiscard("You must use sum of elements")]]
constexpr Type sum() const noexcept
{
return sum_2d() + z;
}
[[nodiscard]]
[[nodiscard("You must use direction check result")]]
bool point_to_same_direction(const Vector3& other) const
{
return dot(other) > static_cast<Type>(0);
}
[[nodiscard]] std::expected<Angle<float, 0.f, 180.f, AngleFlags::Clamped>, Vector3Error>
[[nodiscard("You must use angle between vectors")]]
std::expected<Angle<float, 0.f, 180.f, AngleFlags::Clamped>, Vector3Error>
angle_between(const Vector3& other) const noexcept
{
const auto bottom = length() * other.length();
@@ -240,8 +260,8 @@ namespace omath
return Angle<float, 0.f, 180.f, AngleFlags::Clamped>::from_radians(std::acos(dot(other) / bottom));
}
[[nodiscard]] bool is_perpendicular(const Vector3& other,
Type epsilon = static_cast<Type>(0.0001)) const noexcept
[[nodiscard("You must use perpendicularity check result")]]
bool is_perpendicular(const Vector3& other, Type epsilon = static_cast<Type>(0.0001)) const noexcept
{
if (const auto angle = angle_between(other))
return std::abs(angle->as_degrees() - static_cast<Type>(90)) <= epsilon;
@@ -249,41 +269,43 @@ namespace omath
return false;
}
[[nodiscard]] constexpr Type sum_2d() const noexcept
[[nodiscard("You must use 2D sum")]]
constexpr Type sum_2d() const noexcept
{
return Vector2<Type>::sum();
}
[[nodiscard]] constexpr std::tuple<Type, Type, Type> as_tuple() const noexcept
[[nodiscard("You must use tuple")]]
constexpr std::tuple<Type, Type, Type> as_tuple() const noexcept
{
return std::make_tuple(this->x, this->y, z);
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator<(const Vector3& other) const noexcept
{
return length() < other.length();
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator>(const Vector3& other) const noexcept
{
return length() > other.length();
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator<=(const Vector3& other) const noexcept
{
return length() <= other.length();
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator>=(const Vector3& other) const noexcept
{
return length() >= other.length();
}
[[nodiscard]]
[[nodiscard("You must use array")]]
constexpr std::array<Type, 3> as_array() const noexcept
{
return {this->x, this->y, z};
@@ -293,7 +315,7 @@ namespace omath
template<> struct std::hash<omath::Vector3<float>>
{
[[nodiscard]]
[[nodiscard("You must use hash value")]]
std::size_t operator()(const omath::Vector3<float>& vec) const noexcept
{
std::size_t hash = 0;
@@ -310,14 +332,14 @@ template<> struct std::hash<omath::Vector3<float>>
template<class Type>
struct std::formatter<omath::Vector3<Type>> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
[[nodiscard("You must use parse iterator")]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
template<class FormatContext>
[[nodiscard]]
[[nodiscard("You must use format iterator")]]
static auto format(const omath::Vector3<Type>& vec, FormatContext& ctx)
{
if constexpr (std::is_same_v<typename FormatContext::char_type, char>)
+26 -24
View File
@@ -24,19 +24,19 @@ namespace omath
template<class CastedType>
requires std::is_arithmetic_v<CastedType>
[[nodiscard]] constexpr explicit operator Vector4<CastedType>() const noexcept
[[nodiscard("You must use casted vector")]] constexpr explicit operator Vector4<CastedType>() const noexcept
{
return {static_cast<CastedType>(this->x), static_cast<CastedType>(this->y),
static_cast<CastedType>(this->z), static_cast<CastedType>(this->w)};
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
constexpr bool operator==(const Vector4& other) const noexcept
{
return Vector3<Type>::operator==(other) && w == other.w;
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
constexpr bool operator!=(const Vector4& other) const noexcept
{
return !(*this == other);
@@ -89,17 +89,19 @@ namespace omath
return *this;
}
[[nodiscard]] constexpr Type length_sqr() const noexcept
[[nodiscard("You must use squared length")]]
constexpr Type length_sqr() const noexcept
{
return Vector3<Type>::length_sqr() + w * w;
}
[[nodiscard]] constexpr Type dot(const Vector4& other) const noexcept
[[nodiscard("You must use dot product")]]
constexpr Type dot(const Vector4& other) const noexcept
{
return Vector3<Type>::dot(other) + w * other.w;
}
[[nodiscard]] Type length() const noexcept
[[nodiscard("You must use length")]] Type length() const noexcept
{
return std::sqrt(length_sqr());
}
@@ -120,86 +122,86 @@ namespace omath
return *this;
}
[[nodiscard]]
[[nodiscard("You must use negated vector")]]
constexpr Vector4 operator-() const noexcept
{
return {-this->x, -this->y, -this->z, -w};
}
[[nodiscard]]
[[nodiscard("You must use result vector")]]
constexpr Vector4 operator+(const Vector4& other) const noexcept
{
return {this->x + other.x, this->y + other.y, this->z + other.z, w + other.w};
}
[[nodiscard]]
[[nodiscard("You must use result vector")]]
constexpr Vector4 operator-(const Vector4& other) const noexcept
{
return {this->x - other.x, this->y - other.y, this->z - other.z, w - other.w};
}
[[nodiscard]]
[[nodiscard("You must use result vector")]]
constexpr Vector4 operator*(const Type& value) const noexcept
{
return {this->x * value, this->y * value, this->z * value, w * value};
}
[[nodiscard]]
[[nodiscard("You must use result vector")]]
constexpr Vector4 operator*(const Vector4& other) const noexcept
{
return {this->x * other.x, this->y * other.y, this->z * other.z, w * other.w};
}
[[nodiscard]]
[[nodiscard("You must use result vector")]]
constexpr Vector4 operator/(const Type& value) const noexcept
{
return {this->x / value, this->y / value, this->z / value, w / value};
}
[[nodiscard]]
[[nodiscard("You must use result vector")]]
constexpr Vector4 operator/(const Vector4& other) const noexcept
{
return {this->x / other.x, this->y / other.y, this->z / other.z, w / other.w};
}
[[nodiscard]]
[[nodiscard("You must use sum of elements")]]
constexpr Type sum() const noexcept
{
return Vector3<Type>::sum() + w;
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator<(const Vector4& other) const noexcept
{
return length() < other.length();
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator>(const Vector4& other) const noexcept
{
return length() > other.length();
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator<=(const Vector4& other) const noexcept
{
return length() <= other.length();
}
[[nodiscard]]
[[nodiscard("You must use comparison result")]]
bool operator>=(const Vector4& other) const noexcept
{
return length() >= other.length();
}
[[nodiscard]]
[[nodiscard("You must use array")]]
constexpr std::array<Type, 4> as_array() const noexcept
{
return {this->x, this->y, this->z, w};
}
#ifdef OMATH_IMGUI_INTEGRATION
[[nodiscard]]
[[nodiscard("You must use ImVec4")]]
constexpr ImVec4 to_im_vec4() const noexcept
{
return {
@@ -209,7 +211,7 @@ namespace omath
static_cast<float>(w),
};
}
[[nodiscard]]
[[nodiscard("You must use vector from ImVec4")]]
static Vector4<float> from_im_vec4(const ImVec4& other) noexcept
{
return {static_cast<Type>(other.x), static_cast<Type>(other.y), static_cast<Type>(other.z)};
@@ -220,7 +222,7 @@ namespace omath
template<> struct std::hash<omath::Vector4<float>>
{
[[nodiscard]]
[[nodiscard("You must use hash value")]]
std::size_t operator()(const omath::Vector4<float>& vec) const noexcept
{
std::size_t hash = 0;
@@ -237,13 +239,13 @@ template<> struct std::hash<omath::Vector4<float>>
template<class Type>
struct std::formatter<omath::Vector4<Type>> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
[[nodiscard("You must use parse iterator")]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
template<class FormatContext>
[[nodiscard]]
[[nodiscard("You must use format iterator")]]
static auto format(const omath::Vector4<Type>& vec, FormatContext& ctx)
{
if constexpr (std::is_same_v<typename FormatContext::char_type, char>)
+12 -6
View File
@@ -190,7 +190,8 @@ namespace omath::projection
return get_up();
}
[[nodiscard("You must use view-projection matrix")]] const Mat4X4Type& get_view_projection_matrix() const noexcept
[[nodiscard("You must use view-projection matrix")]]
const Mat4X4Type& get_view_projection_matrix() const noexcept
{
if (!m_view_projection_matrix.has_value())
m_view_projection_matrix = get_projection_matrix() * get_view_matrix();
@@ -313,7 +314,8 @@ namespace omath::projection
std::unreachable();
}
[[nodiscard("You must use frustum culling result")]] bool is_culled_by_frustum(const Triangle<Vector3<NumericType>>& triangle) const noexcept
[[nodiscard("You must use frustum culling result")]] bool
is_culled_by_frustum(const Triangle<Vector3<NumericType>>& triangle) const noexcept
{
// Transform to clip space (before perspective divide)
auto to_clip = [this](const Vector3<NumericType>& point)
@@ -380,7 +382,8 @@ namespace omath::projection
return false;
}
[[nodiscard("You must use AABB frustum culling result")]] bool is_aabb_culled_by_frustum(const primitives::Aabb<NumericType>& aabb) const noexcept
[[nodiscard("You must use AABB frustum culling result")]] bool
is_aabb_culled_by_frustum(const primitives::Aabb<NumericType>& aabb) const noexcept
{
// For each plane, find the AABB corner most in the direction of the plane normal
// (the "positive vertex"). If it's outside, the entire AABB is outside.
@@ -397,7 +400,8 @@ namespace omath::projection
return false;
}
[[nodiscard("You must use OBB frustum culling result")]] bool is_obb_culled_by_frustum(const primitives::Obb<NumericType>& obb) const noexcept
[[nodiscard("You must use OBB frustum culling result")]] bool
is_obb_culled_by_frustum(const primitives::Obb<NumericType>& obb) const noexcept
{
// For each plane, project the OBB extents onto the plane normal to get the
// effective radius, then test the center's signed distance against it.
@@ -545,7 +549,8 @@ namespace omath::projection
}
template<class Type>
[[nodiscard("You must use NDC bounds check result")]] constexpr static bool is_ndc_out_of_bounds(const Type& ndc) noexcept
[[nodiscard("You must use NDC bounds check result")]] constexpr static bool
is_ndc_out_of_bounds(const Type& ndc) noexcept
{
constexpr auto eps = std::numeric_limits<NumericType>::epsilon();
@@ -621,7 +626,8 @@ namespace omath::projection
}
template<ScreenStart screen_start = ScreenStart::TOP_LEFT_CORNER>
[[nodiscard("You must use NDC position")]] Vector3<NumericType> screen_to_ndc(const Vector3<NumericType>& screen_pos) const noexcept
[[nodiscard("You must use NDC position")]] Vector3<NumericType>
screen_to_ndc(const Vector3<NumericType>& screen_pos) const noexcept
{
if constexpr (screen_start == ScreenStart::TOP_LEFT_CORNER)
return {screen_pos.x / m_view_port.m_width * NumericType{2} - NumericType{1},