FastEngine 0.9.3
A multiplayer oriented 2D engine made with Vulkan.
Loading...
Searching...
No Matches
extra_function.inl
1/*
2 * Copyright 2024 Guillaume Guillet
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17namespace fge
18{
20char UnicodeToChar(uint32_t unicode)
21{
22 return (unicode < 128) ? static_cast<char>(unicode) : 0;
23}
24
25template<typename TFloat>
26inline TFloat LimitRangeAngle(TFloat angleDegree)
27{
28 static_assert(std::is_floating_point_v<TFloat>, "TFloat must be a floating point value");
29 angleDegree = static_cast<TFloat>(std::fmod(angleDegree, static_cast<TFloat>(360)));
30 if (angleDegree < static_cast<TFloat>(0))
31 {
32 angleDegree += static_cast<TFloat>(360.f);
33 }
34 return angleDegree;
35}
36
38inline bool
39IsVertexInCone(fge::Line const& line1, fge::Line const& line2, fge::Vector2f const& origin, fge::Vector2f const& vertex)
40{
41 auto const relativePos = vertex - origin;
42
43 auto const line1Product = fge::Cross2d(relativePos, line1.getDirection());
44 auto const line2Product = fge::Cross2d(relativePos, line2.getDirection());
45
46 return line1Product < 0.0f && line2Product > 0.0f;
47}
48inline bool IsVertexInCone(float coneAngle,
49 fge::Vector2f const& direction,
50 fge::Vector2f const& origin,
51 fge::Vector2f const& vertex)
52{
53 auto const demiConeAngle = glm::radians(coneAngle / 2.0f);
54
55 fge::Line const lineLeft{origin, glm::rotate(direction, -demiConeAngle), 1.0f};
56 fge::Line const lineRight{origin, glm::rotate(direction, demiConeAngle), 1.0f};
57
58 return fge::IsVertexInCone(lineLeft, lineRight, origin, vertex);
59}
60
62template<typename T>
63fge::Rect<T> ToRect(fge::Vector2<T> const& pos1, fge::Vector2<T> const& pos2)
64{
65 return fge::Rect<T>({(pos1.x < pos2.x) ? pos1.x : pos2.x, (pos1.y < pos2.y) ? pos1.y : pos2.y},
66 {(pos1.x > pos2.x) ? (pos1.x - pos2.x) : (pos2.x - pos1.x),
67 (pos1.y > pos2.y) ? (pos1.y - pos2.y) : (pos2.y - pos1.y)});
68}
69template<typename T>
70fge::Rect<T> ToRect(std::vector<fge::Vector2<T>> const& pos)
71{
72 float smallestX = std::numeric_limits<float>::max();
73 float biggestX = std::numeric_limits<float>::lowest();
74 float smallestY = std::numeric_limits<float>::max();
75 float biggestY = std::numeric_limits<float>::lowest();
76
77 for (std::size_t i = 0; i < pos.size(); ++i)
78 {
79 if (pos[i].x < smallestX)
80 {
81 smallestX = pos[i].x;
82 }
83 if (pos[i].x > biggestX)
84 {
85 biggestX = pos[i].x;
86 }
87 if (pos[i].y < smallestY)
88 {
89 smallestY = pos[i].y;
90 }
91 if (pos[i].y > biggestY)
92 {
93 biggestY = pos[i].y;
94 }
95 }
96
97 return fge::Rect<T>({smallestX, smallestY}, {biggestX - smallestX, biggestY - smallestY});
98}
99template<typename T>
100fge::Rect<T> ToRect(fge::Vector2<T> const* pos, std::size_t size)
101{
102 T smallestX = std::numeric_limits<T>::max();
103 T biggestX = std::numeric_limits<T>::lowest();
104 T smallestY = std::numeric_limits<T>::max();
105 T biggestY = std::numeric_limits<T>::lowest();
106
107 for (std::size_t i = 0; i < size; ++i)
108 {
109 if (pos[i].x < smallestX)
110 {
111 smallestX = pos[i].x;
112 }
113 if (pos[i].x > biggestX)
114 {
115 biggestX = pos[i].x;
116 }
117 if (pos[i].y < smallestY)
118 {
119 smallestY = pos[i].y;
120 }
121 if (pos[i].y > biggestY)
122 {
123 biggestY = pos[i].y;
124 }
125 }
126
127 return fge::Rect<T>({smallestX, smallestY}, {biggestX - smallestX, biggestY - smallestY});
128}
129
131template<typename T>
132T ReachValue(T value, T target, T speed, float deltaTime)
133{
134 float travelDistance = static_cast<float>(speed) * deltaTime;
135 float direction = (static_cast<float>(target) - static_cast<float>(value)) /
136 std::abs(static_cast<float>(target) - static_cast<float>(value));
137 T actualDistance = std::abs(target - value);
138
139 if (travelDistance >= actualDistance)
140 { //We already reached the target
141 return target;
142 }
143 return static_cast<T>(static_cast<float>(value) + direction * travelDistance);
144}
145
147inline constexpr float Cross2d(fge::Vector2f const& vec1, fge::Vector2f const& vec2)
148{
149 return glm::cross(fge::Vector3f{vec1, 0.0f}, fge::Vector3f{vec2, 0.0f}).z;
150}
151inline fge::Vector2f GetSegmentNormal(fge::Vector2f const& vec1, fge::Vector2f const& vec2)
152{
153 return glm::normalize(fge::Vector2f{vec1.y - vec2.y, vec2.x - vec1.x});
154}
155inline constexpr float GetAngle(fge::Vector2f const& vec)
156{
157 auto const angle = glm::degrees(std::atan2(vec.y, vec.x));
158 return angle < 0.0f ? angle + 360.0f : angle;
159}
160inline constexpr float GetAngleBetween(fge::Vector2f const& vec1, fge::Vector2f const& vec2)
161{
162 auto const angle = glm::degrees(std::atan2(fge::Cross2d(vec1, vec2), glm::dot(vec1, vec2)));
163 return angle < 0.0f ? angle + 360.0f : angle;
164}
165inline float GetDistanceBetween(fge::Vector2f const& vec1, fge::Vector2f const& vec2)
166{
167 return glm::length(vec2 - vec1);
168}
169inline float
170GetShortestDistanceBetween(fge::Vector2f const& point, fge::Vector2f const& lineStart, fge::Vector2f const& lineEnd)
171{
172 auto normalDir = glm::normalize(lineEnd - lineStart);
173 return std::abs((normalDir.y * (point.x - lineStart.x) - normalDir.x * (point.y - lineStart.y)) /
174 (normalDir.x * normalDir.x + normalDir.y * normalDir.y));
175}
176
177template<typename TIterator>
178TIterator GetNearestPoint(fge::Vector2f const& point, TIterator const& pointsBegin, TIterator const& pointsEnd)
179{
180 TIterator bestNearestPoint = pointsEnd;
181 float bestNearestDistance;
182
183 for (TIterator it = pointsBegin; it != pointsEnd; ++it)
184 {
185 float distance = fge::GetDistanceBetween(point, *it);
186 if (bestNearestPoint == pointsEnd)
187 {
188 bestNearestPoint = it;
189 bestNearestDistance = distance;
190 }
191 else
192 {
193 if (distance < bestNearestDistance)
194 {
195 bestNearestPoint = it;
196 bestNearestDistance = distance;
197 }
198 }
199 }
200
201 return bestNearestPoint;
202}
203
204inline constexpr fge::Vector2f GetForwardVector(float angle)
205{
206 angle = glm::radians(angle);
207 return {std::cos(angle), std::sin(angle)};
208}
209inline constexpr fge::Vector2f GetBackwardVector(float angle)
210{
211 angle = glm::radians(angle);
212 return -fge::Vector2f{std::cos(angle), std::sin(angle)};
213}
214inline constexpr fge::Vector2f GetLeftVector(float angle)
215{
216 angle = glm::radians(angle - 90.0f);
217 return {std::cos(angle), std::sin(angle)};
218}
219inline constexpr fge::Vector2f GetRightVector(float angle)
220{
221 angle = glm::radians(angle + 90.0f);
222 return {std::cos(angle), std::sin(angle)};
223}
224
225inline constexpr float DotSquare(fge::Vector2f const& vec)
226{
227 return glm::dot(vec, vec);
228}
229
230inline constexpr float GetHandedness(fge::Vector2f const& vec1, fge::Vector2f const& vec2, fge::Vector2f const& vec3)
231{
232 auto const edge1 = vec2 - vec1;
233 auto const edge2 = vec3 - vec2;
234
235 return fge::Cross2d(edge1, edge2);
236}
237
238inline constexpr float ConvertRange(float x, float xMin, float xMax, float yMin, float yMax)
239{
240 float const a = (yMax - yMin) / (xMax - xMin);
241 float const b = yMin - xMin * a;
242 return a * x + b;
243}
244inline constexpr fge::Vector2f ConvertRange(fge::Vector2f const& x,
245 fge::Vector2f const& xMin,
246 fge::Vector2f const& xMax,
247 fge::Vector2f const& yMin,
248 fge::Vector2f const& yMax)
249{
250 return fge::Vector2f{ConvertRange(x.x, xMin.x, xMax.x, yMin.x, yMax.x),
251 ConvertRange(x.y, xMin.y, xMax.y, yMin.y, yMax.y)};
252}
253
254inline constexpr fge::Vector2f MapCircleToSquareCoords(fge::Vector2f const& circleCoords)
255{
256 fge::Vector2f const circleCoordsPow2 = circleCoords * circleCoords;
257
258 return fge::Vector2f{0.5f * std::sqrt(2.0f + circleCoordsPow2.x - circleCoordsPow2.y +
259 2.0f * circleCoords.x * static_cast<float>(FGE_MATH_SQRT2)) -
260 0.5f * std::sqrt(2.0f + circleCoordsPow2.x - circleCoordsPow2.y -
261 2.0f * circleCoords.x * static_cast<float>(FGE_MATH_SQRT2)),
262 0.5f * std::sqrt(2.0f - circleCoordsPow2.x + circleCoordsPow2.y +
263 2.0f * circleCoords.y * static_cast<float>(FGE_MATH_SQRT2)) -
264 0.5f * std::sqrt(2.0f - circleCoordsPow2.x + circleCoordsPow2.y -
265 2.0f * circleCoords.y * static_cast<float>(FGE_MATH_SQRT2))};
266}
267inline constexpr fge::Vector2f MapSquareToCircleCoords(fge::Vector2f const& squareCoords)
268{
269 return fge::Vector2f{squareCoords.x * std::sqrt(1.0f - 0.5f * squareCoords.y * squareCoords.y),
270 squareCoords.y * std::sqrt(1.0f - 0.5f * squareCoords.x * squareCoords.x)};
271}
272
274inline fge::Color SetAlpha(fge::Color color, uint8_t alpha)
275{
276 color._a = alpha;
277 return color;
278}
279inline fge::Color SetRed(fge::Color color, uint8_t red)
280{
281 color._r = red;
282 return color;
283}
284inline fge::Color SetGreen(fge::Color color, uint8_t green)
285{
286 color._g = green;
287 return color;
288}
289inline fge::Color SetBlue(fge::Color color, uint8_t blue)
290{
291 color._b = blue;
292 return color;
293}
294
296template<class T>
297float DurationToSecondFloat(T duration)
298{
299 return std::chrono::duration<float, std::ratio<1, 1>>(duration).count();
300}
301
302} // namespace fge
Definition C_color.hpp:35
Definition C_rect.hpp:36
Definition extra_function.hpp:44