//--- // geometry: Geometry utilities //--- #pragma once #include "fixed.h" #include #include /* Directions */ enum { UP=0, RIGHT=1, DOWN=2, LEFT=3 }; /* Orientations */ enum { VERTICAL=0, HORIZONTAL=1, CEILING=2 }; //--- // 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. //--- typedef struct { fixed_t x, y; } vec2; typedef struct { int16_t x, y; } ivec2; typedef struct { /* Left edge, right edge */ fixed_t l, r; /* Top edge, bottom edge */ fixed_t t, b; } rect; typedef struct { int16_t l, r; int16_t t, b; } irect; /* Functions converting integer shapes to fixed-point. */ vec2 vec_i2f(ivec2); rect rect_i2f(irect); /* Same as vec_i2f() but adds +0.5 at each coordinate. */ vec2 vec_i2f_center(ivec2); /* Functions converting fixed-point shapes to integer. */ ivec2 vec_f2i(vec2); irect rect_f2i(rect); /* Dot product. */ fixed_t vec_dot(vec2, vec2); /* Rotate a vector by some constants */ vec2 vec_rotate_30(vec2); vec2 vec_rotate_m30(vec2); vec2 vec_rotate_45(vec2); vec2 vec_rotate_m45(vec2); vec2 vec_rotate_60(vec2); vec2 vec_rotate_m60(vec2); //--- // Point operations //--- /* Distance-squared between two points */ static inline fixed_t dist2(vec2 p1, vec2 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 vec2 fdir(int dir) { return (vec2){ .x = fix((dir == RIGHT) - (dir == LEFT)), .y = fix((dir == DOWN) - (dir == UP)), }; } /* Direction closest to specified vector */ static inline int frdir(vec2 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 vec2 fnormalize(vec2 v) { fixed_t norm = fmul(v.x, v.x) + fmul(v.y, v.y); if(norm == 0) return v; norm = fsqrt(norm); return (vec2){ fdiv(v.x, norm), fdiv(v.y, norm) }; } //--- // Rect operations //--- /* Center of rectangle */ vec2 rect_center(rect r); /* Scale a rectangle by the specified factor. */ rect rect_scale(rect r, fixed_t factor); /* Translate a rectangle by the specified point coordinates. */ rect rect_translate(rect r, vec2 vec); /* Draw rectangle on-screen; expects a rectangle in the screen coordinate system. */ void rect_draw(rect r, int color); /* Check whether two rectangles collide */ bool rect_collide(rect r1, rect r2); /* Rotate rectangle from one quad direction to another */ rect rect_rotate(rect r, int from_dir, int to_dir);