move raycastign to its own file
This commit is contained in:
parent
1604da0611
commit
edec8789a9
5 changed files with 172 additions and 121 deletions
17
src/map.h
Normal file
17
src/map.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MAP_SIZE 8
|
||||||
|
static uint8_t MAPDATA[MAP_SIZE * MAP_SIZE] = {
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 3, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 2, 0, 4, 4, 0, 1,
|
||||||
|
1, 0, 0, 0, 4, 0, 0, 1,
|
||||||
|
1, 0, 3, 0, 0, 0, 0, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define value(x, y) (MAPDATA[(x) + MAP_SIZE * (y)])
|
106
src/ray.c
Normal file
106
src/ray.c
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
#include "ray.h"
|
||||||
|
#include "map.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
float v2_cross(v2 a, v2 b) {
|
||||||
|
return fabs(a.x * b.y - a.y * b.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
float v2_len(v2 a) {
|
||||||
|
return sqrt(a.x * a.x + a.y * a.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float v2_square_dist(v2 a, v2 b) {
|
||||||
|
return pow(a.x - b.x, 2) + pow(a.y - b.y, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PI 3.14159265358979323846
|
||||||
|
#define PIH 1.57079632679489661923
|
||||||
|
#define PI2 6.28318530718
|
||||||
|
|
||||||
|
uint32_t cast_ray(v2 pos, float theta, v2* hit_pos) {
|
||||||
|
|
||||||
|
const v2i move = {
|
||||||
|
#define sign(a) ((a) < 0 ? -1 : 1)
|
||||||
|
sign(cos(theta)),
|
||||||
|
sign(sin(theta)),
|
||||||
|
};
|
||||||
|
|
||||||
|
const v2i offset = {
|
||||||
|
move.x == -1 ? 1 : 0,
|
||||||
|
move.y == -1 ? 1 : 0
|
||||||
|
};
|
||||||
|
|
||||||
|
const float tanc = tan(theta);
|
||||||
|
const float cotc = tan(PIH - (theta));
|
||||||
|
|
||||||
|
v2i posi = {
|
||||||
|
(int)pos.x + offset.x,
|
||||||
|
(int)pos.y + offset.y
|
||||||
|
};
|
||||||
|
|
||||||
|
bool fx = false;
|
||||||
|
uint32_t vx = 0;
|
||||||
|
float x;
|
||||||
|
|
||||||
|
while (!fx) {
|
||||||
|
posi.y += move.y;
|
||||||
|
x = cotc * (posi.y - pos.y) + pos.x;
|
||||||
|
|
||||||
|
if (fabs(x) - pos.x >= MAP_SIZE) break;
|
||||||
|
|
||||||
|
vx = value((int)x, posi.y - offset.y);
|
||||||
|
|
||||||
|
if (vx != 0) {
|
||||||
|
fx = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fy = false;
|
||||||
|
uint32_t vy = 0;
|
||||||
|
float y;
|
||||||
|
|
||||||
|
while (!fy) {
|
||||||
|
posi.x += move.x;
|
||||||
|
y = tanc * (posi.x - pos.x) + pos.y;
|
||||||
|
|
||||||
|
if (fabs(y) - pos.y >= MAP_SIZE) break;
|
||||||
|
|
||||||
|
vy = value(posi.x - offset.x, (int)y);
|
||||||
|
|
||||||
|
if (vy != 0) {
|
||||||
|
fy = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t hit;
|
||||||
|
if (!fx && !fy) {
|
||||||
|
hit = 0;
|
||||||
|
hit_pos->x = pos.x + 1000 * move.x;
|
||||||
|
hit_pos->y = pos.y + 1000 * move.y;
|
||||||
|
return false;
|
||||||
|
} else if (fx && !fy) {
|
||||||
|
hit = vx;
|
||||||
|
hit_pos->x = x;
|
||||||
|
hit_pos->y = posi.y;
|
||||||
|
} else if (fy && !fx) {
|
||||||
|
hit = vy;
|
||||||
|
hit_pos->x = posi.x;
|
||||||
|
hit_pos->y = y;
|
||||||
|
} else {
|
||||||
|
const v2 posx = {x, posi.y};
|
||||||
|
const v2 posy = {posi.x, y};
|
||||||
|
if (v2_square_dist(posx, pos) < v2_square_dist(posy, pos)) {
|
||||||
|
hit = vx;
|
||||||
|
hit_pos->x = x;
|
||||||
|
hit_pos->y = posi.y;
|
||||||
|
} else {
|
||||||
|
hit = vy;
|
||||||
|
hit_pos->x = posi.x;
|
||||||
|
hit_pos->y= y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hit;
|
||||||
|
}
|
20
src/ray.h
Normal file
20
src/ray.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x, y;
|
||||||
|
} v2;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int x, y;
|
||||||
|
} v2i;
|
||||||
|
|
||||||
|
|
||||||
|
float v2_cross(v2 a, v2 b);
|
||||||
|
float v2_len(v2 a);
|
||||||
|
float v2_square_dist(v2 a, v2 b);
|
||||||
|
v2 v2_add(v2 a, v2 b);
|
||||||
|
|
||||||
|
uint32_t cast_ray(v2 pos, float theta, v2* hit_pos);
|
146
src/renderer.c
146
src/renderer.c
|
@ -1,5 +1,6 @@
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
#include "ray.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
@ -13,16 +14,11 @@ void init_camera(Camera* camera) {
|
||||||
camera->angle = PI / 4;
|
camera->angle = PI / 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
static double fov = PI / 4;
|
||||||
float x, y;
|
|
||||||
} v2;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int x, y;
|
|
||||||
} v2i;
|
|
||||||
|
|
||||||
#define MOVE_SPEED 1
|
#define MOVE_SPEED 1
|
||||||
#define ROTATE_SPEED PI / 2
|
#define ROTATE_SPEED PI / 2
|
||||||
|
#define FOV_CHANGE_SPEED 1
|
||||||
void update_camera(Camera* camera, Screen* screen) {
|
void update_camera(Camera* camera, Screen* screen) {
|
||||||
double rotate = 0;
|
double rotate = 0;
|
||||||
|
|
||||||
|
@ -63,22 +59,25 @@ void update_camera(Camera* camera, Screen* screen) {
|
||||||
move.y -= left.y;
|
move.y -= left.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key_pressed(screen, SDL_SCANCODE_EQUALS)) {
|
||||||
|
fov += FOV_CHANGE_SPEED * screen->delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_pressed(screen, SDL_SCANCODE_MINUS)) {
|
||||||
|
fov -= FOV_CHANGE_SPEED * screen->delta;
|
||||||
|
}
|
||||||
|
|
||||||
camera->x += move.x * MOVE_SPEED * screen->delta;
|
camera->x += move.x * MOVE_SPEED * screen->delta;
|
||||||
camera->y += move.y * MOVE_SPEED * screen->delta;
|
camera->y += move.y * MOVE_SPEED * screen->delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v2 get_cam_right(const Camera* camera) {
|
||||||
#define MAP_SIZE 8
|
v2 cam_right = {
|
||||||
static uint8_t MAPDATA[MAP_SIZE * MAP_SIZE] = {
|
-sin(camera->angle),
|
||||||
1, 1, 1, 1, 1, 1, 1, 1,
|
cos(camera->angle)
|
||||||
1, 0, 0, 0, 0, 0, 0, 1,
|
};
|
||||||
1, 0, 0, 0, 0, 3, 0, 1,
|
return cam_right;
|
||||||
1, 0, 0, 0, 0, 0, 0, 1,
|
}
|
||||||
1, 0, 2, 0, 4, 4, 0, 1,
|
|
||||||
1, 0, 0, 0, 4, 0, 0, 1,
|
|
||||||
1, 0, 3, 0, 0, 0, 0, 1,
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void verline(Screen* screen, int x, int y0, int y1, uint32_t color) {
|
static void verline(Screen* screen, int x, int y0, int y1, uint32_t color) {
|
||||||
for (int y = y0; y <= y1; y++) {
|
for (int y = y0; y <= y1; y++) {
|
||||||
|
@ -86,124 +85,31 @@ static void verline(Screen* screen, int x, int y0, int y1, uint32_t color) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static float v2_cross(v2 a, v2 b) {
|
|
||||||
return fabs(a.x * b.y - a.y * b.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
static float v2_len(v2 a) {
|
|
||||||
return sqrt(a.x * a.x + a.y * a.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static float v2_square_dist(v2 a, v2 b) {
|
|
||||||
return pow(a.x - b.x, 2) + pow(a.y - b.y, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||||
#define sign(a) ((a) < 0 ? -1 : 1)
|
|
||||||
#define value(x, y) (MAPDATA[(x) + MAP_SIZE * (y)])
|
|
||||||
|
|
||||||
void render(Screen* screen, const Camera* camera) {
|
void render(Screen* screen, const Camera* camera) {
|
||||||
|
|
||||||
const double fov = PI / 3;
|
|
||||||
|
|
||||||
const v2 cam_right = {
|
|
||||||
-sin(camera->angle),
|
|
||||||
cos(camera->angle)
|
|
||||||
};
|
|
||||||
|
|
||||||
const v2 pos = {
|
const v2 pos = {
|
||||||
camera->x,
|
camera->x,
|
||||||
camera->y
|
camera->y
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const v2 cam_right = get_cam_right(camera);
|
||||||
|
|
||||||
for (int sx = 0; sx < screen->width; sx++) {
|
for (int sx = 0; sx < screen->width; sx++) {
|
||||||
|
|
||||||
const float xcam = (2 * (sx / (float) (screen->width))) - 1;
|
const float xcam = (2 * (sx / (float) (screen->width))) - 1;
|
||||||
const float change = fov * atan(xcam);
|
const float change = fov * atan(xcam);
|
||||||
|
const float theta = camera->angle + change;
|
||||||
|
|
||||||
const v2i move = {
|
v2 hit_pos;
|
||||||
sign(cos(camera->angle + change)),
|
uint32_t hit = cast_ray(pos, theta, &hit_pos);
|
||||||
sign(sin(camera->angle + change)),
|
|
||||||
};
|
|
||||||
|
|
||||||
const v2i offset = {
|
hit_pos.x -= pos.x;
|
||||||
move.x == -1 ? 1 : 0,
|
hit_pos.y -= pos.y;
|
||||||
move.y == -1 ? 1 : 0
|
|
||||||
};
|
|
||||||
|
|
||||||
const float tanc = tan(camera->angle + change);
|
float len = v2_cross(hit_pos, cam_right) / v2_len(cam_right);
|
||||||
const float cotc = tan(PIH - (camera->angle + change));
|
|
||||||
|
|
||||||
v2i posi = {
|
|
||||||
(int)pos.x + offset.x,
|
|
||||||
(int)pos.y + offset.y
|
|
||||||
};
|
|
||||||
|
|
||||||
bool fx = false;
|
|
||||||
uint32_t vx = 0;
|
|
||||||
float x;
|
|
||||||
|
|
||||||
while (!fx) {
|
|
||||||
posi.y += move.y;
|
|
||||||
x = cotc * (posi.y - pos.y) + pos.x;
|
|
||||||
|
|
||||||
if (fabs(x) - pos.x >= MAP_SIZE) break;
|
|
||||||
|
|
||||||
vx = value((int)x, posi.y - offset.y);
|
|
||||||
|
|
||||||
if (vx != 0) {
|
|
||||||
fx = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fy = false;
|
|
||||||
uint32_t vy = 0;
|
|
||||||
float y;
|
|
||||||
|
|
||||||
while (!fy) {
|
|
||||||
posi.x += move.x;
|
|
||||||
y = tanc * (posi.x - pos.x) + pos.y;
|
|
||||||
|
|
||||||
if (fabs(y) - pos.y >= MAP_SIZE) break;
|
|
||||||
|
|
||||||
vy = value(posi.x - offset.x, (int)y);
|
|
||||||
|
|
||||||
if (vy != 0) {
|
|
||||||
fy = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t hit;
|
|
||||||
if (!fx && !fy) {
|
|
||||||
hit = 0;
|
|
||||||
x = pos.x + 1000 * move.x;
|
|
||||||
y = pos.y + 1000 * move.y;
|
|
||||||
} else if (fx && !fy) {
|
|
||||||
hit = vx;
|
|
||||||
y = posi.y;
|
|
||||||
} else if (fy && !fx) {
|
|
||||||
hit = vy;
|
|
||||||
x = posi.x;
|
|
||||||
} else {
|
|
||||||
const v2 posx = {x, posi.y};
|
|
||||||
const v2 posy = {posi.x, y};
|
|
||||||
if (v2_square_dist(posx, pos) < v2_square_dist(posy, pos)) {
|
|
||||||
hit = vx;
|
|
||||||
y = posi.y;
|
|
||||||
} else {
|
|
||||||
hit = vy;
|
|
||||||
x = posi.x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const v2 relative = {
|
|
||||||
x - pos.x,
|
|
||||||
y - pos.y
|
|
||||||
};
|
|
||||||
|
|
||||||
float len = v2_cross(relative, cam_right) / v2_len(cam_right);
|
|
||||||
if (len < 0.00001) len = 0.00001;
|
|
||||||
|
|
||||||
uint32_t color;
|
uint32_t color;
|
||||||
switch (hit) {
|
switch (hit) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
#include "ray.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float x, y;
|
float x, y;
|
||||||
|
@ -9,5 +10,6 @@ typedef struct {
|
||||||
|
|
||||||
void init_camera(Camera* camera);
|
void init_camera(Camera* camera);
|
||||||
void update_camera(Camera* camera, Screen* screeen);
|
void update_camera(Camera* camera, Screen* screeen);
|
||||||
|
v2 get_cam_right(const Camera* camera);
|
||||||
|
|
||||||
void render(Screen* screen, const Camera* camera);
|
void render(Screen* screen, const Camera* camera);
|
||||||
|
|
Loading…
Reference in a new issue