117 lines
2.5 KiB
C
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);
|