122 lines
3.3 KiB
C
122 lines
3.3 KiB
C
|
|
#include "types.h"
|
|
#include <math.h>
|
|
#include <windows.h>
|
|
#include <timeapi.h>
|
|
|
|
static inline double dmin(double x, double y) {
|
|
return x < y ? x : y;
|
|
}
|
|
static inline double dmax(double x, double y) {
|
|
return x > y ? x : y;
|
|
}
|
|
|
|
const double EPS = 1e-6;
|
|
|
|
|
|
Vec2 vec2_Add(Vec2 x, Vec2 y) {
|
|
Vec2 result = {
|
|
.x = x.x + y.x,
|
|
.y = x.y + y.y};
|
|
return result;
|
|
}
|
|
|
|
Vec2 vec2_Scale(Vec2 v, double scale) {
|
|
Vec2 result = {
|
|
.x = v.x * scale,
|
|
.y = v.y * scale};
|
|
return result;
|
|
}
|
|
|
|
bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection) {
|
|
// Compute the min and max of the first rectangle on both axes
|
|
const double r1MinX = dmin(x.lefttop.x, x.lefttop.x + x.size.x);
|
|
const double r1MaxX = dmax(x.lefttop.x, x.lefttop.x + x.size.x);
|
|
const double r1MinY = dmin(x.lefttop.y, x.lefttop.y + x.size.y);
|
|
const double r1MaxY = dmax(x.lefttop.y, x.lefttop.y + x.size.y);
|
|
|
|
// Compute the min and max of the second rectangle on both axes
|
|
const double r2MinX = dmin(y.lefttop.x, y.lefttop.x + y.size.x);
|
|
const double r2MaxX = dmax(y.lefttop.x, y.lefttop.x + y.size.x);
|
|
const double r2MinY = dmin(y.lefttop.y, y.lefttop.y + y.size.y);
|
|
const double r2MaxY = dmax(y.lefttop.y, y.lefttop.y + y.size.y);
|
|
|
|
// Compute the intersection boundaries
|
|
const double interLeft = dmax(r1MinX, r2MinX);
|
|
const double interTop = dmax(r1MinY, r2MinY);
|
|
const double interRight = dmin(r1MaxX, r2MaxX);
|
|
const double interBottom = dmin(r1MaxY, r2MaxY);
|
|
|
|
// If the intersection is valid (positive non zero area), then there is an intersection
|
|
if ((interLeft < interRight) && (interTop < interBottom)) {
|
|
if (out_intersection) {
|
|
out_intersection->lefttop.x = interLeft;
|
|
out_intersection->lefttop.y = interTop;
|
|
out_intersection->size.x = interRight - interLeft;
|
|
out_intersection->size.y = interBottom - interTop;
|
|
}
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Box2 box2_Offset(Box2 box, Vec2 offset) {
|
|
box.lefttop = vec2_Add(box.lefttop, offset);
|
|
return box;
|
|
}
|
|
Box2 box2_OffsetX(Box2 box, double offsetX) {
|
|
box.lefttop.x += offsetX;
|
|
return box;
|
|
}
|
|
Box2 box2_OffsetY(Box2 box, double offsetY) {
|
|
box.lefttop.y += offsetY;
|
|
return box;
|
|
}
|
|
|
|
|
|
static double freqInverse = 0.0;
|
|
|
|
|
|
void duration_Sleep(const Duration t) {
|
|
if (t.microseconds <= 0)
|
|
return;
|
|
// https://learn.microsoft.com/zh-cn/windows/win32/api/timeapi/nf-timeapi-timebeginperiod
|
|
// timeBeginPeriod() and friends
|
|
TIMECAPS tc;
|
|
timeGetDevCaps(&tc, sizeof(TIMECAPS));
|
|
timeBeginPeriod(tc.wPeriodMin);
|
|
Sleep((DWORD)(round(duration_Milliseconds(t)))); // Only millisecond precision. Sad
|
|
timeEndPeriod(tc.wPeriodMin);
|
|
}
|
|
|
|
TimePoint time_Now() {
|
|
// Reference: https://github.com/SFML/SFML/blob/2.6.x/src/SFML/System/Win32/ClockImpl.cpp
|
|
|
|
if (freqInverse == 0.0) {
|
|
LARGE_INTEGER freq;
|
|
QueryPerformanceFrequency(&freq);
|
|
freqInverse = 1000000.0 / ((double)freq.QuadPart);
|
|
}
|
|
|
|
LARGE_INTEGER time;
|
|
QueryPerformanceCounter(&time);
|
|
|
|
TimePoint t = {.microseconds = (int64_t)(((double)time.QuadPart) * freqInverse)};
|
|
return t;
|
|
}
|
|
|
|
Duration time_Since(TimePoint prev) {
|
|
return time_Difference(time_Now(), prev);
|
|
}
|
|
Duration time_Difference(TimePoint now, TimePoint prev) {
|
|
Duration d = {.microseconds = now.microseconds - prev.microseconds};
|
|
return d;
|
|
}
|
|
Duration time_Reset(TimePoint *prev) {
|
|
TimePoint now = time_Now();
|
|
Duration d = time_Difference(now, *prev);
|
|
*prev = now;
|
|
return d;
|
|
}
|