mirror of
https://git.coom.tech/drummyfish/raycastlib.git
synced 2024-11-21 20:29:59 +01:00
Fix division by 0
This commit is contained in:
parent
8c5231cf9f
commit
c25fdd486b
2 changed files with 117 additions and 37 deletions
|
@ -1184,7 +1184,7 @@ PixelInfo mapToScreen(Vector2D worldPosition, Unit height, Camera camera)
|
||||||
(result.depth * sinInt(HORIZONTAL_FOV_HALF)) / (cos == 0 ? 1 : cos);
|
(result.depth * sinInt(HORIZONTAL_FOV_HALF)) / (cos == 0 ? 1 : cos);
|
||||||
// sin/cos = tan
|
// sin/cos = tan
|
||||||
|
|
||||||
result.position.x = (a * middleColumn) / b;
|
result.position.x = (a * middleColumn) / (b == 0 ? 1 : b);
|
||||||
result.position.x = middleColumn - result.position.x;
|
result.position.x = middleColumn - result.position.x;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
152
testSDL.c
152
testSDL.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Raycasting SDL test.
|
Raycasting SDL test. This is a port of my Pokitto demo.
|
||||||
|
|
||||||
author: Miloslav Ciz
|
author: Miloslav Ciz
|
||||||
license: CC0
|
license: CC0
|
||||||
|
@ -25,6 +25,10 @@
|
||||||
#define SCREEN_HEIGHT 480
|
#define SCREEN_HEIGHT 480
|
||||||
#define MIDDLE_ROW (SCREEN_HEIGHT / 2)
|
#define MIDDLE_ROW (SCREEN_HEIGHT / 2)
|
||||||
|
|
||||||
|
#define TRANSPARENT_COLOR 0b00000111
|
||||||
|
|
||||||
|
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
|
||||||
#define KEYS 6
|
#define KEYS 6
|
||||||
#define KEY_UP 0
|
#define KEY_UP 0
|
||||||
#define KEY_RIGHT 1
|
#define KEY_RIGHT 1
|
||||||
|
@ -49,7 +53,7 @@ typedef struct
|
||||||
Unit mPixelSize;
|
Unit mPixelSize;
|
||||||
} Sprite;
|
} Sprite;
|
||||||
|
|
||||||
#define RGB(r,g,b) (0 | ((r << 24) | (g << 16) | (b << 8)))
|
uint32_t palette[256];
|
||||||
|
|
||||||
#define SPRITES 7
|
#define SPRITES 7
|
||||||
#define SPRITE_MAX_DISTANCE 5 * UNITS_PER_SQUARE
|
#define SPRITE_MAX_DISTANCE 5 * UNITS_PER_SQUARE
|
||||||
|
@ -750,12 +754,15 @@ Unit floorHeightAt(int16_t x, int16_t y)
|
||||||
if (x >= 0 && x < LEVEL_X_RES && y >= 0 && y < LEVEL_Y_RES)
|
if (x >= 0 && x < LEVEL_X_RES && y >= 0 && y < LEVEL_Y_RES)
|
||||||
return (levelFloor[(LEVEL_Y_RES - y -1) * LEVEL_X_RES + x] * UNITS_PER_SQUARE) / 8;
|
return (levelFloor[(LEVEL_Y_RES - y -1) * LEVEL_X_RES + x] * UNITS_PER_SQUARE) / 8;
|
||||||
|
|
||||||
return 0;
|
int a = absVal(x - LEVEL_X_RES / 2) - LEVEL_X_RES / 2;
|
||||||
|
int b = absVal(y - LEVEL_Y_RES / 2) - LEVEL_Y_RES / 2;
|
||||||
|
|
||||||
|
return (a > b ? a : b) * UNITS_PER_SQUARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Unit ceilingHeightAt(int16_t x, int16_t y)
|
Unit ceilingHeightAt(int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
signed char v = 127;
|
int v = 1024;
|
||||||
|
|
||||||
if (x >= 0 && x < LEVEL_X_RES && y >= 0 && y < LEVEL_Y_RES)
|
if (x >= 0 && x < LEVEL_X_RES && y >= 0 && y < LEVEL_Y_RES)
|
||||||
v = levelCeiling[(LEVEL_Y_RES - y -1) * LEVEL_X_RES + x];
|
v = levelCeiling[(LEVEL_Y_RES - y -1) * LEVEL_X_RES + x];
|
||||||
|
@ -763,6 +770,52 @@ Unit ceilingHeightAt(int16_t x, int16_t y)
|
||||||
return (v * UNITS_PER_SQUARE) / 8;
|
return (v * UNITS_PER_SQUARE) / 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Draws a scaled sprite on screen in an optimized way. The sprite has to be
|
||||||
|
square in resolution.
|
||||||
|
*/
|
||||||
|
void drawSpriteSquare(const unsigned char *sprite, int16_t x, int16_t y, Unit depth, int16_t size)
|
||||||
|
{
|
||||||
|
if (size < 0 || size > 200 || // let's not mess up with the incoming array
|
||||||
|
sprite[0] != sprite[1]) // only draw square sprites
|
||||||
|
return;
|
||||||
|
|
||||||
|
int16_t samplingIndices[size];
|
||||||
|
|
||||||
|
// optimization: precompute the indices
|
||||||
|
|
||||||
|
for (Unit i = 0; i < size; ++i)
|
||||||
|
samplingIndices[i] = (i * sprite[0]) / size;
|
||||||
|
|
||||||
|
x -= size / 2;
|
||||||
|
y -= size / 2;
|
||||||
|
|
||||||
|
Unit step = UNITS_PER_SQUARE / size;
|
||||||
|
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
|
int16_t jTo = size - max(0,y + size - 88);
|
||||||
|
int16_t iTo = size - max(0,x + size - 110);
|
||||||
|
|
||||||
|
for (Unit i = max(-1 * x,0); i < iTo; ++i)
|
||||||
|
{
|
||||||
|
int16_t xPos = x + i;
|
||||||
|
|
||||||
|
if (zBuffer[xPos] <= depth)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int16_t columnLocation = 2 + samplingIndices[i] * sprite[0];
|
||||||
|
|
||||||
|
for (Unit j = max(-1 * y,0); j < jTo; ++j)
|
||||||
|
{
|
||||||
|
c = sprite[columnLocation + samplingIndices[j]];
|
||||||
|
|
||||||
|
if (c != TRANSPARENT_COLOR)
|
||||||
|
pixels[j * SCREEN_WIDTH + i] = c | c | c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Function for drawing a single pixel (like fragment shader). Bottleneck =>
|
Function for drawing a single pixel (like fragment shader). Bottleneck =>
|
||||||
should be as fast as possible.
|
should be as fast as possible.
|
||||||
|
@ -774,33 +827,30 @@ void pixelFunc(PixelInfo *pixel)
|
||||||
|
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
|
|
||||||
Unit depth = pixel->depth - UNITS_PER_SQUARE * 3;
|
|
||||||
depth = depth > 0 ? depth : 1;
|
|
||||||
|
|
||||||
int intensity = 7 - (depth * 7) / (UNITS_PER_SQUARE * 5);
|
|
||||||
|
|
||||||
if (intensity < 0)
|
|
||||||
intensity = 0;
|
|
||||||
|
|
||||||
//intensity = 5;
|
|
||||||
|
|
||||||
if (pixel->isWall)
|
if (pixel->isWall)
|
||||||
{
|
|
||||||
if ((pixel->hit.direction == 0 || pixel->hit.direction == 2))
|
|
||||||
intensity -= 2;
|
|
||||||
|
|
||||||
if (intensity < 0)
|
|
||||||
intensity = 0;
|
|
||||||
|
|
||||||
c = sampleImage(textures[pixel->hit.type],pixel->hit.textureCoord,pixel->textureCoordY);
|
c = sampleImage(textures[pixel->hit.type],pixel->hit.textureCoord,pixel->textureCoordY);
|
||||||
c = addIntensity(c,intensity - 3);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
c = pixel->isFloor ?
|
c = pixel->isFloor ? 0b00010001 : 0b00001010;
|
||||||
rgbToIndex(intensity/2,intensity,intensity/3) :
|
|
||||||
rgbToIndex(intensity,intensity/2,0);
|
|
||||||
|
|
||||||
pixels[pixel->position.y * SCREEN_WIDTH + pixel->position.x] = RGB( (c & 0b00000111) * 36, ((c & 0b00111000) >> 3) * 36 , ((c & 0b11000000) >> 6) * 85 );
|
int intensity = pixel->depth - 8 * UNITS_PER_SQUARE;
|
||||||
|
intensity = intensity < 0 ? 0 : intensity;
|
||||||
|
intensity = (intensity * 32) / UNITS_PER_SQUARE;
|
||||||
|
|
||||||
|
int32_t color = palette[c];
|
||||||
|
|
||||||
|
int32_t r = ((color & 0xFF000000) >> 24) - intensity;
|
||||||
|
r = r > 0 ? r : 0;
|
||||||
|
r = r << 24;
|
||||||
|
|
||||||
|
int32_t g = ((color & 0x00FF0000) >> 16) - intensity;
|
||||||
|
g = g > 0 ? g : 0;
|
||||||
|
g = g << 16;
|
||||||
|
|
||||||
|
int32_t b = ((color & 0x0000FF00) >> 8) - intensity;
|
||||||
|
b = b > 0 ? b : 0;
|
||||||
|
b = b << 8;
|
||||||
|
|
||||||
|
pixels[pixel->position.y * SCREEN_WIDTH + pixel->position.x] = r | g | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw()
|
void draw()
|
||||||
|
@ -808,16 +858,13 @@ void draw()
|
||||||
RayConstraints c;
|
RayConstraints c;
|
||||||
|
|
||||||
c.maxHits = 16;
|
c.maxHits = 16;
|
||||||
// c.maxSteps = 10;
|
c.maxSteps = 20;
|
||||||
c.maxSteps = 20;
|
|
||||||
|
|
||||||
c.computeTextureCoords = 1;
|
c.computeTextureCoords = 1;
|
||||||
render(camera,floorHeightAt,ceilingHeightAt,textureAt,pixelFunc,c);
|
render(camera,floorHeightAt,ceilingHeightAt,textureAt,pixelFunc,c);
|
||||||
|
|
||||||
Unit previousDepth;
|
Unit previousDepth;
|
||||||
|
|
||||||
// draw sprites
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < SPRITES; ++i)
|
for (uint8_t i = 0; i < SPRITES; ++i)
|
||||||
{
|
{
|
||||||
// use Chebyshew distance instead Euclidean, it's faster
|
// use Chebyshew distance instead Euclidean, it's faster
|
||||||
|
@ -828,6 +875,20 @@ c.maxSteps = 20;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PixelInfo pos = mapToScreen(sprites[i].mPosition,sprites[i].mHeight,camera);
|
PixelInfo pos = mapToScreen(sprites[i].mPosition,sprites[i].mHeight,camera);
|
||||||
|
|
||||||
|
if (pos.depth > 0)
|
||||||
|
drawSpriteSquare(sprites[i].mImage,pos.position.x,pos.position.y,
|
||||||
|
pos.depth,perspectiveScale(sprites[i].mPixelSize,pos.depth));
|
||||||
|
|
||||||
|
/* trick: sort the sprites by distance with bubble sort as we draw - the
|
||||||
|
order will be correct in a few frames */
|
||||||
|
if (i != 0 && pos.depth > previousDepth)
|
||||||
|
{
|
||||||
|
Sprite tmp = sprites[i];
|
||||||
|
sprites[i] = sprites[i - 1];
|
||||||
|
sprites[i - 1] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
previousDepth = pos.depth;
|
previousDepth = pos.depth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -837,17 +898,36 @@ int main()
|
||||||
for (int i = 0; i < SCREEN_WIDTH; ++i)
|
for (int i = 0; i < SCREEN_WIDTH; ++i)
|
||||||
zBuffer[i] = 0;
|
zBuffer[i] = 0;
|
||||||
|
|
||||||
camera.position.x = 5;
|
for (uint8_t r = 0; r < 8; ++r)
|
||||||
camera.position.y = 5;
|
for (uint8_t g = 0; g < 8; ++g)
|
||||||
|
for (uint8_t b = 0; b < 4; ++b)
|
||||||
|
palette[rgbToIndex(r,g,b)] = ((36 * r) << 24) | ((36 * g) << 16) | ((85 * b) << 8);
|
||||||
|
|
||||||
|
#define placeSprite(i,s,X,Y,z,n)\
|
||||||
|
sprites[i].mImage = s;\
|
||||||
|
sprites[i].mPosition.x = X * UNITS_PER_SQUARE;\
|
||||||
|
sprites[i].mPosition.y = Y * UNITS_PER_SQUARE;\
|
||||||
|
sprites[i].mHeight = z;\
|
||||||
|
sprites[i].mPixelSize = n;
|
||||||
|
|
||||||
|
placeSprite(0,sprite1,10,5,1,100);
|
||||||
|
placeSprite(1,sprite1,14,5,1,100);
|
||||||
|
placeSprite(2,sprite2,15,19,1,200);
|
||||||
|
placeSprite(3,sprite3,8,2,1,300);
|
||||||
|
placeSprite(4,sprite3,20,5,1,300);
|
||||||
|
placeSprite(5,sprite3,26,18,1,300);
|
||||||
|
placeSprite(6,sprite3,16,12,1,300);
|
||||||
|
|
||||||
|
#undef placeSprite
|
||||||
|
|
||||||
|
camera.position.x = UNITS_PER_SQUARE * 5;
|
||||||
|
camera.position.y = UNITS_PER_SQUARE * 4;
|
||||||
camera.shear = 0;
|
camera.shear = 0;
|
||||||
camera.direction = 0;
|
camera.direction = 0;
|
||||||
camera.height = UNITS_PER_SQUARE * 2;
|
camera.height = UNITS_PER_SQUARE * 2;
|
||||||
camera.resolution.x = SCREEN_WIDTH;
|
camera.resolution.x = SCREEN_WIDTH;
|
||||||
camera.resolution.y = SCREEN_HEIGHT;
|
camera.resolution.y = SCREEN_HEIGHT;
|
||||||
|
|
||||||
for (int i = 0; i < KEYS; ++i)
|
|
||||||
keys[i] = 0;
|
|
||||||
|
|
||||||
SDL_Window *window = SDL_CreateWindow("raycasting", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
|
SDL_Window *window = SDL_CreateWindow("raycasting", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
|
||||||
SDL_Renderer *renderer = SDL_CreateRenderer(window,-1,0);
|
SDL_Renderer *renderer = SDL_CreateRenderer(window,-1,0);
|
||||||
SDL_Texture *texture = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBX8888, SDL_TEXTUREACCESS_STATIC, SCREEN_WIDTH, SCREEN_HEIGHT);
|
SDL_Texture *texture = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBX8888, SDL_TEXTUREACCESS_STATIC, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
|
|
Loading…
Reference in a new issue