Update raycastlib
This commit is contained in:
parent
99a2af6f55
commit
b67d8c9b43
1 changed files with 120 additions and 64 deletions
178
raycastlib.h
178
raycastlib.h
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
author: Miloslav "drummyfish" Ciz
|
author: Miloslav "drummyfish" Ciz
|
||||||
license: CC0 1.0
|
license: CC0 1.0
|
||||||
version: 0.1
|
version: 0.8
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -40,11 +40,11 @@
|
||||||
RCL_UNITS_PER_SQUARE units in a square's
|
RCL_UNITS_PER_SQUARE units in a square's
|
||||||
length. This effectively serves the purpose of
|
length. This effectively serves the purpose of
|
||||||
a fixed-point arithmetic. */
|
a fixed-point arithmetic. */
|
||||||
#define RCL_INFINITY 5000000;
|
#define RCL_INFINITY 2000000000
|
||||||
#else
|
#else
|
||||||
#define RCL_UNITS_PER_SQUARE 32
|
#define RCL_UNITS_PER_SQUARE 32
|
||||||
typedef int16_t RCL_Unit;
|
typedef int16_t RCL_Unit;
|
||||||
#define RCL_INFINITY 32000;
|
#define RCL_INFINITY 30000
|
||||||
#define RCL_USE_DIST_APPROX 2
|
#define RCL_USE_DIST_APPROX 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -56,6 +56,14 @@
|
||||||
#define RCL_COMPUTE_FLOOR_TEXCOORDS 0
|
#define RCL_COMPUTE_FLOOR_TEXCOORDS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef RCL_FLOOR_TEXCOORDS_HEIGHT
|
||||||
|
#define RCL_FLOOR_TEXCOORDS_HEIGHT 0 /** If RCL_COMPUTE_FLOOR_TEXCOORDS == 1,
|
||||||
|
this says for what height level the
|
||||||
|
texture coords will be computed for
|
||||||
|
(for simplicity/performance only one
|
||||||
|
level is allowed). */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef RCL_USE_COS_LUT
|
#ifndef RCL_USE_COS_LUT
|
||||||
#define RCL_USE_COS_LUT 0 /**< type of look up table for cos function:
|
#define RCL_USE_COS_LUT 0 /**< type of look up table for cos function:
|
||||||
0: none (compute)
|
0: none (compute)
|
||||||
|
@ -162,7 +170,7 @@
|
||||||
printf(" start: ");\
|
printf(" start: ");\
|
||||||
RCL_logV2D(r.start);\
|
RCL_logV2D(r.start);\
|
||||||
printf(" dir: ");\
|
printf(" dir: ");\
|
||||||
RCL_logV2D(r.direction);}\
|
RCL_logV2D(r.direction);}
|
||||||
|
|
||||||
#define RCL_logHitResult(h){\
|
#define RCL_logHitResult(h){\
|
||||||
printf("hit:\n");\
|
printf("hit:\n");\
|
||||||
|
@ -172,17 +180,30 @@
|
||||||
RCL_logV2D(h.position);\
|
RCL_logV2D(h.position);\
|
||||||
printf(" dist: %d\n", h.distance);\
|
printf(" dist: %d\n", h.distance);\
|
||||||
printf(" dir: %d\n", h.direction);\
|
printf(" dir: %d\n", h.direction);\
|
||||||
printf(" texcoord: %d\n", h.textureCoord);}\
|
printf(" texcoord: %d\n", h.textureCoord);}
|
||||||
|
|
||||||
#define RCL_logPixelInfo(p){\
|
#define RCL_logPixelInfo(p){\
|
||||||
printf("pixel:\n");\
|
printf("pixel:\n");\
|
||||||
printf(" position: ");\
|
printf(" position: ");\
|
||||||
RCL_logV2D(p.position);\
|
RCL_logV2D(p.position);\
|
||||||
|
printf(" texCoord: ");\
|
||||||
|
RCL_logV2D(p.texCoords);\
|
||||||
printf(" depth: %d\n", p.depth);\
|
printf(" depth: %d\n", p.depth);\
|
||||||
|
printf(" height: %d\n", p.height);\
|
||||||
printf(" wall: %d\n", p.isWall);\
|
printf(" wall: %d\n", p.isWall);\
|
||||||
printf(" hit: ");\
|
printf(" hit: ");\
|
||||||
RCL_logHitResult(p.hit);\
|
RCL_logHitResult(p.hit);\
|
||||||
}\
|
}
|
||||||
|
|
||||||
|
#define RCL_logCamera(c){\
|
||||||
|
printf("camera:\n");\
|
||||||
|
printf(" position: ");\
|
||||||
|
RCL_logV2D(c.position);\
|
||||||
|
printf(" height: %d\n",c.height);\
|
||||||
|
printf(" direction: %d\n",c.direction);\
|
||||||
|
printf(" shear: %d\n",c.shear);\
|
||||||
|
printf(" resolution: %d x %d\n",c.resolution.x,c.resolution.y);\
|
||||||
|
}
|
||||||
|
|
||||||
/// Position in 2D space.
|
/// Position in 2D space.
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -235,6 +256,7 @@ typedef struct
|
||||||
int8_t isFloor; ///< Whether the pixel is floor or ceiling.
|
int8_t isFloor; ///< Whether the pixel is floor or ceiling.
|
||||||
int8_t isHorizon; ///< If the pixel belongs to horizon segment.
|
int8_t isHorizon; ///< If the pixel belongs to horizon segment.
|
||||||
RCL_Unit depth; ///< Corrected depth.
|
RCL_Unit depth; ///< Corrected depth.
|
||||||
|
RCL_Unit height; ///< World height (mostly for floor).
|
||||||
RCL_HitResult hit; ///< Corresponding ray hit.
|
RCL_HitResult hit; ///< Corresponding ray hit.
|
||||||
RCL_Vector2D texCoords; /**< Normalized (0 to RCL_UNITS_PER_SQUARE - 1)
|
RCL_Vector2D texCoords; /**< Normalized (0 to RCL_UNITS_PER_SQUARE - 1)
|
||||||
texture coordinates. */
|
texture coordinates. */
|
||||||
|
@ -791,9 +813,7 @@ void RCL_castRayMultiHit(RCL_Ray ray, RCL_ArrayFunction arrayFunc,
|
||||||
{
|
{
|
||||||
RCL_profileCall(RCL_castRayMultiHit);
|
RCL_profileCall(RCL_castRayMultiHit);
|
||||||
|
|
||||||
RCL_Vector2D initialPos = ray.start;
|
|
||||||
RCL_Vector2D currentPos = ray.start;
|
RCL_Vector2D currentPos = ray.start;
|
||||||
|
|
||||||
RCL_Vector2D currentSquare;
|
RCL_Vector2D currentSquare;
|
||||||
|
|
||||||
currentSquare.x = RCL_divRoundDown(ray.start.x,RCL_UNITS_PER_SQUARE);
|
currentSquare.x = RCL_divRoundDown(ray.start.x,RCL_UNITS_PER_SQUARE);
|
||||||
|
@ -883,7 +903,6 @@ void RCL_castRayMultiHit(RCL_Ray ray, RCL_ArrayFunction arrayFunc,
|
||||||
RCL_Unit diff = h.position.x - ray.start.x;
|
RCL_Unit diff = h.position.x - ray.start.x;
|
||||||
h.position.y = ray.start.y + ((ray.direction.y * diff) /
|
h.position.y = ray.start.y + ((ray.direction.y * diff) /
|
||||||
RCL_nonZero(ray.direction.x));
|
RCL_nonZero(ray.direction.x));
|
||||||
h.textureCoord = h.position.y;
|
|
||||||
|
|
||||||
h.distance =
|
h.distance =
|
||||||
((h.position.x - ray.start.x) * RCL_UNITS_PER_SQUARE) /
|
((h.position.x - ray.start.x) * RCL_UNITS_PER_SQUARE) /
|
||||||
|
@ -903,7 +922,6 @@ void RCL_castRayMultiHit(RCL_Ray ray, RCL_ArrayFunction arrayFunc,
|
||||||
RCL_Unit diff = h.position.y - ray.start.y;
|
RCL_Unit diff = h.position.y - ray.start.y;
|
||||||
h.position.x = ray.start.x + ((ray.direction.x * diff) /
|
h.position.x = ray.start.x + ((ray.direction.x * diff) /
|
||||||
RCL_nonZero(ray.direction.y));
|
RCL_nonZero(ray.direction.y));
|
||||||
h.textureCoord = h.position.x;
|
|
||||||
|
|
||||||
h.distance =
|
h.distance =
|
||||||
((h.position.y - ray.start.y) * RCL_UNITS_PER_SQUARE) /
|
((h.position.y - ray.start.y) * RCL_UNITS_PER_SQUARE) /
|
||||||
|
@ -914,8 +932,27 @@ void RCL_castRayMultiHit(RCL_Ray ray, RCL_ArrayFunction arrayFunc,
|
||||||
h.type = typeFunc(currentSquare.x,currentSquare.y);
|
h.type = typeFunc(currentSquare.x,currentSquare.y);
|
||||||
|
|
||||||
#if RCL_COMPUTE_WALL_TEXCOORDS == 1
|
#if RCL_COMPUTE_WALL_TEXCOORDS == 1
|
||||||
|
switch (h.direction)
|
||||||
|
{
|
||||||
|
case 0: h.textureCoord =
|
||||||
|
RCL_wrap(-1 * h.position.x,RCL_UNITS_PER_SQUARE); break;
|
||||||
|
|
||||||
|
case 1: h.textureCoord =
|
||||||
|
RCL_wrap(h.position.y,RCL_UNITS_PER_SQUARE); break;
|
||||||
|
|
||||||
|
case 2: h.textureCoord =
|
||||||
|
RCL_wrap(h.position.x,RCL_UNITS_PER_SQUARE); break;
|
||||||
|
|
||||||
|
case 3: h.textureCoord =
|
||||||
|
RCL_wrap(-1 * h.position.y,RCL_UNITS_PER_SQUARE); break;
|
||||||
|
|
||||||
|
default: h.textureCoord = 0; break;
|
||||||
|
}
|
||||||
|
|
||||||
if (_RCL_rollFunction != 0)
|
if (_RCL_rollFunction != 0)
|
||||||
h.doorRoll = _RCL_rollFunction(currentSquare.x,currentSquare.y);
|
h.doorRoll = _RCL_rollFunction(currentSquare.x,currentSquare.y);
|
||||||
|
#else
|
||||||
|
h.textureCoord = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hitResults[*hitResultsLen] = h;
|
hitResults[*hitResultsLen] = h;
|
||||||
|
@ -1063,8 +1100,6 @@ static inline int16_t _RCL_drawHorizontal(
|
||||||
RCL_Unit depthIncrement;
|
RCL_Unit depthIncrement;
|
||||||
RCL_Unit dx;
|
RCL_Unit dx;
|
||||||
RCL_Unit dy;
|
RCL_Unit dy;
|
||||||
RCL_Unit pixPos;
|
|
||||||
RCL_Unit rayCameraCos;
|
|
||||||
|
|
||||||
pixelInfo->isWall = 0;
|
pixelInfo->isWall = 0;
|
||||||
|
|
||||||
|
@ -1085,9 +1120,6 @@ static inline int16_t _RCL_drawHorizontal(
|
||||||
{\
|
{\
|
||||||
dx = pixelInfo->hit.position.x - _RCL_camera.position.x;\
|
dx = pixelInfo->hit.position.x - _RCL_camera.position.x;\
|
||||||
dy = pixelInfo->hit.position.y - _RCL_camera.position.y;\
|
dy = pixelInfo->hit.position.y - _RCL_camera.position.y;\
|
||||||
pixPos = yCurrent - _RCL_middleRow - 1;\
|
|
||||||
rayCameraCos = RCL_vectorsAngleCos(\
|
|
||||||
RCL_angleToDirection(_RCL_camera.direction),ray->direction);\
|
|
||||||
}\
|
}\
|
||||||
for (int16_t i = yCurrent + increment;\
|
for (int16_t i = yCurrent + increment;\
|
||||||
increment == -1 ? i >= limit : i <= limit; /* TODO: is efficient? */\
|
increment == -1 ? i >= limit : i <= limit; /* TODO: is efficient? */\
|
||||||
|
@ -1098,12 +1130,12 @@ static inline int16_t _RCL_drawHorizontal(
|
||||||
pixelInfo->depth += depthIncrement;\
|
pixelInfo->depth += depthIncrement;\
|
||||||
if (doCoords) /*constant condition - compiler should optimize it out*/\
|
if (doCoords) /*constant condition - compiler should optimize it out*/\
|
||||||
{\
|
{\
|
||||||
RCL_Unit d = _RCL_floorPixelDistances[pixPos];\
|
RCL_Unit d = _RCL_floorPixelDistances[i];\
|
||||||
|
RCL_Unit d2 = RCL_nonZero(pixelInfo->hit.distance);\
|
||||||
pixelInfo->texCoords.x =\
|
pixelInfo->texCoords.x =\
|
||||||
_RCL_camera.position.x + ((d * dx) / (pixelInfo->hit.distance));\
|
_RCL_camera.position.x + ((d * dx) / d2);\
|
||||||
pixelInfo->texCoords.y =\
|
pixelInfo->texCoords.y =\
|
||||||
_RCL_camera.position.y + ((d * dy) / (pixelInfo->hit.distance));\
|
_RCL_camera.position.y + ((d * dy) / d2);\
|
||||||
++pixPos;\
|
|
||||||
}\
|
}\
|
||||||
RCL_PIXEL_FUNCTION(pixelInfo);\
|
RCL_PIXEL_FUNCTION(pixelInfo);\
|
||||||
}\
|
}\
|
||||||
|
@ -1174,7 +1206,6 @@ static inline int16_t _RCL_drawWall(
|
||||||
i += increment)
|
i += increment)
|
||||||
{
|
{
|
||||||
// more expensive texture coord computing
|
// more expensive texture coord computing
|
||||||
|
|
||||||
pixelInfo->position.y = i;
|
pixelInfo->position.y = i;
|
||||||
|
|
||||||
#if RCL_COMPUTE_WALL_TEXCOORDS == 1
|
#if RCL_COMPUTE_WALL_TEXCOORDS == 1
|
||||||
|
@ -1210,6 +1241,22 @@ static inline int16_t _RCL_drawWall(
|
||||||
return limit;
|
return limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fills a RCL_HitResult struct with info for a hit at infinity.
|
||||||
|
static inline void _RCL_makeInfiniteHit(RCL_HitResult *hit, RCL_Ray *ray)
|
||||||
|
{
|
||||||
|
hit->distance = RCL_UNITS_PER_SQUARE * RCL_UNITS_PER_SQUARE;
|
||||||
|
/* ^ horizon is at infinity, but we can't use too big infinity
|
||||||
|
(RCL_INFINITY) because it would overflow in the following mult. */
|
||||||
|
hit->position.x = (ray->direction.x * hit->distance) / RCL_UNITS_PER_SQUARE;
|
||||||
|
hit->position.y = (ray->direction.y * hit->distance) / RCL_UNITS_PER_SQUARE;
|
||||||
|
|
||||||
|
hit->direction = 0;
|
||||||
|
hit->textureCoord = 0;
|
||||||
|
hit->arrayValue = 0;
|
||||||
|
hit->doorRoll = 0;
|
||||||
|
hit->type = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t x,
|
void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t x,
|
||||||
RCL_Ray ray)
|
RCL_Ray ray)
|
||||||
{
|
{
|
||||||
|
@ -1217,12 +1264,13 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t
|
||||||
RCL_Unit fPosY = _RCL_camera.resolution.y;
|
RCL_Unit fPosY = _RCL_camera.resolution.y;
|
||||||
RCL_Unit cPosY = -1;
|
RCL_Unit cPosY = -1;
|
||||||
|
|
||||||
// world coordinates
|
// world coordinates (relative to camera height though)
|
||||||
RCL_Unit fZ1World = _RCL_startFloorHeight;
|
RCL_Unit fZ1World = _RCL_startFloorHeight;
|
||||||
RCL_Unit cZ1World = _RCL_startCeil_Height;
|
RCL_Unit cZ1World = _RCL_startCeil_Height;
|
||||||
|
|
||||||
RCL_PixelInfo p;
|
RCL_PixelInfo p;
|
||||||
p.position.x = x;
|
p.position.x = x;
|
||||||
|
p.height = 0;
|
||||||
p.texCoords.x = 0;
|
p.texCoords.x = 0;
|
||||||
p.texCoords.y = 0;
|
p.texCoords.y = 0;
|
||||||
|
|
||||||
|
@ -1232,7 +1280,7 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t
|
||||||
int8_t drawingHorizon = j == hitCount;
|
int8_t drawingHorizon = j == hitCount;
|
||||||
|
|
||||||
RCL_HitResult hit;
|
RCL_HitResult hit;
|
||||||
RCL_Unit distance;
|
RCL_Unit distance = 1;
|
||||||
|
|
||||||
RCL_Unit fWallHeight = 0, cWallHeight = 0;
|
RCL_Unit fWallHeight = 0, cWallHeight = 0;
|
||||||
RCL_Unit fZ2World = 0, cZ2World = 0;
|
RCL_Unit fZ2World = 0, cZ2World = 0;
|
||||||
|
@ -1242,7 +1290,8 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t
|
||||||
if (!drawingHorizon)
|
if (!drawingHorizon)
|
||||||
{
|
{
|
||||||
hit = hits[j];
|
hit = hits[j];
|
||||||
distance = hit.distance;
|
distance = RCL_nonZero(hit.distance);
|
||||||
|
p.hit = hit;
|
||||||
|
|
||||||
fWallHeight = _RCL_floorFunction(hit.square.x,hit.square.y);
|
fWallHeight = _RCL_floorFunction(hit.square.x,hit.square.y);
|
||||||
fZ2World = fWallHeight - _RCL_camera.height;
|
fZ2World = fWallHeight - _RCL_camera.height;
|
||||||
|
@ -1269,6 +1318,7 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t
|
||||||
{
|
{
|
||||||
fZ1Screen = _RCL_middleRow;
|
fZ1Screen = _RCL_middleRow;
|
||||||
cZ1Screen = _RCL_middleRow + 1;
|
cZ1Screen = _RCL_middleRow + 1;
|
||||||
|
_RCL_makeInfiniteHit(&p.hit,&ray);
|
||||||
}
|
}
|
||||||
|
|
||||||
RCL_Unit limit;
|
RCL_Unit limit;
|
||||||
|
@ -1278,6 +1328,7 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t
|
||||||
|
|
||||||
// draw floor until wall
|
// draw floor until wall
|
||||||
p.isFloor = 1;
|
p.isFloor = 1;
|
||||||
|
p.height = fZ1World + _RCL_camera.height;
|
||||||
|
|
||||||
#if RCL_COMPUTE_FLOOR_DEPTH == 1
|
#if RCL_COMPUTE_FLOOR_DEPTH == 1
|
||||||
p.depth = (_RCL_fHorizontalDepthStart - fPosY) * _RCL_horizontalDepthStep;
|
p.depth = (_RCL_fHorizontalDepthStart - fPosY) * _RCL_horizontalDepthStep;
|
||||||
|
@ -1286,8 +1337,10 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
limit = _RCL_drawHorizontal(fPosY,fZ1Screen,cPosY + 1,
|
limit = _RCL_drawHorizontal(fPosY,fZ1Screen,cPosY + 1,
|
||||||
_RCL_camera.resolution.y,fZ1World,-1,RCL_COMPUTE_FLOOR_DEPTH,0,1,&ray,&p);
|
_RCL_camera.resolution.y,fZ1World,-1,RCL_COMPUTE_FLOOR_DEPTH,
|
||||||
// ^ purposfully allow outside screen bounds
|
// ^ purposfully allow outside screen bounds
|
||||||
|
RCL_COMPUTE_FLOOR_TEXCOORDS && p.height == RCL_FLOOR_TEXCOORDS_HEIGHT,
|
||||||
|
1,&ray,&p);
|
||||||
|
|
||||||
if (fPosY > limit)
|
if (fPosY > limit)
|
||||||
fPosY = limit;
|
fPosY = limit;
|
||||||
|
@ -1296,6 +1349,7 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t
|
||||||
{
|
{
|
||||||
// draw ceiling until wall
|
// draw ceiling until wall
|
||||||
p.isFloor = 0;
|
p.isFloor = 0;
|
||||||
|
p.height = cZ1World + _RCL_camera.height;
|
||||||
|
|
||||||
#if RCL_COMPUTE_CEILING_DEPTH == 1
|
#if RCL_COMPUTE_CEILING_DEPTH == 1
|
||||||
p.depth = (cPosY - _RCL_cHorizontalDepthStart) *
|
p.depth = (cPosY - _RCL_cHorizontalDepthStart) *
|
||||||
|
@ -1315,8 +1369,8 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t
|
||||||
p.isWall = 1;
|
p.isWall = 1;
|
||||||
p.depth = distance;
|
p.depth = distance;
|
||||||
p.isFloor = 1;
|
p.isFloor = 1;
|
||||||
p.hit = hit;
|
|
||||||
p.texCoords.x = hit.textureCoord;
|
p.texCoords.x = hit.textureCoord;
|
||||||
|
p.height = 0; // don't compute this, no use
|
||||||
|
|
||||||
// draw floor wall
|
// draw floor wall
|
||||||
|
|
||||||
|
@ -1400,9 +1454,11 @@ void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount,
|
||||||
{
|
{
|
||||||
// normal hit, check the door roll
|
// normal hit, check the door roll
|
||||||
|
|
||||||
|
RCL_Unit texCoordMod = hit.textureCoord % RCL_UNITS_PER_SQUARE;
|
||||||
|
|
||||||
int8_t unrolled = hit.doorRoll >= 0 ?
|
int8_t unrolled = hit.doorRoll >= 0 ?
|
||||||
hit.doorRoll > hit.textureCoord :
|
hit.doorRoll > texCoordMod :
|
||||||
hit.textureCoord > RCL_UNITS_PER_SQUARE + hit.doorRoll;
|
texCoordMod > RCL_UNITS_PER_SQUARE + hit.doorRoll;
|
||||||
|
|
||||||
if (unrolled)
|
if (unrolled)
|
||||||
{
|
{
|
||||||
|
@ -1450,17 +1506,7 @@ void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RCL_HitResult hit;
|
_RCL_makeInfiniteHit(&p.hit,&ray);
|
||||||
|
|
||||||
hit.distance = RCL_HORIZON_DEPTH;
|
|
||||||
hit.direction = 0;
|
|
||||||
hit.textureCoord = x * 128;
|
|
||||||
hit.position.x = 0;
|
|
||||||
hit.position.y = 0;
|
|
||||||
hit.arrayValue = 0;
|
|
||||||
hit.type = 0;
|
|
||||||
|
|
||||||
p.hit = hit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw ceiling
|
// draw ceiling
|
||||||
|
@ -1469,6 +1515,7 @@ void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount,
|
||||||
p.isFloor = 0;
|
p.isFloor = 0;
|
||||||
p.isHorizon = 1;
|
p.isHorizon = 1;
|
||||||
p.depth = 1;
|
p.depth = 1;
|
||||||
|
p.height = RCL_UNITS_PER_SQUARE;
|
||||||
|
|
||||||
y = _RCL_drawHorizontal(-1,wallStart,-1,_RCL_middleRow,_RCL_camera.height,1,
|
y = _RCL_drawHorizontal(-1,wallStart,-1,_RCL_middleRow,_RCL_camera.height,1,
|
||||||
RCL_COMPUTE_CEILING_DEPTH,0,1,&ray,&p);
|
RCL_COMPUTE_CEILING_DEPTH,0,1,&ray,&p);
|
||||||
|
@ -1478,6 +1525,7 @@ void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount,
|
||||||
p.isWall = 1;
|
p.isWall = 1;
|
||||||
p.isFloor = 1;
|
p.isFloor = 1;
|
||||||
p.depth = dist;
|
p.depth = dist;
|
||||||
|
p.height = 0;
|
||||||
|
|
||||||
#if RCL_ROLL_TEXTURE_COORDS == 1 && RCL_COMPUTE_WALL_TEXCOORDS == 1
|
#if RCL_ROLL_TEXTURE_COORDS == 1 && RCL_COMPUTE_WALL_TEXCOORDS == 1
|
||||||
p.hit.textureCoord -= p.hit.doorRoll;
|
p.hit.textureCoord -= p.hit.doorRoll;
|
||||||
|
@ -1490,7 +1538,7 @@ void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount,
|
||||||
-1,_RCL_camResYLimit,p.hit.arrayValue,1,&p);
|
-1,_RCL_camResYLimit,p.hit.arrayValue,1,&p);
|
||||||
|
|
||||||
y = RCL_max(y,limit); // take max, in case no wall was drawn
|
y = RCL_max(y,limit); // take max, in case no wall was drawn
|
||||||
y = RCL_max(y,_RCL_middleRow + 1);
|
y = RCL_max(y,wallStart);
|
||||||
|
|
||||||
// draw floor
|
// draw floor
|
||||||
|
|
||||||
|
@ -1505,6 +1553,22 @@ void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount,
|
||||||
-1,&ray,&p);
|
-1,&ray,&p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Precomputes a distance from camera to the floor at each screen row into an
|
||||||
|
array (must be preallocated with sufficient (camera.resolution.y) length).
|
||||||
|
*/
|
||||||
|
static inline void _RCL_precomputeFloorDistances(RCL_Camera camera,
|
||||||
|
RCL_Unit *dest, uint16_t startIndex)
|
||||||
|
{
|
||||||
|
RCL_Unit camHeightScreenSize =
|
||||||
|
(camera.height * camera.resolution.y) / RCL_UNITS_PER_SQUARE;
|
||||||
|
|
||||||
|
for (uint16_t i = startIndex
|
||||||
|
; i < camera.resolution.y; ++i)
|
||||||
|
dest[i] = RCL_perspectiveScaleInverse(camHeightScreenSize,
|
||||||
|
RCL_absVal(i - _RCL_middleRow));
|
||||||
|
}
|
||||||
|
|
||||||
void RCL_renderComplex(RCL_Camera cam, RCL_ArrayFunction floorHeightFunc,
|
void RCL_renderComplex(RCL_Camera cam, RCL_ArrayFunction floorHeightFunc,
|
||||||
RCL_ArrayFunction ceilingHeightFunc, RCL_ArrayFunction typeFunction,
|
RCL_ArrayFunction ceilingHeightFunc, RCL_ArrayFunction typeFunction,
|
||||||
RCL_RayConstraints constraints)
|
RCL_RayConstraints constraints)
|
||||||
|
@ -1514,7 +1578,7 @@ void RCL_renderComplex(RCL_Camera cam, RCL_ArrayFunction floorHeightFunc,
|
||||||
_RCL_camera = cam;
|
_RCL_camera = cam;
|
||||||
_RCL_camResYLimit = cam.resolution.y - 1;
|
_RCL_camResYLimit = cam.resolution.y - 1;
|
||||||
|
|
||||||
int16_t halfResY = cam.resolution.y / 2;
|
uint16_t halfResY = cam.resolution.y / 2;
|
||||||
|
|
||||||
_RCL_middleRow = halfResY + cam.shear;
|
_RCL_middleRow = halfResY + cam.shear;
|
||||||
|
|
||||||
|
@ -1534,6 +1598,12 @@ void RCL_renderComplex(RCL_Camera cam, RCL_ArrayFunction floorHeightFunc,
|
||||||
|
|
||||||
_RCL_horizontalDepthStep = RCL_HORIZON_DEPTH / cam.resolution.y;
|
_RCL_horizontalDepthStep = RCL_HORIZON_DEPTH / cam.resolution.y;
|
||||||
|
|
||||||
|
#if RCL_COMPUTE_FLOOR_TEXCOORDS == 1
|
||||||
|
RCL_Unit floorPixelDistances[cam.resolution.y];
|
||||||
|
_RCL_precomputeFloorDistances(cam,floorPixelDistances,0);
|
||||||
|
_RCL_floorPixelDistances = floorPixelDistances; // pass to column function
|
||||||
|
#endif
|
||||||
|
|
||||||
RCL_castRaysMultiHit(cam,_RCL_floorCeilFunction,typeFunction,
|
RCL_castRaysMultiHit(cam,_RCL_floorCeilFunction,typeFunction,
|
||||||
_RCL_columnFunctionComplex,constraints);
|
_RCL_columnFunctionComplex,constraints);
|
||||||
}
|
}
|
||||||
|
@ -1560,25 +1630,9 @@ void RCL_renderSimple(RCL_Camera cam, RCL_ArrayFunction floorHeightFunc,
|
||||||
3; // for correctly rendering rolling doors we'll need 3 hits (NOT 2)
|
3; // for correctly rendering rolling doors we'll need 3 hits (NOT 2)
|
||||||
|
|
||||||
#if RCL_COMPUTE_FLOOR_TEXCOORDS == 1
|
#if RCL_COMPUTE_FLOOR_TEXCOORDS == 1
|
||||||
uint16_t halfResY = cam.resolution.y / 2;
|
RCL_Unit floorPixelDistances[cam.resolution.y];
|
||||||
|
_RCL_precomputeFloorDistances(cam,floorPixelDistances,_RCL_middleRow);
|
||||||
RCL_Unit floorPixelDistances[halfResY]; /* for each vertical floor pixel,
|
_RCL_floorPixelDistances = floorPixelDistances; // pass to column function
|
||||||
this will contain precomputed
|
|
||||||
distance to the camera */
|
|
||||||
RCL_Unit camHeightScreenSize =
|
|
||||||
#ifdef RCL_RAYCAST_TINY
|
|
||||||
(cam.height
|
|
||||||
#else
|
|
||||||
(((cam.height >> 6) << 6) // prevent weird floor movement with rounding
|
|
||||||
#endif
|
|
||||||
* cam.resolution.y) / RCL_UNITS_PER_SQUARE;
|
|
||||||
|
|
||||||
for (uint16_t i = 0; i < halfResY; ++i) // precompute the distances
|
|
||||||
floorPixelDistances[i] =
|
|
||||||
RCL_perspectiveScaleInverse(camHeightScreenSize,i);
|
|
||||||
|
|
||||||
// pass to _RCL_columnFunctionSimple
|
|
||||||
_RCL_floorPixelDistances = floorPixelDistances;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RCL_castRaysMultiHit(cam,_floorHeightNotZeroFunction,typeFunc,
|
RCL_castRaysMultiHit(cam,_floorHeightNotZeroFunction,typeFunc,
|
||||||
|
@ -1677,9 +1731,10 @@ RCL_Unit RCL_perspectiveScaleInverse(RCL_Unit originalSize,
|
||||||
RCL_Unit scaledSize)
|
RCL_Unit scaledSize)
|
||||||
{
|
{
|
||||||
return scaledSize != 0 ?
|
return scaledSize != 0 ?
|
||||||
(originalSize * RCL_UNITS_PER_SQUARE) /
|
(originalSize * RCL_UNITS_PER_SQUARE + RCL_UNITS_PER_SQUARE / 2) /
|
||||||
|
// ^ take the middle
|
||||||
((RCL_VERTICAL_FOV * 2 * scaledSize) / RCL_UNITS_PER_SQUARE)
|
((RCL_VERTICAL_FOV * 2 * scaledSize) / RCL_UNITS_PER_SQUARE)
|
||||||
: 0;
|
: RCL_INFINITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RCL_moveCameraWithCollision(RCL_Camera *camera, RCL_Vector2D planeOffset,
|
void RCL_moveCameraWithCollision(RCL_Camera *camera, RCL_Vector2D planeOffset,
|
||||||
|
@ -1837,6 +1892,7 @@ void RCL_moveCameraWithCollision(RCL_Camera *camera, RCL_Vector2D planeOffset,
|
||||||
camera->height = RCL_clamp(camera->height,
|
camera->height = RCL_clamp(camera->height,
|
||||||
bottomLimit + RCL_CAMERA_COLL_HEIGHT_BELOW,
|
bottomLimit + RCL_CAMERA_COLL_HEIGHT_BELOW,
|
||||||
topLimit - RCL_CAMERA_COLL_HEIGHT_ABOVE);
|
topLimit - RCL_CAMERA_COLL_HEIGHT_ABOVE);
|
||||||
|
|
||||||
#undef checkSquares
|
#undef checkSquares
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue