mirror of
https://gitlab.com/drummyfish/anarch.git
synced 2024-11-24 09:52:20 -05:00
Fix visibility and RCL
This commit is contained in:
parent
db4e13af8a
commit
639a7fddba
1
TODO.txt
1
TODO.txt
@ -37,6 +37,7 @@ general:
|
|||||||
- easter egg(s)
|
- easter egg(s)
|
||||||
- optioal graphics enhance: vertical wall shading ("ambient occlusions")?
|
- optioal graphics enhance: vertical wall shading ("ambient occlusions")?
|
||||||
- option for disabling wall transparency, for performance?
|
- option for disabling wall transparency, for performance?
|
||||||
|
- open door by shooting at them?
|
||||||
|
|
||||||
level ideas:
|
level ideas:
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.7 KiB |
74
main.c
74
main.c
@ -694,15 +694,6 @@ void SFG_pixelFunc(RCL_PixelInfo *pixel)
|
|||||||
uint8_t color;
|
uint8_t color;
|
||||||
uint8_t shadow = 0;
|
uint8_t shadow = 0;
|
||||||
|
|
||||||
if (pixel->position.y == SFG_GAME_RESOLUTION_Y / 2)
|
|
||||||
{
|
|
||||||
uint8_t zValue = pixel->isWall ? SFG_RCLUnitToZBuffer(pixel->depth) : 255;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < SFG_RAYCASTING_SUBSAMPLE; ++i)
|
|
||||||
SFG_game.zBuffer[pixel->position.x * SFG_RAYCASTING_SUBSAMPLE + i] =
|
|
||||||
zValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pixel->isHorizon && pixel->depth > RCL_UNITS_PER_SQUARE * 16)
|
if (pixel->isHorizon && pixel->depth > RCL_UNITS_PER_SQUARE * 16)
|
||||||
{
|
{
|
||||||
color = SFG_TRANSPARENT_COLOR;
|
color = SFG_TRANSPARENT_COLOR;
|
||||||
@ -3621,6 +3612,25 @@ for (uint16_t j = 0; j < l; ++j)
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Checks a 3D point visibility from player's position (WITHOUT considering
|
||||||
|
facing direction).
|
||||||
|
*/
|
||||||
|
static inline uint8_t SFG_spriteIsVisible(RCL_Vector2D pos, RCL_Unit height,
|
||||||
|
uint8_t spriteSize)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
RCL_castRay3D(
|
||||||
|
SFG_player.camera.position,
|
||||||
|
SFG_player.camera.height,
|
||||||
|
pos,
|
||||||
|
height,
|
||||||
|
SFG_floorHeightAt,
|
||||||
|
SFG_ceilingHeightAt,
|
||||||
|
SFG_game.rayConstraints
|
||||||
|
) == RCL_UNITS_PER_SQUARE;
|
||||||
|
}
|
||||||
|
|
||||||
void SFG_draw()
|
void SFG_draw()
|
||||||
{
|
{
|
||||||
#if SFG_BACKGROUND_BLUR != 0
|
#if SFG_BACKGROUND_BLUR != 0
|
||||||
@ -3705,17 +3715,18 @@ void SFG_draw()
|
|||||||
uint8_t spriteSize = SFG_GET_MONSTER_SPRITE_SIZE(
|
uint8_t spriteSize = SFG_GET_MONSTER_SPRITE_SIZE(
|
||||||
SFG_MONSTER_TYPE_TO_INDEX(SFG_MR_TYPE(m)));
|
SFG_MONSTER_TYPE_TO_INDEX(SFG_MR_TYPE(m)));
|
||||||
|
|
||||||
RCL_PixelInfo p =
|
RCL_Unit worldHeight =
|
||||||
RCL_mapToScreen(
|
SFG_floorHeightAt(
|
||||||
worldPosition,
|
SFG_MONSTER_COORD_TO_SQUARES(m.coords[0]),
|
||||||
SFG_floorHeightAt(
|
SFG_MONSTER_COORD_TO_SQUARES(m.coords[1]))
|
||||||
SFG_MONSTER_COORD_TO_SQUARES(m.coords[0]),
|
+
|
||||||
SFG_MONSTER_COORD_TO_SQUARES(m.coords[1]))
|
SFG_SPRITE_SIZE_TO_HEIGHT_ABOVE_GROUND(spriteSize);
|
||||||
+
|
|
||||||
SFG_SPRITE_SIZE_TO_HEIGHT_ABOVE_GROUND(spriteSize),
|
|
||||||
SFG_player.camera);
|
|
||||||
|
|
||||||
if (p.depth > 0)
|
RCL_PixelInfo p =
|
||||||
|
RCL_mapToScreen(worldPosition,worldHeight,SFG_player.camera);
|
||||||
|
|
||||||
|
if (p.depth > 0 &&
|
||||||
|
SFG_spriteIsVisible(worldPosition,worldHeight,spriteSize))
|
||||||
{
|
{
|
||||||
const uint8_t *s =
|
const uint8_t *s =
|
||||||
SFG_getMonsterSprite(
|
SFG_getMonsterSprite(
|
||||||
@ -3725,7 +3736,7 @@ void SFG_draw()
|
|||||||
|
|
||||||
SFG_drawScaledSprite(s,
|
SFG_drawScaledSprite(s,
|
||||||
p.position.x * SFG_RAYCASTING_SUBSAMPLE,p.position.y,
|
p.position.x * SFG_RAYCASTING_SUBSAMPLE,p.position.y,
|
||||||
RCL_perspectiveScale(
|
RCL_perspectiveScaleVertical(
|
||||||
SFG_SPRITE_SIZE_PIXELS(spriteSize),
|
SFG_SPRITE_SIZE_PIXELS(spriteSize),
|
||||||
p.depth),
|
p.depth),
|
||||||
p.depth / (RCL_UNITS_PER_SQUARE * 2),p.depth);
|
p.depth / (RCL_UNITS_PER_SQUARE * 2),p.depth);
|
||||||
@ -3756,21 +3767,19 @@ void SFG_draw()
|
|||||||
|
|
||||||
if (sprite != 0)
|
if (sprite != 0)
|
||||||
{
|
{
|
||||||
RCL_PixelInfo p =
|
RCL_Unit worldHeight = SFG_floorHeightAt(e.coords[0],e.coords[1])
|
||||||
RCL_mapToScreen(
|
+ SFG_SPRITE_SIZE_TO_HEIGHT_ABOVE_GROUND(spriteSize);
|
||||||
worldPosition,
|
|
||||||
SFG_floorHeightAt(e.coords[0],e.coords[1])
|
|
||||||
+ SFG_SPRITE_SIZE_TO_HEIGHT_ABOVE_GROUND(spriteSize),
|
|
||||||
SFG_player.camera);
|
|
||||||
|
|
||||||
if (p.depth > 0)
|
RCL_PixelInfo p =
|
||||||
{
|
RCL_mapToScreen(worldPosition,worldHeight,SFG_player.camera);
|
||||||
|
|
||||||
|
if (p.depth > 0 &&
|
||||||
|
SFG_spriteIsVisible(worldPosition,worldHeight,spriteSize))
|
||||||
SFG_drawScaledSprite(
|
SFG_drawScaledSprite(
|
||||||
sprite,
|
sprite,
|
||||||
p.position.x * SFG_RAYCASTING_SUBSAMPLE,p.position.y,
|
p.position.x * SFG_RAYCASTING_SUBSAMPLE,p.position.y,
|
||||||
RCL_perspectiveScale(SFG_SPRITE_SIZE_PIXELS(spriteSize),p.depth),
|
RCL_perspectiveScaleVertical(SFG_SPRITE_SIZE_PIXELS(spriteSize),p.depth),
|
||||||
p.depth / (RCL_UNITS_PER_SQUARE * 2),p.depth);
|
p.depth / (RCL_UNITS_PER_SQUARE * 2),p.depth);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3811,10 +3820,11 @@ void SFG_draw()
|
|||||||
) / RCL_UNITS_PER_SQUARE;
|
) / RCL_UNITS_PER_SQUARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.depth > 0)
|
if (p.depth > 0 &&
|
||||||
|
SFG_spriteIsVisible(worldPosition,proj->position[2],spriteSize))
|
||||||
SFG_drawScaledSprite(s,
|
SFG_drawScaledSprite(s,
|
||||||
p.position.x * SFG_RAYCASTING_SUBSAMPLE,p.position.y,
|
p.position.x * SFG_RAYCASTING_SUBSAMPLE,p.position.y,
|
||||||
RCL_perspectiveScale(spriteSize,p.depth),
|
RCL_perspectiveScaleVertical(spriteSize,p.depth),
|
||||||
SFG_fogValueDiminish(p.depth),
|
SFG_fogValueDiminish(p.depth),
|
||||||
p.depth);
|
p.depth);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#define SFG_TEXTURE_DISTANCE 5000
|
#define SFG_TEXTURE_DISTANCE 5000
|
||||||
|
|
||||||
#undef SFG_FPS
|
#undef SFG_FPS
|
||||||
#define SFG_FPS 35
|
#define SFG_FPS 30
|
||||||
|
|
||||||
#undef SFG_SCREEN_RESOLUTION_X
|
#undef SFG_SCREEN_RESOLUTION_X
|
||||||
#define SFG_SCREEN_RESOLUTION_X 110
|
#define SFG_SCREEN_RESOLUTION_X 110
|
||||||
|
183
raycastlib.h
183
raycastlib.h
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
author: Miloslav "drummyfish" Ciz
|
author: Miloslav "drummyfish" Ciz
|
||||||
license: CC0 1.0
|
license: CC0 1.0
|
||||||
version: 0.903
|
version: 0.904
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -116,6 +116,8 @@
|
|||||||
#define RCL_HORIZONTAL_FOV (RCL_UNITS_PER_SQUARE / 4)
|
#define RCL_HORIZONTAL_FOV (RCL_UNITS_PER_SQUARE / 4)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define RCL_HORIZONTAL_FOV_TAN (RCL_VERTICAL_FOV * 4)
|
||||||
|
|
||||||
#define RCL_HORIZONTAL_FOV_HALF (RCL_HORIZONTAL_FOV / 2)
|
#define RCL_HORIZONTAL_FOV_HALF (RCL_HORIZONTAL_FOV / 2)
|
||||||
|
|
||||||
#ifndef RCL_CAMERA_COLL_RADIUS
|
#ifndef RCL_CAMERA_COLL_RADIUS
|
||||||
@ -242,7 +244,7 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
RCL_Vector2D position;
|
RCL_Vector2D position;
|
||||||
RCL_Unit direction;
|
RCL_Unit direction; // TODO: rename to "angle" to keep consistency
|
||||||
RCL_Vector2D resolution;
|
RCL_Vector2D resolution;
|
||||||
int16_t shear; /**< Shear offset in pixels (0 => no shear), can simulate
|
int16_t shear; /**< Shear offset in pixels (0 => no shear), can simulate
|
||||||
looking up/down. */
|
looking up/down. */
|
||||||
@ -305,10 +307,24 @@ typedef void
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Simple-interface function to cast a single ray.
|
Simple-interface function to cast a single ray.
|
||||||
|
|
||||||
@return The first collision result.
|
@return The first collision result.
|
||||||
*/
|
*/
|
||||||
RCL_HitResult RCL_castRay(RCL_Ray ray, RCL_ArrayFunction arrayFunc);
|
RCL_HitResult RCL_castRay(RCL_Ray ray, RCL_ArrayFunction arrayFunc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Casts a 3D ray in 3D environment with floor and optional ceiling
|
||||||
|
(ceilingHeightFunc can be 0). This can be useful for hitscan shooting,
|
||||||
|
visibility checking etc.
|
||||||
|
|
||||||
|
@return normalized ditance (0 to RCL_UNITS_PER_SQUARE) along the ray at which
|
||||||
|
the environment was hit, RCL_UNITS_PER_SQUARE means nothing was hit
|
||||||
|
*/
|
||||||
|
RCL_Unit RCL_castRay3D(
|
||||||
|
RCL_Vector2D pos1, RCL_Unit height1, RCL_Vector2D pos2, RCL_Unit height2,
|
||||||
|
RCL_ArrayFunction floorHeightFunc, RCL_ArrayFunction ceilingHeightFunc,
|
||||||
|
RCL_RayConstraints constraints);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Maps a single point in the world to the screen (2D position + depth).
|
Maps a single point in the world to the screen (2D position + depth).
|
||||||
*/
|
*/
|
||||||
@ -352,6 +368,10 @@ RCL_Unit RCL_cosInt(RCL_Unit input);
|
|||||||
|
|
||||||
RCL_Unit RCL_sinInt(RCL_Unit input);
|
RCL_Unit RCL_sinInt(RCL_Unit input);
|
||||||
|
|
||||||
|
RCL_Unit RCL_tanInt(RCL_Unit input);
|
||||||
|
|
||||||
|
RCL_Unit RCL_ctgInt(RCL_Unit input);
|
||||||
|
|
||||||
/// Normalizes given vector to have RCL_UNITS_PER_SQUARE length.
|
/// Normalizes given vector to have RCL_UNITS_PER_SQUARE length.
|
||||||
RCL_Vector2D RCL_normalize(RCL_Vector2D v);
|
RCL_Vector2D RCL_normalize(RCL_Vector2D v);
|
||||||
|
|
||||||
@ -368,10 +388,16 @@ RCL_Unit RCL_len(RCL_Vector2D v);
|
|||||||
*/
|
*/
|
||||||
RCL_Unit RCL_degreesToUnitsAngle(int16_t degrees);
|
RCL_Unit RCL_degreesToUnitsAngle(int16_t degrees);
|
||||||
|
|
||||||
///< Computes the change in size of an object due to perspective.
|
///< Computes the change in size of an object due to perspective (vertical FOV).
|
||||||
RCL_Unit RCL_perspectiveScale(RCL_Unit originalSize, RCL_Unit distance);
|
RCL_Unit RCL_perspectiveScaleVertical(RCL_Unit originalSize, RCL_Unit distance);
|
||||||
|
|
||||||
RCL_Unit RCL_perspectiveScaleInverse(RCL_Unit originalSize,
|
RCL_Unit RCL_perspectiveScaleVerticalInverse(RCL_Unit originalSize,
|
||||||
|
RCL_Unit scaledSize);
|
||||||
|
|
||||||
|
RCL_Unit
|
||||||
|
RCL_perspectiveScaleHorizontal(RCL_Unit originalSize, RCL_Unit distance);
|
||||||
|
|
||||||
|
RCL_Unit RCL_perspectiveScaleHorizontalInverse(RCL_Unit originalSize,
|
||||||
RCL_Unit scaledSize);
|
RCL_Unit scaledSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -502,7 +528,7 @@ RCL_Unit *_RCL_floorPixelDistances = 0;
|
|||||||
uint32_t profile_RCL_absVal = 0;
|
uint32_t profile_RCL_absVal = 0;
|
||||||
uint32_t profile_RCL_normalize = 0;
|
uint32_t profile_RCL_normalize = 0;
|
||||||
uint32_t profile_RCL_vectorsAngleCos = 0;
|
uint32_t profile_RCL_vectorsAngleCos = 0;
|
||||||
uint32_t profile_RCL_perspectiveScale = 0;
|
uint32_t profile_RCL_perspectiveScaleVertical = 0;
|
||||||
uint32_t profile_RCL_wrap = 0;
|
uint32_t profile_RCL_wrap = 0;
|
||||||
uint32_t profile_RCL_divRoundDown = 0;
|
uint32_t profile_RCL_divRoundDown = 0;
|
||||||
#define RCL_profileCall(c) profile_##c += 1
|
#define RCL_profileCall(c) profile_##c += 1
|
||||||
@ -521,7 +547,7 @@ RCL_Unit *_RCL_floorPixelDistances = 0;
|
|||||||
printf(" RCL_normalize: %d\n",profile_RCL_normalize);\
|
printf(" RCL_normalize: %d\n",profile_RCL_normalize);\
|
||||||
printf(" RCL_vectorsAngleCos: %d\n",profile_RCL_vectorsAngleCos);\
|
printf(" RCL_vectorsAngleCos: %d\n",profile_RCL_vectorsAngleCos);\
|
||||||
printf(" RCL_absVal: %d\n",profile_RCL_absVal);\
|
printf(" RCL_absVal: %d\n",profile_RCL_absVal);\
|
||||||
printf(" RCL_perspectiveScale: %d\n",profile_RCL_perspectiveScale);\
|
printf(" RCL_perspectiveScaleVertical: %d\n",profile_RCL_perspectiveScaleVertical);\
|
||||||
printf(" RCL_wrap: %d\n",profile_RCL_wrap);\
|
printf(" RCL_wrap: %d\n",profile_RCL_wrap);\
|
||||||
printf(" RCL_divRoundDown: %d\n",profile_RCL_divRoundDown); }
|
printf(" RCL_divRoundDown: %d\n",profile_RCL_divRoundDown); }
|
||||||
#else
|
#else
|
||||||
@ -637,6 +663,16 @@ RCL_Unit RCL_sinInt(RCL_Unit input)
|
|||||||
return RCL_cosInt(input - RCL_UNITS_PER_SQUARE / 4);
|
return RCL_cosInt(input - RCL_UNITS_PER_SQUARE / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RCL_Unit RCL_tanInt(RCL_Unit input)
|
||||||
|
{
|
||||||
|
return (RCL_sinInt(input) * RCL_UNITS_PER_SQUARE) / RCL_cosInt(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCL_Unit RCL_ctgInt(RCL_Unit input)
|
||||||
|
{
|
||||||
|
return (RCL_cosInt(input) * RCL_UNITS_PER_SQUARE) / RCL_sinInt(input);
|
||||||
|
}
|
||||||
|
|
||||||
RCL_Vector2D RCL_angleToDirection(RCL_Unit angle)
|
RCL_Vector2D RCL_angleToDirection(RCL_Unit angle)
|
||||||
{
|
{
|
||||||
RCL_profileCall(RCL_angleToDirection);
|
RCL_profileCall(RCL_angleToDirection);
|
||||||
@ -892,17 +928,6 @@ void RCL_castRayMultiHit(RCL_Ray ray, RCL_ArrayFunction arrayFunc,
|
|||||||
|
|
||||||
#if !RCL_RECTILINEAR
|
#if !RCL_RECTILINEAR
|
||||||
h.distance = RCL_dist(h.position,ray.start);
|
h.distance = RCL_dist(h.position,ray.start);
|
||||||
#else
|
|
||||||
h.distance = (h.distance * 23) / 32;
|
|
||||||
|
|
||||||
/* ^ UGLY HACK
|
|
||||||
|
|
||||||
For some reason the computed distance with rectilinear is larger, the
|
|
||||||
correct distance is about 0.711 (~= 23/32) of the computed distance, so
|
|
||||||
we correct it here in this ugly way.
|
|
||||||
|
|
||||||
TODO: investigate why, fix nicely
|
|
||||||
*/
|
|
||||||
#endif
|
#endif
|
||||||
if (typeFunc != 0)
|
if (typeFunc != 0)
|
||||||
h.type = typeFunc(currentSquare.x,currentSquare.y);
|
h.type = typeFunc(currentSquare.x,currentSquare.y);
|
||||||
@ -993,6 +1018,17 @@ void RCL_castRaysMultiHit(RCL_Camera cam, RCL_ArrayFunction arrayFunc,
|
|||||||
RCL_Vector2D dir2 =
|
RCL_Vector2D dir2 =
|
||||||
RCL_angleToDirection(cam.direction + RCL_HORIZONTAL_FOV_HALF);
|
RCL_angleToDirection(cam.direction + RCL_HORIZONTAL_FOV_HALF);
|
||||||
|
|
||||||
|
/* We scale the side distances so that the middle one is
|
||||||
|
RCL_UNITS_PER_SQUARE, which has to be this way. */
|
||||||
|
|
||||||
|
RCL_Unit cos = RCL_nonZero(RCL_cosInt(RCL_HORIZONTAL_FOV_HALF));
|
||||||
|
|
||||||
|
dir1.x = (dir1.x * RCL_UNITS_PER_SQUARE) / cos;
|
||||||
|
dir1.y = (dir1.y * RCL_UNITS_PER_SQUARE) / cos;
|
||||||
|
|
||||||
|
dir2.x = (dir2.x * RCL_UNITS_PER_SQUARE) / cos;
|
||||||
|
dir2.y = (dir2.y * RCL_UNITS_PER_SQUARE) / cos;
|
||||||
|
|
||||||
RCL_Unit dX = dir2.x - dir1.x;
|
RCL_Unit dX = dir2.x - dir1.x;
|
||||||
RCL_Unit dY = dir2.y - dir1.y;
|
RCL_Unit dY = dir2.y - dir1.y;
|
||||||
|
|
||||||
@ -1288,10 +1324,10 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t
|
|||||||
|
|
||||||
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;
|
||||||
fZ1Screen = _RCL_middleRow - RCL_perspectiveScale(
|
fZ1Screen = _RCL_middleRow - RCL_perspectiveScaleVertical(
|
||||||
(fZ1World * _RCL_camera.resolution.y) /
|
(fZ1World * _RCL_camera.resolution.y) /
|
||||||
RCL_UNITS_PER_SQUARE,distance);
|
RCL_UNITS_PER_SQUARE,distance);
|
||||||
fZ2Screen = _RCL_middleRow - RCL_perspectiveScale(
|
fZ2Screen = _RCL_middleRow - RCL_perspectiveScaleVertical(
|
||||||
(fZ2World * _RCL_camera.resolution.y) /
|
(fZ2World * _RCL_camera.resolution.y) /
|
||||||
RCL_UNITS_PER_SQUARE,distance);
|
RCL_UNITS_PER_SQUARE,distance);
|
||||||
|
|
||||||
@ -1299,10 +1335,10 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t
|
|||||||
{
|
{
|
||||||
cWallHeight = _RCL_ceilFunction(hit.square.x,hit.square.y);
|
cWallHeight = _RCL_ceilFunction(hit.square.x,hit.square.y);
|
||||||
cZ2World = cWallHeight - _RCL_camera.height;
|
cZ2World = cWallHeight - _RCL_camera.height;
|
||||||
cZ1Screen = _RCL_middleRow - RCL_perspectiveScale(
|
cZ1Screen = _RCL_middleRow - RCL_perspectiveScaleVertical(
|
||||||
(cZ1World * _RCL_camera.resolution.y) /
|
(cZ1World * _RCL_camera.resolution.y) /
|
||||||
RCL_UNITS_PER_SQUARE,distance);
|
RCL_UNITS_PER_SQUARE,distance);
|
||||||
cZ2Screen = _RCL_middleRow - RCL_perspectiveScale(
|
cZ2Screen = _RCL_middleRow - RCL_perspectiveScaleVertical(
|
||||||
(cZ2World * _RCL_camera.resolution.y) /
|
(cZ2World * _RCL_camera.resolution.y) /
|
||||||
RCL_UNITS_PER_SQUARE,distance);
|
RCL_UNITS_PER_SQUARE,distance);
|
||||||
}
|
}
|
||||||
@ -1490,13 +1526,13 @@ void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount,
|
|||||||
|
|
||||||
int16_t wallHeightWorld = _RCL_floorFunction(hit.square.x,hit.square.y);
|
int16_t wallHeightWorld = _RCL_floorFunction(hit.square.x,hit.square.y);
|
||||||
|
|
||||||
wallHeightScreen = RCL_perspectiveScale((wallHeightWorld *
|
wallHeightScreen = RCL_perspectiveScaleVertical((wallHeightWorld *
|
||||||
_RCL_camera.resolution.y) / RCL_UNITS_PER_SQUARE,dist);
|
_RCL_camera.resolution.y) / RCL_UNITS_PER_SQUARE,dist);
|
||||||
|
|
||||||
int16_t RCL_normalizedWallHeight = wallHeightWorld != 0 ?
|
int16_t RCL_normalizedWallHeight = wallHeightWorld != 0 ?
|
||||||
((RCL_UNITS_PER_SQUARE * wallHeightScreen) / wallHeightWorld) : 0;
|
((RCL_UNITS_PER_SQUARE * wallHeightScreen) / wallHeightWorld) : 0;
|
||||||
|
|
||||||
heightOffset = RCL_perspectiveScale(_RCL_cameraHeightScreen,dist);
|
heightOffset = RCL_perspectiveScaleVertical(_RCL_cameraHeightScreen,dist);
|
||||||
|
|
||||||
wallStart = _RCL_middleRow - wallHeightScreen + heightOffset +
|
wallStart = _RCL_middleRow - wallHeightScreen + heightOffset +
|
||||||
RCL_normalizedWallHeight;
|
RCL_normalizedWallHeight;
|
||||||
@ -1562,7 +1598,7 @@ static inline void _RCL_precomputeFloorDistances(RCL_Camera camera,
|
|||||||
(camera.height * camera.resolution.y) / RCL_UNITS_PER_SQUARE;
|
(camera.height * camera.resolution.y) / RCL_UNITS_PER_SQUARE;
|
||||||
|
|
||||||
for (uint16_t i = startIndex; i < camera.resolution.y; ++i)
|
for (uint16_t i = startIndex; i < camera.resolution.y; ++i)
|
||||||
dest[i] = RCL_perspectiveScaleInverse(camHeightScreenSize,
|
dest[i] = RCL_perspectiveScaleVerticalInverse(camHeightScreenSize,
|
||||||
RCL_absVal(i - _RCL_middleRow));
|
RCL_absVal(i - _RCL_middleRow));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1693,7 +1729,7 @@ RCL_PixelInfo RCL_mapToScreen(RCL_Vector2D worldPosition, RCL_Unit height,
|
|||||||
|
|
||||||
result.position.y =
|
result.position.y =
|
||||||
camera.resolution.y / 2 -
|
camera.resolution.y / 2 -
|
||||||
(RCL_perspectiveScale(height - camera.height,result.depth)
|
(RCL_perspectiveScaleVertical(height - camera.height,result.depth)
|
||||||
* camera.resolution.y) / RCL_UNITS_PER_SQUARE
|
* camera.resolution.y) / RCL_UNITS_PER_SQUARE
|
||||||
+ camera.shear;
|
+ camera.shear;
|
||||||
|
|
||||||
@ -1705,9 +1741,9 @@ RCL_Unit RCL_degreesToUnitsAngle(int16_t degrees)
|
|||||||
return (degrees * RCL_UNITS_PER_SQUARE) / 360;
|
return (degrees * RCL_UNITS_PER_SQUARE) / 360;
|
||||||
}
|
}
|
||||||
|
|
||||||
RCL_Unit RCL_perspectiveScale(RCL_Unit originalSize, RCL_Unit distance)
|
RCL_Unit RCL_perspectiveScaleVertical(RCL_Unit originalSize, RCL_Unit distance)
|
||||||
{
|
{
|
||||||
RCL_profileCall(RCL_perspectiveScale);
|
RCL_profileCall(RCL_perspectiveScaleVertical);
|
||||||
|
|
||||||
return distance != 0 ?
|
return distance != 0 ?
|
||||||
(originalSize * RCL_UNITS_PER_SQUARE) /
|
(originalSize * RCL_UNITS_PER_SQUARE) /
|
||||||
@ -1715,7 +1751,7 @@ RCL_Unit RCL_perspectiveScale(RCL_Unit originalSize, RCL_Unit distance)
|
|||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RCL_Unit RCL_perspectiveScaleInverse(RCL_Unit originalSize,
|
RCL_Unit RCL_perspectiveScaleVerticalInverse(RCL_Unit originalSize,
|
||||||
RCL_Unit scaledSize)
|
RCL_Unit scaledSize)
|
||||||
{
|
{
|
||||||
return scaledSize != 0 ?
|
return scaledSize != 0 ?
|
||||||
@ -1725,6 +1761,95 @@ RCL_Unit RCL_perspectiveScaleInverse(RCL_Unit originalSize,
|
|||||||
: RCL_INFINITY;
|
: RCL_INFINITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RCL_Unit
|
||||||
|
RCL_perspectiveScaleHorizontal(RCL_Unit originalSize, RCL_Unit distance)
|
||||||
|
{
|
||||||
|
return distance != 0 ?
|
||||||
|
(originalSize * RCL_UNITS_PER_SQUARE) /
|
||||||
|
((RCL_HORIZONTAL_FOV_TAN * 2 * distance) / RCL_UNITS_PER_SQUARE)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RCL_Unit RCL_perspectiveScaleHorizontalInverse(RCL_Unit originalSize,
|
||||||
|
RCL_Unit scaledSize)
|
||||||
|
{
|
||||||
|
return scaledSize != 0 ?
|
||||||
|
(originalSize * RCL_UNITS_PER_SQUARE + RCL_UNITS_PER_SQUARE / 2) /
|
||||||
|
((RCL_HORIZONTAL_FOV_TAN * 2 * scaledSize) / RCL_UNITS_PER_SQUARE)
|
||||||
|
: RCL_INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
RCL_Unit RCL_castRay3D(
|
||||||
|
RCL_Vector2D pos1, RCL_Unit height1, RCL_Vector2D pos2, RCL_Unit height2,
|
||||||
|
RCL_ArrayFunction floorHeightFunc, RCL_ArrayFunction ceilingHeightFunc,
|
||||||
|
RCL_RayConstraints constraints)
|
||||||
|
{
|
||||||
|
RCL_HitResult hits[constraints.maxHits];
|
||||||
|
uint16_t numHits;
|
||||||
|
|
||||||
|
RCL_Ray ray;
|
||||||
|
|
||||||
|
ray.start = pos1;
|
||||||
|
|
||||||
|
RCL_Unit distance;
|
||||||
|
|
||||||
|
ray.direction.x = pos2.x - pos1.x;
|
||||||
|
ray.direction.y = pos2.y - pos1.y;
|
||||||
|
|
||||||
|
distance = RCL_len(ray.direction);
|
||||||
|
|
||||||
|
ray.direction = RCL_normalize(ray.direction);
|
||||||
|
|
||||||
|
RCL_Unit heightDiff = height2 - height1;
|
||||||
|
|
||||||
|
RCL_castRayMultiHit(ray,floorHeightFunc,0,hits,&numHits,constraints);
|
||||||
|
|
||||||
|
RCL_Unit result = RCL_UNITS_PER_SQUARE;
|
||||||
|
|
||||||
|
int16_t squareX = RCL_divRoundDown(pos1.x,RCL_UNITS_PER_SQUARE);
|
||||||
|
int16_t squareY = RCL_divRoundDown(pos1.y,RCL_UNITS_PER_SQUARE);
|
||||||
|
|
||||||
|
RCL_Unit startHeight = floorHeightFunc(squareX,squareY);
|
||||||
|
|
||||||
|
#define checkHits(comp,res) \
|
||||||
|
{ \
|
||||||
|
RCL_Unit currentHeight = startHeight; \
|
||||||
|
for (uint16_t i = 0; i < numHits; ++i) \
|
||||||
|
{ \
|
||||||
|
if (hits[i].distance > distance) \
|
||||||
|
break;\
|
||||||
|
RCL_Unit h = hits[i].arrayValue; \
|
||||||
|
if ((currentHeight comp h ? currentHeight : h) \
|
||||||
|
comp (height1 + (hits[i].distance * heightDiff) / distance)) \
|
||||||
|
{ \
|
||||||
|
res = (hits[i].distance * RCL_UNITS_PER_SQUARE) / distance; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
currentHeight = h; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
checkHits(>,result)
|
||||||
|
|
||||||
|
if (ceilingHeightFunc != 0)
|
||||||
|
{
|
||||||
|
RCL_Unit result2 = RCL_UNITS_PER_SQUARE;
|
||||||
|
|
||||||
|
startHeight = ceilingHeightFunc(squareX,squareY);
|
||||||
|
|
||||||
|
RCL_castRayMultiHit(ray,ceilingHeightFunc,0,hits,&numHits,constraints);
|
||||||
|
|
||||||
|
checkHits(<,result2)
|
||||||
|
|
||||||
|
if (result2 < result)
|
||||||
|
result = result2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef checkHits
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void RCL_moveCameraWithCollision(RCL_Camera *camera, RCL_Vector2D planeOffset,
|
void RCL_moveCameraWithCollision(RCL_Camera *camera, RCL_Vector2D planeOffset,
|
||||||
RCL_Unit heightOffset, RCL_ArrayFunction floorHeightFunc,
|
RCL_Unit heightOffset, RCL_ArrayFunction floorHeightFunc,
|
||||||
RCL_ArrayFunction ceilingHeightFunc, int8_t computeHeight, int8_t force)
|
RCL_ArrayFunction ceilingHeightFunc, int8_t computeHeight, int8_t force)
|
||||||
|
Loading…
Reference in New Issue
Block a user