mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Add srb2::math, fixed-point, vector, line and slope formula classes
- srb2::math::Fixed
- Operator overloads for FixedMul and FixedDiv
- Implicit conversion between fixed_t, Fixed and
floating-point types
- srb2::math::Vec2
- Template to any type
- Operator overloads for arithmetic operations
- Convertible between different types
- srb2::math::LineSegment
- Template to any type
- Holds two Vec2 instances
- Sorting methods and vertical/horizontal test
- srb2::math::LineEquation
- Slope formula from LineSegment
- y method to find y from x
- Intersect algorithm
- Fixed-point specialization to avoid overflows
- srb2::math::LineEquationX
- Inherits LineEquation
- x method to find x from y
This commit is contained in:
parent
6686215330
commit
37f2384229
5 changed files with 370 additions and 0 deletions
107
src/math/fixed.hpp
Normal file
107
src/math/fixed.hpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef math_fixed_hpp
|
||||
#define math_fixed_hpp
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "traits.hpp"
|
||||
|
||||
#include "../m_fixed.h"
|
||||
|
||||
namespace srb2::math
|
||||
{
|
||||
|
||||
struct Fixed
|
||||
{
|
||||
static Fixed copysign(fixed_t x, fixed_t y) { return (x < 0) != (y < 0) ? -x : x; }
|
||||
static Fixed hypot(fixed_t x, fixed_t y) { return FixedHypot(x, y); }
|
||||
|
||||
constexpr Fixed() : val_(0) {}
|
||||
constexpr Fixed(fixed_t val) : val_(val) {}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
|
||||
Fixed(T val) : val_(FloatToFixed(val)) {}
|
||||
|
||||
Fixed(const Fixed& b) = default;
|
||||
Fixed& operator=(const Fixed& b) = default;
|
||||
|
||||
fixed_t value() const { return val_; }
|
||||
int sign() const { return val_ < 0 ? -1 : 1; }
|
||||
|
||||
operator fixed_t() const { return val_; }
|
||||
explicit operator float() const { return FixedToFloat(val_); }
|
||||
|
||||
Fixed& operator+=(const Fixed& b)
|
||||
{
|
||||
val_ += b.val_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Fixed& operator-=(const Fixed& b)
|
||||
{
|
||||
val_ -= b.val_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Fixed& operator*=(const Fixed& b)
|
||||
{
|
||||
val_ = FixedMul(val_, b.val_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Fixed& operator/=(const Fixed& b)
|
||||
{
|
||||
val_ = FixedDiv(val_, b.val_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Fixed operator-() const { return -val_; }
|
||||
|
||||
#define X(op) \
|
||||
template <typename T> \
|
||||
Fixed operator op(const T& b) const { return val_ op b; } \
|
||||
Fixed operator op(const Fixed& b) const \
|
||||
{ \
|
||||
Fixed f{val_};\
|
||||
f op##= b;\
|
||||
return f;\
|
||||
} \
|
||||
template <typename T> \
|
||||
Fixed& operator op##=(const T& b) \
|
||||
{ \
|
||||
val_ op##= b; \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
X(+)
|
||||
X(-)
|
||||
X(*)
|
||||
X(/)
|
||||
|
||||
#undef X
|
||||
|
||||
private:
|
||||
fixed_t val_;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Traits<Fixed>
|
||||
{
|
||||
static constexpr Fixed kZero = 0;
|
||||
static constexpr Fixed kUnit = FRACUNIT;
|
||||
|
||||
static constexpr auto copysign = Fixed::copysign;
|
||||
static constexpr auto hypot = Fixed::hypot;
|
||||
};
|
||||
|
||||
}; // namespace srb2::math
|
||||
|
||||
#endif/*math_fixed_hpp*/
|
||||
102
src/math/line_equation.hpp
Normal file
102
src/math/line_equation.hpp
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef math_line_equation_hpp
|
||||
#define math_line_equation_hpp
|
||||
|
||||
#include "fixed.hpp"
|
||||
#include "line_segment.hpp"
|
||||
#include "vec.hpp"
|
||||
|
||||
namespace srb2::math
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct LineEquation
|
||||
{
|
||||
using vec2 = Vec2<T>;
|
||||
using line_segment = LineSegment<T>;
|
||||
|
||||
// Fixed-point: shift value by this amount during
|
||||
// multiplications and divisions to avoid overflows.
|
||||
static constexpr std::enable_if_t<std::is_same_v<T, Fixed>, fixed_t> kF = 1024; // fixed_t, not Fixed
|
||||
|
||||
LineEquation() {}
|
||||
LineEquation(const vec2& p, const vec2& d) : d_(d), m_(d.y / d.x), b_(p.y - (p.x * m())) {}
|
||||
LineEquation(const line_segment& l) : LineEquation(l.a, l.b - l.a) {}
|
||||
|
||||
const vec2& d() const { return d_; }
|
||||
T m() const { return m_; }
|
||||
T b() const { return b_; }
|
||||
T y(T x) const { return (m() * x) + b(); }
|
||||
|
||||
vec2 intersect(const LineEquation& q) const
|
||||
{
|
||||
T x = (b() - q.b()) / (q.m() - m());
|
||||
return {x, y(x)};
|
||||
}
|
||||
|
||||
protected:
|
||||
vec2 d_{};
|
||||
T m_{}, b_{};
|
||||
};
|
||||
|
||||
template <>
|
||||
inline LineEquation<Fixed>::LineEquation(const vec2& p, const vec2& d) :
|
||||
d_(d), m_((d.y / d.x) / kF), b_((p.y / kF) - (p.x * m_))
|
||||
{
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Fixed LineEquation<Fixed>::m() const
|
||||
{
|
||||
return m_ * kF;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Fixed LineEquation<Fixed>::b() const
|
||||
{
|
||||
return b_ * kF;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Fixed LineEquation<Fixed>::y(Fixed x) const
|
||||
{
|
||||
return ((m_ * x) + b_) * kF;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline LineEquation<Fixed>::vec2 LineEquation<Fixed>::intersect(const LineEquation& q) const
|
||||
{
|
||||
Fixed x = ((b_ - q.b_) / ((q.m_ - m_) * kF)) * kF;
|
||||
return {x, y(x)};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct LineEquationX : LineEquation<T>
|
||||
{
|
||||
T x(T y) const { return (y - LineEquation<T>::b()) / LineEquation<T>::m(); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct LineEquationX<Fixed> : LineEquation<Fixed>
|
||||
{
|
||||
LineEquationX() {}
|
||||
LineEquationX(const vec2& p, const vec2& d) : LineEquation(p, d), w_((d.x / d.y) / kF), a_((p.x / kF) - (p.y * w_)) {}
|
||||
LineEquationX(const line_segment& l) : LineEquationX(l.a, l.b - l.a) {}
|
||||
|
||||
Fixed x(Fixed y) const { return ((w_ * y) + a_) * kF; }
|
||||
|
||||
protected:
|
||||
Fixed w_{}, a_{};
|
||||
};
|
||||
|
||||
}; // namespace srb2::math
|
||||
|
||||
#endif/*math_line_equation_hpp*/
|
||||
43
src/math/line_segment.hpp
Normal file
43
src/math/line_segment.hpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef math_line_segment_hpp
|
||||
#define math_line_segment_hpp
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "vec.hpp"
|
||||
|
||||
namespace srb2::math
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct LineSegment
|
||||
{
|
||||
using vec2 = Vec2<T>;
|
||||
using view = std::pair<const vec2&, const vec2&>;
|
||||
|
||||
vec2 a, b;
|
||||
|
||||
LineSegment(vec2 a_, vec2 b_) : a(a_), b(b_) {}
|
||||
|
||||
template <typename U>
|
||||
LineSegment(const LineSegment<U>& b) : LineSegment(b.a, b.b) {}
|
||||
|
||||
bool horizontal() const { return a.y == b.y; }
|
||||
bool vertical() const { return a.x == b.x; }
|
||||
|
||||
view by_x() const { return std::minmax(a, b, [](auto& a, auto& b) { return a.x < b.x; }); }
|
||||
view by_y() const { return std::minmax(a, b, [](auto& a, auto& b) { return a.y < b.y; }); }
|
||||
};
|
||||
|
||||
}; // namespace srb2
|
||||
|
||||
#endif/*math_line_segment_hpp*/
|
||||
34
src/math/traits.hpp
Normal file
34
src/math/traits.hpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef math_traits_hpp
|
||||
#define math_traits_hpp
|
||||
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
|
||||
namespace srb2::math
|
||||
{
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct Traits;
|
||||
|
||||
template <typename T>
|
||||
struct Traits<T, std::enable_if_t<std::is_floating_point_v<T>>>
|
||||
{
|
||||
static constexpr T kZero = 0.0;
|
||||
static constexpr T kUnit = 1.0;
|
||||
|
||||
static T copysign(T x, T y) { return std::copysign(x, y); }
|
||||
static T hypot(T x, T y) { return std::hypot(x, y); }
|
||||
};
|
||||
|
||||
}; // namespace srb2::math
|
||||
|
||||
#endif/*math_traits_hpp*/
|
||||
84
src/math/vec.hpp
Normal file
84
src/math/vec.hpp
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef math_vec_hpp
|
||||
#define math_vec_hpp
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "traits.hpp"
|
||||
|
||||
namespace srb2::math
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct Vec2
|
||||
{
|
||||
T x, y;
|
||||
|
||||
Vec2() : x{}, y{} {}
|
||||
Vec2(T x_, T y_) : x(x_), y(y_) {}
|
||||
Vec2(T z) : x(z), y(z) {}
|
||||
|
||||
template <typename U>
|
||||
Vec2(const Vec2<U>& b) : Vec2(b.x, b.y) {}
|
||||
|
||||
T magnitude() const { return Traits<T>::hypot(x, y); }
|
||||
Vec2 normal() const { return {-y, x}; }
|
||||
|
||||
#define X(op) \
|
||||
Vec2& operator op##=(const Vec2& b) \
|
||||
{ \
|
||||
x op##= b.x; \
|
||||
y op##= b.y; \
|
||||
return *this; \
|
||||
} \
|
||||
Vec2 operator op(const Vec2& b) const { return Vec2(x op b.x, y op b.y); } \
|
||||
|
||||
X(+)
|
||||
X(-)
|
||||
X(*)
|
||||
X(/)
|
||||
|
||||
#undef X
|
||||
|
||||
Vec2 operator-() const { return Vec2(-x, -y); }
|
||||
};
|
||||
|
||||
template <typename>
|
||||
struct is_vec2 : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_vec2<Vec2<T>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_vec2_v = is_vec2<T>::value;
|
||||
|
||||
#define X(op) \
|
||||
template <typename T, typename U, std::enable_if_t<!is_vec2_v<T>, bool> = true> \
|
||||
Vec2<T> operator op(const T& a, const Vec2<U>& b) \
|
||||
{ \
|
||||
return Vec2 {a} op Vec2<T> {b}; \
|
||||
} \
|
||||
template <typename T, typename U, std::enable_if_t<!is_vec2_v<U>, bool> = true> \
|
||||
Vec2<U> operator op(const Vec2<T>& a, const U& b) \
|
||||
{ \
|
||||
return Vec2<U> {a} op Vec2 {b}; \
|
||||
} \
|
||||
|
||||
X(+)
|
||||
X(-)
|
||||
X(*)
|
||||
X(/)
|
||||
|
||||
#undef X
|
||||
|
||||
}; // namespace srb2::math
|
||||
|
||||
#endif/*math_vec_hpp*/
|
||||
Loading…
Add table
Reference in a new issue