JacksEscape/types.c

175 lines
4.8 KiB
C
Raw Normal View History

2024-02-29 11:22:52 +08:00
2024-03-05 11:40:42 +08:00
#include "types.h"
2024-03-26 13:26:22 +08:00
#include "util/rand.h"
2024-03-04 15:05:21 +08:00
#include <math.h>
2024-03-07 09:55:36 +08:00
#include <stdio.h>
#include <stdlib.h>
2024-03-07 09:55:36 +08:00
#ifdef WIN32_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN
#endif
2024-03-01 15:06:58 +08:00
#include <windows.h>
2024-03-04 15:05:21 +08:00
#include <timeapi.h>
2024-02-29 11:22:52 +08:00
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;
}
2024-03-01 17:09:24 +08:00
const double EPS = 1e-6;
2024-02-29 11:22:52 +08:00
Vec2 vec2_Add(Vec2 x, Vec2 y) {
Vec2 result = {
.x = x.x + y.x,
.y = x.y + y.y};
return result;
}
2024-03-08 14:51:29 +08:00
Vec2 vec2_Minus(Vec2 pos, Vec2 neg) {
Vec2 result = {
.x = pos.x - neg.x,
.y = pos.y - neg.y};
return result;
}
2024-02-29 11:22:52 +08:00
Vec2 vec2_Scale(Vec2 v, double scale) {
Vec2 result = {
.x = v.x * scale,
.y = v.y * scale};
return result;
}
Vec2 vec2_Random(double minX, double maxX, double minY, double maxY) {
2024-03-26 13:26:22 +08:00
Vec2 result = {
.x = minX + (maxX - minX) * rand_Double01(),
.y = minY + (maxY - minY) * rand_Double01()};
return result;
}
2024-02-29 11:22:52 +08:00
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);
2024-03-05 10:42:17 +08:00
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);
2024-02-29 11:22:52 +08:00
// 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;
}
}
2024-02-29 16:51:46 +08:00
2024-03-07 09:55:36 +08:00
Vec2 box2_Center(Box2 box) {
return vec2(
box.lefttop.x + box.size.x / 2.0,
box.lefttop.y + box.size.y / 2.0);
}
2024-03-08 14:51:29 +08:00
Box2 box2_FromCenter(Vec2 center, Vec2 size) {
Box2 box = {
.size = size,
.lefttop = {
.x = center.x - size.x / 2.0,
.y = center.y - size.y / 2.0}};
return box;
}
2024-02-29 16:51:46 +08:00
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;
}
2024-03-01 14:37:59 +08:00
2024-03-01 15:06:58 +08:00
static double freqInverse = 0.0;
2024-03-04 15:05:21 +08:00
2024-03-07 09:55:36 +08:00
// https://stackoverflow.com/a/31411628
// "How to make thread sleep less than a millisecond on Windows"
typedef NTSTATUS(__stdcall *NtDelayExecution_Type)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
typedef NTSTATUS(__stdcall *ZwSetTimerResolution_Type)(IN ULONG RequestedResolution, IN BOOLEAN Set, OUT PULONG ActualResolution);
static NtDelayExecution_Type NtDelayExecution;
static ZwSetTimerResolution_Type ZwSetTimerResolution;
2024-03-04 15:05:21 +08:00
void duration_Sleep(const Duration t) {
2024-03-07 09:55:36 +08:00
if (!NtDelayExecution) {
NtDelayExecution = (NtDelayExecution_Type)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtDelayExecution");
ZwSetTimerResolution = (ZwSetTimerResolution_Type)GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwSetTimerResolution");
2024-03-07 09:55:36 +08:00
// Only run this once
ULONG actualResolution;
ZwSetTimerResolution(1, true, &actualResolution);
fprintf(stderr, "[duration_Sleep] ActualResolution was %u\n", actualResolution);
}
LARGE_INTEGER interval;
interval.QuadPart = t.microseconds * -10;
NtDelayExecution(false, &interval);
2024-03-04 15:05:21 +08:00
}
2024-03-01 15:06:58 +08:00
TimePoint time_Now() {
2024-03-01 14:37:59 +08:00
// Reference: https://github.com/SFML/SFML/blob/2.6.x/src/SFML/System/Win32/ClockImpl.cpp
2024-03-01 15:06:58 +08:00
if (freqInverse == 0.0) {
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
freqInverse = 1000000.0 / ((double)freq.QuadPart);
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
fprintf(stderr, "[time_Now] Frequency=%llu, Epoch=%llu\n", freq.QuadPart, time.QuadPart);
2024-03-01 15:06:58 +08:00
}
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};
2024-03-01 14:37:59 +08:00
return d;
}
2024-03-04 15:05:21 +08:00
Duration time_Reset(TimePoint *prev) {
TimePoint now = time_Now();
Duration d = time_Difference(now, *prev);
*prev = now;
return d;
}