RogueLife/src/geometry.h

117 lines
2.5 KiB
C

//---
// geometry: Geometry utilities
//---
#pragma once
#include "fixed.h"
#include <stdbool.h>
#include <stdlib.h>
/* Directions */
enum { UP=0, RIGHT=1, DOWN=2, LEFT=3 };
//---
// Geometric primitives; the engine types are the fixed-point versions, but the
// integer versions are useful as input/output, either to specify model data or
// to draw to screen using pixel-based methods.
//---
struct fpoint {
fixed_t x, y;
};
struct ipoint {
int16_t x, y;
};
struct frect {
/* Left edge, right edge */
fixed_t l, r;
/* Top edge, bottom edge */
fixed_t t, b;
};
struct irect {
int16_t l, r;
int16_t t, b;
};
typedef struct fpoint fpoint_t;
typedef struct ipoint ipoint_t;
typedef struct frect frect_t;
typedef struct irect irect_t;
/* Functions converting integer shapes to fixed-point. */
fpoint_t point_i2f(ipoint_t);
frect_t rect_i2f(irect_t);
/* Same as point_i2f() but adds +0.5 at each coordinate. */
fpoint_t point_i2f_center(ipoint_t);
/* Functions converting fixed-point shapes to integer. */
ipoint_t point_f2i(fpoint_t);
irect_t rect_f2i(frect_t);
//---
// Point operations
//---
/* Distance-squared between two points */
static inline fixed_t dist2(fpoint_t p1, fpoint_t p2)
{
fixed_t dx = p2.x - p1.x;
fixed_t dy = p2.y - p1.y;
return fmul(dx, dx) + fmul(dy, dy);
}
/* Unit vector in the specified direction */
static inline fpoint_t fdir(int dir)
{
return (fpoint_t){
.x = fix((dir == RIGHT) - (dir == LEFT)),
.y = fix((dir == DOWN) - (dir == UP)),
};
}
/* Direction closest to specified vector */
static inline int frdir(fpoint_t v)
{
if(v.x >= abs(v.y)) return RIGHT;
if(v.x <= -abs(v.y)) return LEFT;
if(v.y < 0) return UP;
return DOWN;
}
/* Normalize vector */
static inline fpoint_t fnormalize(fpoint_t v)
{
fixed_t norm = fmul(v.x, v.x) + fmul(v.y, v.y);
if(norm == 0) return v;
norm = fsqrt(norm);
return (fpoint_t){ fdiv(v.x, norm), fdiv(v.y, norm) };
}
//---
// Rect operations
//---
/* Center of rectangle */
fpoint_t rect_center(frect_t r);
/* Scale a rectangle by the specified factor. */
frect_t rect_scale(frect_t r, fixed_t factor);
/* Translate a rectangle by the specified point coordinates. */
frect_t rect_translate(frect_t r, fpoint_t vec);
/* Draw rectangle on-screen; expects a rectangle in the screen coordinate system. */
void rect_draw(frect_t r, int color);
/* Check whether two rectangles collide */
bool rect_collide(frect_t r1, frect_t r2);
/* Rotate rectangle from one quad direction to another */
frect_t rect_rotate(frect_t r, int from_dir, int to_dir);