commit 44c48182ab141ee6d6339ea430c126685dc5e7d1 Author: Miloslav Číž Date: Tue Aug 21 13:49:45 2018 +0200 Init diff --git a/make.sh b/make.sh new file mode 100755 index 0000000..dcf8923 --- /dev/null +++ b/make.sh @@ -0,0 +1,2 @@ +#!/bin/bash +clear; clear; g++ -x c -fmax-errors=5 -pedantic -Wall -Wextra -o test raycastlib.c 2>&1 >/dev/null && ./test diff --git a/raycastlib.c b/raycastlib.c new file mode 100644 index 0000000..ec222ed --- /dev/null +++ b/raycastlib.c @@ -0,0 +1,138 @@ +#include +#include + +/** + author: Miloslav "drummyfish" Ciz + license: CC0 + + - Game field's bottom left corner is at [0,0]. + - X axis goes right. + - Y axis goes up. + - Each game square is UNITS_PER_SQUARE * UNITS_PER_SQUARE. + + */ + +#define UNITS_PER_SQUARE 1024 + +typedef int64_t Unit; /**< Smallest spatial unit, there is UNITS_PER_SQUARE + units in a square's length. */ + +/// Position in 2D space. +typedef struct +{ + Unit y; + Unit x; +} Vector2D; + +typedef struct +{ + Vector2D start; + Vector2D direction; +} Ray; + + +//============================================================================= +// privates + +#define logVector2D(v) printf("[%d,%d]\n",v.x,v.y) +#define logRay(r) printf("{\n");\ + logVector2D(r.start);\ + logVector2D(r.direction);\ + printf("}\n"); + +int8_t pointIsLeftOfRay(Vector2D point, Ray ray) +{ + int dX = point.x - ray.start.x; + int dY = point.y - ray.start.y; + return (ray.direction.x * dY - ray.direction.y * dX) > 0; + // ^ Z component of cross-product +} + +/** + + */ +void castRaySquare(Ray globalRay, Vector2D *nextCellOffset, + Vector2D *collisionPointOffset) +{ + globalRay.start.x %= UNITS_PER_SQUARE; + globalRay.start.y %= UNITS_PER_SQUARE; + + nextCellOffset->x = 0; + nextCellOffset->y = 0; + + Ray criticalLine = globalRay; + + #define helper(c1,c2,n)\ + {\ + nextCellOffset->c1 = n;\ + collisionPointOffset->c1 = criticalLine.start.c1 - globalRay.start.c1;\ + collisionPointOffset->c2 =\ + (collisionPointOffset->c1 * globalRay.direction.c2) /\ + (globalRay.direction.c1 == 0 ? 1 : globalRay.direction.c1);\ + } + + #define helper2(n1,n2,c)\ + if (pointIsLeftOfRay(globalRay.start,criticalLine) == c)\ + helper(y,x,n1)\ + else\ + helper(x,y,n2) + + if (globalRay.direction.x > 0) + { + criticalLine.start.x = UNITS_PER_SQUARE - 1; + + if (globalRay.direction.y > 0) + { + // top right + criticalLine.start.y = UNITS_PER_SQUARE - 1; + helper2(1,1,1) + } + else + { + // bottom right + criticalLine.start.y = 0; + helper2(-1,1,0) + } + } + else + { + criticalLine.start.x = 0; + + if (globalRay.direction.y > 0) + { + // top left + criticalLine.start.y = UNITS_PER_SQUARE - 1; + helper2(1,-1,0) + } + else + { + // bottom left + criticalLine.start.y = 0; + helper2(-1,-1,1) + } + } + + #undef helper2 + #undef helper +} + +int main() +{ + Ray r; + Vector2D no; + Vector2D co; + + r.start.x = 10; + r.start.y = 10; + r.direction.x = -200; + r.direction.y = -200; + + logRay(r); + + castRaySquare(r,&no,&co); + + logVector2D(no); + logVector2D(co); + + return 0; +}