Harmonic Flow Framework (libhffwk)
Cross platform C++ 2D Game Engine Framework
MathUtil.cpp
1 /*
2  Harmonic Flow Framework
3  Copyright (C) 2014-2018 Andreas Widen <andreas@harmonicflow.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "MathUtil.h"
22 
23 #include "platform/Environment.h"
24 #include "platform/Camera.h"
25 #include <stdlib.h>
26 #include <assert.h>
27 #include <math.h>
28 
29 using namespace HFCore;
30 
31 #include "debug/CrtDbgNew.h"
32 
34 {
35  glm::vec2 worldDimensions = HFCORE_CAMERA->getWorldDimensions();
36  fp32_hf screenWidth = (fp32_hf)HFCORE_ENV->getScreenWidth();
37  fp32_hf screenHeight = (fp32_hf)HFCORE_ENV->getScreenHeight();
38 
39  fp32_hf worldX = ((x / screenWidth) - 0.5f) * worldDimensions.x;
40  fp32_hf worldY = (0.5f - (y / screenHeight)) * worldDimensions.y;
41 
42  glm::vec2 camPos = HFCORE_CAMERA->getPositionV2();
43  Vector2 tmp(worldX + camPos.x, worldY + camPos.y);
44  Vector2 retval = rotate(tmp, HFCORE_CAMERA->getRotationZRad());
45 
46  return glm::vec2(retval.x, retval.y);
47 }
48 
49 glm::vec2 MathUtil::mapScreenToWorld(const glm::vec2 &screenPos)
50 {
51  return MathUtil::mapScreenToWorld(screenPos.x, screenPos.y);
52 }
53 
55 {
56  glm::vec2 worldPos(x, y);
57  return mapWorldToScreen(worldPos);
58 }
59 
60 glm::vec2 MathUtil::mapWorldToScreen(const glm::vec2 &worldPos)
61 {
62  fp32_hf screenWidth = (fp32_hf)HFCORE_ENV->getScreenWidth();
63  fp32_hf screenHeight = (fp32_hf)HFCORE_ENV->getScreenHeight();
64  Vector2 startingWorldCoords(worldPos.x, worldPos.y);
65  glm::vec2 camPos = HFCORE_CAMERA->getPositionV2();
66 
67  startingWorldCoords.x -= camPos.x;
68  startingWorldCoords.y -= camPos.y;
69  startingWorldCoords = rotate(startingWorldCoords,
70  HFCORE_CAMERA->getRotationZRad());
71 
72  glm::vec2 worldDimensions = HFCORE_CAMERA->getWorldDimensions();
73 
74  fp32_hf screenX = screenWidth * ((startingWorldCoords.x / worldDimensions.x) + 0.5f);
75  fp32_hf screenY = screenHeight - (screenHeight * (0.5f + (startingWorldCoords.y /
76  worldDimensions.y)));
77 
78  return glm::vec2(screenX, screenY);
79 }
80 
82 {
83  fp32_hf ratio = (HFCORE_ENV->getScreenWidth() /
84  HFCORE_CAMERA->getWorldDimensions().x);
85  return pixels / ratio;
86 }
87 
89 {
90  fp32_hf ratio = (HFCORE_ENV->getScreenWidth() /
91  HFCORE_CAMERA->getWorldDimensions().x);
92  return worldUnits * ratio;
93 }
94 
96 {
97  // change the 10 to a smaller/bigger number as needed
98  return (int32_hf)(10 * sqrtf(radius));
99 }
100 
102 {
103  return rad * 180.0f / HF_PI;
104 }
105 
107 {
108  return deg * HF_PI / 180.0f;
109 }
110 
112 {
113  return d < 0.0f ? ceil(d - 0.5f) : floor(d + 0.5f);
114 }
115 
117 {
118  fp32_hf normalized = d / n;
119  fp32_hf normalizedRounded = MathUtil::roundf(normalized);
120  return (normalizedRounded * n);
121 }
122 
124 {
125  fp32_hf dx = x1 - x0;
126  fp32_hf dy = y1 - y0;
127  return sqrtf(dx * dx + dy * dy);
128 }
129 
130 fp32_hf MathUtil::dist(const Vector2 &p0, const Vector2 &p1)
131 {
132  fp32_hf dx = p1.x - p0.x;
133  fp32_hf dy = p1.y - p0.y;
134  return sqrtf(dx * dx + dy * dy);
135 }
136 
138 {
139  fp32_hf dx = p.x - x;
140  fp32_hf dy = p.y - y;
141  return sqrtf(dx * dx + dy * dy);
142 }
143 
145  const Vector2 &l1)
146 {
147  fp32_hf ldx = l1.x - l0.x; // dx for line
148  fp32_hf ldy = l1.y - l0.y; // dy for line
149  return fabs(ldx * (l0.y - p.y) - (l0.x - p.x) * ldy) / sqrtf(ldx * ldx + ldy * ldy);
150 }
151 
153  fp32_hf l0x, fp32_hf l0y,
154  fp32_hf l1x, fp32_hf l1y)
155 {
156  fp32_hf ldx = l1x - l0x; // dx for line
157  fp32_hf ldy = l1y - l0y; // dy for line
158  return fabs(ldx * (l0y - py) - (l0x - px) * ldy) / sqrtf(ldx * ldx + ldy * ldy);
159 }
160 
162 {
163  srand(seed);
164 }
165 
167 {
168  assert(max >= min);
169  return min + ((fp32_hf)rand() / RAND_MAX) * (max - min);
170 }
171 
173 {
174  assert(max >= min);
175  return min + (rand() % (max - min + 1));
176 }
177 
179  const Vector2 &l1)
180 {
181  // calculate the normal along the line:
182  Vector2 n = (l1 - l0);
183  n /= n.magnitude();
184 
185  return l0 * 2 - p + n * 2 * (p - l0).dot(n);
186 }
187 
189 {
190  return acos(v0.dot(v1) / (v0.magnitude() * v1.magnitude()));
191 }
192 
194 {
195  fp32_hf angleRad = getAngleInRadBetween(v0, v1);
196  return rad2deg(angleRad);
197 }
198 
200  fp32_hf angleRad)
201 {
202  Vector2 d = p1 - p0;
203 
204  return p0 + Vector2(
205  d.x * cos(angleRad) - d.y * sin(angleRad),
206  d.x * sin(angleRad) + d.y * cos(angleRad));
207 }
208 
210 {
211  return Vector2(
212  p.x * cos(angleRad) - p.y * sin(angleRad),
213  p.x * sin(angleRad) + p.y * cos(angleRad));
214 }
215 
217  fp32_hf x2, fp32_hf y2,
218  fp32_hf x3, fp32_hf y3,
219  fp32_hf x4, fp32_hf y4,
220  Vector2 &intersectPoint,
221  bool allowOffSegment)
222 {
223  // let's find the intersection of lines L12 and L34:
224  fp32_hf a1 = y2 - y1;
225  fp32_hf b1 = x1 - x2;
226  fp32_hf c1 = x2 * y1 - x1 * y2;
227  fp32_hf a2 = y4 - y3;
228  fp32_hf b2 = x3 - x4;
229  fp32_hf c2 = x4 * y3 - x3 * y4;
230  fp32_hf denom = a1 * b2 - a2 * b1;
231  if (denom == 0)
232  {
233  // these lines never intersect
234  return false;
235  }
236  fp32_hf x = (b1 * c2 - b2 * c1) / denom;
237  fp32_hf y = (a2 * c1 - a1 * c2) / denom;
238 
239  // check if this intersection in within this specific segment
240  fp32_hf d0 = dist(x3, y3, x4, y4);
241  fp32_hf d1 = dist(x, y, x3, y3);
242  fp32_hf d2 = dist(x, y, x4, y4);
243  bool onSegment = (d0 >= d1 && d0 >= d2);
244 
245  if (onSegment || allowOffSegment)
246  {
247  intersectPoint.x = x;
248  intersectPoint.y = y;
249  }
250 
251  return onSegment;
252 }
253 
255  const Vector2 &lp1,
256  const Vector2 &p)
257 {
258  fp32_hf dx = lp1.x - lp0.x;
259  fp32_hf dy = lp1.y - lp0.y;
260 
261  fp32_hf perpdx = dy;
262  fp32_hf perpdy = -dx;
263 
264  Vector2 closestPoint;
266  lp0.x, lp0.y,
267  lp1.x, lp1.y,
268  p.x - 10 * perpdx, p.y - 10 * perpdy,
269  p.x + 10 * perpdx, p.y + 10 * perpdy,
270  closestPoint,
271  false);
272 
273  return closestPoint;
274 }
275 
277 {
278  assert(t1 > t0);
279  assert(t >= t0);
280  assert(t <= t1);
281 
282  return v0 + (v1 - v0) * (t - t0) / (t1 - t0);
283 }
284 
286 {
287  assert(t1 > t0);
288  assert(t >= t0);
289  assert(t <= t1);
290 
291  return static_cast<int32_hf>(v0 + (v1 - v0) * (t - t0) / (t1 - t0));
292 }
293 
295 {
296  assert(t1 > t0);
297  assert(t >= t0);
298  assert(t <= t1);
299 
300  int32_hf r0 = c0 & 0xff0000;
301  int32_hf g0 = c0 & 0x00ff00;
302  int32_hf b0 = c0 & 0x0000ff;
303 
304  int32_hf r1 = c1 & 0xff0000;
305  int32_hf g1 = c1 & 0x00ff00;
306  int32_hf b1 = c1 & 0x0000ff;
307 
308  return
309  (interpolatei(r0, r1, t0, t1, t) & 0xff0000) |
310  (interpolatei(g0, g1, t0, t1, t) & 0x00ff00) |
311  (interpolatei(b0, b1, t0, t1, t) & 0x0000ff);
312 }
313 
315  fp32_hf x1, fp32_hf y1, fp32_hf r1,
316  fp32_hf *xi0, fp32_hf *yi0,
317  fp32_hf *xi1, fp32_hf *yi1)
318 {
319  fp32_hf a, dx, dy, d, h, rx, ry;
320  fp32_hf x2, y2;
321 
322  // dx and dy are the vertical and horizontal distances between the circle centers:
323  dx = x1 - x0;
324  dy = y1 - y0;
325 
326  // Determine the straight-line distance between the centers:
327  d = sqrtf(dx * dx + dy * dy);
328 
329  // Check for solvability
330  if (d > (r0 + r1))
331  {
332  // no solution, circles do not intersect:
333  return false;
334  }
335 
336  if (d < fabs(r0 - r1))
337  {
338  // no solution, one circle is contained in the other:
339  return 0;
340  }
341 
342  // 'point 2' is the point where the line through the circle intersection
343  // points crosses the line between the circle centers.
344 
345  // Determine the distance from point 0 to point 2:
346  a = ((r0 * r0) - (r1 * r1) + (d * d)) / (2.0f * d) ;
347 
348  // Determine the coordinates of point 2:
349  x2 = x0 + (dx * a / d);
350  y2 = y0 + (dy * a / d);
351 
352  // Determine the distance from point 2 to either of the intersection points:
353  h = sqrtf((r0 * r0) - (a * a));
354 
355  // Now determine the offsets of the intersection points from point 2:
356  rx = -dy * (h / d);
357  ry = dx * (h / d);
358 
359  // Determine the absolute intersection points:
360  *xi0 = x2 + rx;
361  *xi1 = x2 - rx;
362  *yi0 = y2 + ry;
363  *yi1 = y2 - ry;
364 
365  return true;
366 }
367 
369 {
370  uint32_hf i = 1;
371 
372  while (i < num)
373  {
374  i *= 2;
375  }
376 
377  return i;
378 }
379 
381 {
382  uint32_hf i = 1;
383 
384  while ((i * 2) < num)
385  {
386  i *= 2;
387  }
388 
389  return i;
390 }
static fp32_hf roundToNearestMultipleOf(fp32_hf d, fp32_hf n)
Round d to nearest multiple of n integral (as a floating-point value).
Definition: MathUtil.cpp:116
unsigned int uint32_hf
A type definition for unsigned int.
Definition: HFDataTypes.h:354
static int32_hf interpolateColor(int32_hf c0, int32_hf c1, fp32_hf t0, fp32_hf t1, fp32_hf t)
Linearly interpolates a given set of colors c0 and c1 (time based).
Definition: MathUtil.cpp:294
fp32_hf x
X coordinate of the vector.
Definition: Vector2.h:284
static bool intersectCircles(fp32_hf x0, fp32_hf y0, fp32_hf r0, fp32_hf x1, fp32_hf y1, fp32_hf r1, fp32_hf *xi0, fp32_hf *yi0, fp32_hf *xi1, fp32_hf *yi1)
Determine if two circles intersect.
Definition: MathUtil.cpp:314
#define HFCORE_CAMERA
Get HFCore::Camera instance shortcut macro.
Definition: Environment.h:118
Interface useful for controlling the Camera.
static fp32_hf getAngleInRadBetween(const Vector2 &v0, const Vector2 &v1)
Get the angle in radians of line between the two points v0 and v1.
Definition: MathUtil.cpp:188
fp32_hf dot(const Vector2 &v) const
Get the dot product of two vectors.
Definition: Vector2.h:191
int int32_hf
A type definition for int.
Definition: HFDataTypes.h:349
static uint32_hf findHighestPowerOf2SmallerThan(uint32_hf num)
Find highest power of two smaller than num.
Definition: MathUtil.cpp:380
static fp32_hf rad2deg(fp32_hf rad)
Convert radians to degrees.
Definition: MathUtil.cpp:101
static Vector2 rotate(const Vector2 &p1, const Vector2 &p0, fp32_hf angleRad)
Rotate a point p1 around the point p0.
Definition: MathUtil.cpp:199
static glm::vec2 mapWorldToScreen(fp32_hf x, fp32_hf y)
Convert world coordinates to screen (pixel) coordinates.
Definition: MathUtil.cpp:54
static fp32_hf dist(fp32_hf x0, fp32_hf y0, fp32_hf x1, fp32_hf y1)
Get the distance between the two points (x0, y0) and (x1, y1).
Definition: MathUtil.cpp:123
static uint32_hf findNextHigherPowerOf2(uint32_hf num)
Find next power of two value given num.
Definition: MathUtil.cpp:368
static glm::vec2 mapScreenToWorld(fp32_hf x, fp32_hf y)
Convert screen (pixel) coordinates to world coordinates.
Definition: MathUtil.cpp:33
static fp32_hf interpolatef(fp32_hf v0, fp32_hf v1, fp32_hf t0, fp32_hf t1, fp32_hf t)
Linearly interpolates a given set of floating points v0 and v1 (time based).
Definition: MathUtil.cpp:276
A two-dimensional floating point vector and associated math functions.
Definition: Vector2.h:42
static fp32_hf roundf(fp32_hf d)
Round d to nearest integral (as a floating-point value).
Definition: MathUtil.cpp:111
static fp32_hf pixelsToWorldUnits(fp32_hf pixels)
Take a number of pixels and find out how many world units they cover.
Definition: MathUtil.cpp:81
static bool getIntersectPoint(fp32_hf x1, fp32_hf y1, fp32_hf x2, fp32_hf y2, fp32_hf x3, fp32_hf y3, fp32_hf x4, fp32_hf y4, Vector2 &intersectPoint, bool allowOffSegment=false)
Determine whether or not two lines intersect, and if they do, set intersection point.
Definition: MathUtil.cpp:216
static fp32_hf worldUnitsToPixels(fp32_hf worldUnits)
Take a number of world units and find out how many pixels stretch across that distance.
Definition: MathUtil.cpp:88
static Vector2 closestPointOnLine(const Vector2 &lp0, const Vector2 &lp1, const Vector2 &p)
Get closest point on line (lp0, lp1) for point p.
Definition: MathUtil.cpp:254
Interface for math related helper methods.
static fp32_hf getAngleInDegBetween(const Vector2 &v0, const Vector2 &v1)
Get the angle in degrees of line between the two points v0 and v1.
Definition: MathUtil.cpp:193
fp32_hf y
Y coordinate of the vector.
Definition: Vector2.h:289
#define HF_PI
The number PI is a mathematical constant, the ratio of a circle&#39;s circumference to its diameter...
Definition: HFDataTypes.h:35
static void seedRand(uint32_hf seed)
Initialize random number generator.
Definition: MathUtil.cpp:161
Definition: Actor.h:34
static fp32_hf distPointToLine(const Vector2 &p, const Vector2 &l0, const Vector2 &l1)
Get the distance between the point p and line specified as l0 and l1.
Definition: MathUtil.cpp:144
Singleton interface for platform specific things.
static fp32_hf deg2rad(fp32_hf deg)
Convert degrees to radians.
Definition: MathUtil.cpp:106
static fp32_hf randf(fp32_hf min, fp32_hf max)
Get random floating point value between min and max.
Definition: MathUtil.cpp:166
#define HFCORE_ENV
Get HFCore::Environment instance shortcut macro.
Definition: Environment.h:68
fp32_hf magnitude() const
Get the absolute magnitude of the vector.
Definition: Vector2.h:215
static Vector2 reflect(const Vector2 &p, const Vector2 &l0, const Vector2 &l1)
Reflect a point p off a line l that passes through the two points l0 and l1.
Definition: MathUtil.cpp:178
float fp32_hf
A type definition for float.
Definition: HFDataTypes.h:359
static int32_hf interpolatei(int32_hf v0, int32_hf v1, fp32_hf t0, fp32_hf t1, fp32_hf t)
Linearly interpolates a given set of integer points v0 and v1 (time based).
Definition: MathUtil.cpp:285
static int32_hf getNumCircleSegments(fp32_hf radius)
Get optimal number of segments needed for a given radius.
Definition: MathUtil.cpp:95
static int32_hf randi(int32_hf min, int32_hf max)
Get random integer value between min and max.
Definition: MathUtil.cpp:172