Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
PieceInterpolation.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cmath>
5
6namespace monopoly::pieces
7{
8 namespace
9 {
10 [[nodiscard]] float magnitude(InterpolationVec3 v) noexcept
11 { return std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z); }
12
13 [[nodiscard]] InterpolationVec3 normalized(InterpolationVec3 v) noexcept
14 {
15 const float length = magnitude(v);
16 if (length <= 0.00001F) return {};
17 return v * (1.0F / length);
18 }
19
20 [[nodiscard]] InterpolationVec3 bezier(float ratio,
21 const std::array<InterpolationVec3, 4>& p) noexcept
22 {
23 const float u = 1.0F - ratio;
24 const float b0 = u * u * u;
25 const float b1 = 3.0F * ratio * u * u;
26 const float b2 = 3.0F * ratio * ratio * u;
27 const float b3 = ratio * ratio * ratio;
28 return b0 * p[0] + b1 * p[1] + b2 * p[2] + b3 * p[3];
29 }
30
31 [[nodiscard]] float adjustedRatio(float ratio, InterpolationSpeed speed) noexcept
32 {
33 ratio = std::clamp(ratio, 0.0F, 1.0F);
36 {
37 constexpr float Pi = 3.14159265358979323846F;
38 if (ratio < 0.5F)
39 return 0.5F - 0.5F * std::cos(ratio * Pi);
40 return 0.5F + 0.5F * std::sin((ratio - 0.5F) * Pi);
41 }
42 return ratio;
43 }
44 }
45
49 float tangentDelta) noexcept
50 {
52 path.segments[index] = {a, b, c, d};
53 path.tangentDeltas[index] = tangentDelta;
54 if (index == path.used && path.used < BezierMaxSegments)
55 ++path.used;
56 path.lengths[index] = magnitude(d - c) +
57 magnitude(c - b) + magnitude(b - a);
58 return true;
59 }
60
63 float tangentDelta) noexcept
64 {
66 if (index < 1) return false;
67 const auto a = path.segments[index - 1][3];
68 const auto b = a + (a - path.segments[index - 1][2]);
70 }
71
73 const PieceInterpolationPath& path, std::uint64_t tick) noexcept
74 {
76 std::size_t used = path.used;
77 if (used >= BezierMaxSegments) used = BezierMaxSegments - 1;
78 if (used == 0) return result;
79
80 float ratio = 1.0F;
81 if (path.endTick != path.startTick)
82 {
83 const auto current = tick < path.startTick ? path.startTick : tick;
84 ratio = static_cast<float>(current - path.startTick) /
85 static_cast<float>(path.endTick - path.startTick);
86 }
87 ratio = adjustedRatio(ratio, path.speed);
88 result.ratio = ratio;
89
90 float total{};
91 for (std::size_t i = 0; i < used; ++i) total += path.lengths[i];
92 if (total == 0.0F) total = static_cast<float>(used);
93
94 std::size_t segment{};
95 float start{};
96 float end{};
97 for (; segment < used; ++segment)
98 {
99 end += path.lengths[segment] == 0.0F ? 1.0F : path.lengths[segment];
100 if ((end / total + 0.000001F) >= ratio) break;
101 start = end;
102 }
103 if (segment >= used) segment = used - 1;
104
105 float localRatio = ratio;
106 if (used > 1)
107 {
108 const float segmentLength = end - start;
109 localRatio = segmentLength == 0.0F ? 1.0F :
110 (ratio - start / total) / (segmentLength / total);
111 }
112
113 result.segment = segment;
114 result.location = bezier(localRatio, path.segments[segment]);
115 const auto nearby = bezier(
116 localRatio + path.tangentDeltas[segment], path.segments[segment]);
117 const auto tangent = nearby - result.location;
118 if (magnitude(tangent) > 0.00001F)
119 result.forward = normalized(tangent);
120 result.up = {0.0F, 1.0F, 0.0F};
121 return result;
122 }
123}
unsigned index
std::string path
std::uint8_t speed
Definition Timers.cpp:19
PieceInterpolationSample samplePieceInterpolation(const PieceInterpolationPath &path, std::uint64_t tick) noexcept
constexpr std::size_t BezierMaxSegments
bool addBezierSegmentSmooth(PieceInterpolationPath &path, std::size_t index, InterpolationVec3 c, InterpolationVec3 d, float tangentDelta) noexcept
bool addBezierSegment(PieceInterpolationPath &path, std::size_t index, InterpolationVec3 a, InterpolationVec3 b, InterpolationVec3 c, InterpolationVec3 d, float tangentDelta) noexcept