1
0
Fork 0
mirror of https://git.coom.tech/drummyfish/raycastlib.git synced 2024-11-21 20:29:59 +01:00

Add castRay function

This commit is contained in:
Miloslav Číž 2018-08-22 08:21:38 +02:00
parent 44c48182ab
commit 879326c3db

View file

@ -30,6 +30,16 @@ typedef struct
Vector2D direction; Vector2D direction;
} Ray; } Ray;
typedef struct
{
Vector2D square; ///< Collided square coordinates.
Vector2D position; ///< Exact collision position in Units.
Unit distance; /**< Euclidean distance to the hit position, or -1 if
no collision happened. */
} HitResult;
HitResult castRay(Ray ray, int (*collisionFunc)(int, int),
unsigned int maxSteps);
//============================================================================= //=============================================================================
// privates // privates
@ -49,65 +59,62 @@ int8_t pointIsLeftOfRay(Vector2D point, Ray ray)
} }
/** /**
Casts a ray within a single square, to collide with the square borders.
*/ */
void castRaySquare(Ray globalRay, Vector2D *nextCellOffset, void castRaySquare(Ray localRay, Vector2D *nextCellOffset,
Vector2D *collisionPointOffset) Vector2D *collisionPointOffset)
{ {
globalRay.start.x %= UNITS_PER_SQUARE;
globalRay.start.y %= UNITS_PER_SQUARE;
nextCellOffset->x = 0; nextCellOffset->x = 0;
nextCellOffset->y = 0; nextCellOffset->y = 0;
Ray criticalLine = globalRay; Ray criticalLine = localRay;
#define helper(c1,c2,n)\ #define helper(c1,c2,n)\
{\ {\
nextCellOffset->c1 = n;\ nextCellOffset->c1 = n;\
collisionPointOffset->c1 = criticalLine.start.c1 - globalRay.start.c1;\ collisionPointOffset->c1 = criticalLine.start.c1 - localRay.start.c1;\
collisionPointOffset->c2 =\ collisionPointOffset->c2 =\
(collisionPointOffset->c1 * globalRay.direction.c2) /\ (collisionPointOffset->c1 * localRay.direction.c2) /\
(globalRay.direction.c1 == 0 ? 1 : globalRay.direction.c1);\ (localRay.direction.c1 == 0 ? 1 : localRay.direction.c1);\
} }
#define helper2(n1,n2,c)\ #define helper2(n1,n2,c)\
if (pointIsLeftOfRay(globalRay.start,criticalLine) == c)\ if (pointIsLeftOfRay(localRay.start,criticalLine) == c)\
helper(y,x,n1)\ helper(y,x,n1)\
else\ else\
helper(x,y,n2) helper(x,y,n2)
if (globalRay.direction.x > 0) if (localRay.direction.x > 0)
{ {
criticalLine.start.x = UNITS_PER_SQUARE - 1; criticalLine.start.x = UNITS_PER_SQUARE;
if (globalRay.direction.y > 0) if (localRay.direction.y > 0)
{ {
// top right // top right
criticalLine.start.y = UNITS_PER_SQUARE - 1; criticalLine.start.y = UNITS_PER_SQUARE;
helper2(1,1,1) helper2(1,1,1)
} }
else else
{ {
// bottom right // bottom right
criticalLine.start.y = 0; criticalLine.start.y = -1;
helper2(-1,1,0) helper2(-1,1,0)
} }
} }
else else
{ {
criticalLine.start.x = 0; criticalLine.start.x = -1;
if (globalRay.direction.y > 0) if (localRay.direction.y > 0)
{ {
// top left // top left
criticalLine.start.y = UNITS_PER_SQUARE - 1; criticalLine.start.y = UNITS_PER_SQUARE;
helper2(1,-1,0) helper2(1,-1,0)
} }
else else
{ {
// bottom left // bottom left
criticalLine.start.y = 0; criticalLine.start.y = -1;
helper2(-1,-1,1) helper2(-1,-1,1)
} }
} }
@ -116,23 +123,52 @@ void castRaySquare(Ray globalRay, Vector2D *nextCellOffset,
#undef helper #undef helper
} }
HitResult castRay(Ray ray, int (*collisionFunc)(int, int),
unsigned int maxSteps)
{
HitResult result;
result.distance = -1;
result.square.x = ray.start.x / UNITS_PER_SQUARE;
result.square.y = ray.start.y / UNITS_PER_SQUARE;
result.position = ray.start;
for (uint16_t i = 0; i < maxSteps; ++i)
{
ray.start.x = result.position.x % UNITS_PER_SQUARE;
ray.start.y = result.position.y % UNITS_PER_SQUARE;
Vector2D no, co;
castRaySquare(ray,&no,&co);
result.square.x += no.x;
result.square.y += no.y;
result.position.x += co.x;
result.position.y += co.y;
}
return result;
}
int aaa(int x, int y)
{
return (x < 0 || y < 0 || x > 10 || y > 10) ? 1 : 0;
}
int main() int main()
{ {
Ray r; Ray r;
Vector2D no;
Vector2D co;
r.start.x = 10; r.start.x = 4 * UNITS_PER_SQUARE + UNITS_PER_SQUARE / 2;
r.start.y = 10; r.start.y = 4 * UNITS_PER_SQUARE + UNITS_PER_SQUARE / 2;
r.direction.x = -200; r.direction.x = 100;
r.direction.y = -200; r.direction.y = 50;
logRay(r); logRay(r);
castRaySquare(r,&no,&co); castRay(r,aaa,10);
logVector2D(no);
logVector2D(co);
return 0; return 0;
} }