diff options
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | capture.c | 3 | ||||
| -rw-r--r-- | cub3d.h | 52 | ||||
| -rw-r--r-- | helper.c | 180 | ||||
| m--------- | libft | 0 | ||||
| -rw-r--r-- | main.c | 3 | ||||
| -rw-r--r-- | render.c | 98 | ||||
| -rw-r--r-- | render_state.c | 187 | ||||
| -rw-r--r-- | state.c | 3 | ||||
| -rw-r--r-- | vector.c | 8 |
10 files changed, 288 insertions, 247 deletions
@@ -18,6 +18,7 @@ SRC = main.c \ state.c \ vector.c \ render.c \ + render_state.c \ helper.c \ error.c \ capture.c @@ -6,7 +6,7 @@ /* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/01/11 13:15:11 by cacharle #+# #+# */ -/* Updated: 2020/01/11 13:32:54 by cacharle ### ########.fr */ +/* Updated: 2020/01/15 15:08:34 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,5 +21,4 @@ int capture(t_state *state) void write_bmp(t_image *image) { - } @@ -6,7 +6,7 @@ /* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/11/15 06:40:37 by cacharle #+# #+# */ -/* Updated: 2020/01/12 15:35:49 by cacharle ### ########.fr */ +/* Updated: 2020/01/15 15:10:45 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ #include <stdio.h> @@ -21,6 +21,8 @@ # include "mlx.h" # include "libft.h" +# define BUFFER_SIZE 64 + # define WINDOW_TITLE "cub3D" # define MLXK_ESC 53 # define MLXK_W 13 @@ -113,6 +115,26 @@ typedef struct s_state t_image textures[TEXTURES_NUM]; } t_state; +typedef enum +{ + SIDE_NS, + SIDE_WE +} t_side; + +typedef struct s_render_state +{ + int x; + t_vector ray; + t_vector map_pos; + t_vector delta; + t_side side; + int line_height; + t_vector probe; + t_vector map_step; + int draw_start; + int draw_end; +} t_render_state; + typedef t_bool (*t_option_parser_func)(t_state *state, char *line); typedef struct s_option_parser @@ -121,12 +143,6 @@ typedef struct s_option_parser t_option_parser_func func; } t_option_parser; -typedef enum -{ - SIDE_NS, - SIDE_WE -} t_side; - /* ** parse/parse.c */ @@ -189,15 +205,22 @@ void load_texture(void *mlx_ptr, t_image *image, char *path); int render_update(void *param); void render_update_window(t_state *state); void render_column(t_state *state, int x); +void render_window_column(t_state *state, t_render_state *rstate); /* ** vector.c */ +# define VECTOR_MINUS(v) vector_scale(v, -1.0) +# define VECTOR_SUB(v, w) vector_add(v, VECTOR_MINUS(w)) +# define VECTOR_ADD_CONST(v, c) vector_add(v, vector_new(c, c)) + t_vector vector_add(t_vector a, t_vector b); t_vector vector_scale(t_vector v, double scalar); t_vector vector_rotate(t_vector v, double angle); double vector_norm(t_vector v); +t_vector vector_new(double x, double y); +t_vector vector_apply(t_vector v, double (*f)(double)); /* ** error.c @@ -217,6 +240,21 @@ void *error_put_return_lines_state_destroy( t_bool helper_is_player_cell(t_cell cell); void helper_free_splited(char **splited); void helper_rotate_player(t_state *state, double rotation); +void helper_init_dir_plane(t_state *state, int y, int x); +// int get_tex_x() + +/* +** render_state.c +*/ + +void rstate_ray(t_state *state, t_render_state *rstate); +void rstate_delta(t_render_state *rstate); +void rstate_init_probe(t_state *state, t_render_state *rstate); +double rstate_perp_dist(t_state *state, t_render_state *rstate); +void rstate_line_height(t_state *state, t_render_state *rstate); +void rstate_next_probe(t_render_state *rstate); +t_image *get_tex(t_state *state, t_render_state *rstate); + /* ** capture.c @@ -6,7 +6,7 @@ /* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/01/11 07:32:20 by cacharle #+# #+# */ -/* Updated: 2020/01/12 15:43:29 by cacharle ### ########.fr */ +/* Updated: 2020/01/15 14:40:49 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -51,181 +51,3 @@ void helper_init_dir_plane(t_state *state, int y, int x) state->plane = vector_scale(state->plane, 0.66); state->plane = vector_apply(state->plane, &fabs); } - -/* -** -1 0 1 <-- camera_x -** v v v -** ################ -** # | # <-- screen -** # | # -** ################ -** -** camera_x is the x column from the camera percpective -** scaling the plane vector and adding it to the direction vector -** to create a vector in the *direction* of the column x. -*/ - -t_vector get_ray(t_state *state, int x) -{ - double camera_x; - - camera_x = 2 * x / (double)state->window.width - 1; - return (vector_add(state->dir, vector_scale(state->plane, camera_x))); -} - -/* -** delta between each grid unit form the vector percpective -** -** if we have a vector v = [2 3]: -** dx = |v| / v_1 -** = sqrt(v_1^2 + v_2^2) / v_1 -** = (v_1^2 + v_2^2) / v_1^2 -** = 1 + v_2^2 / v_1^2 -** Same thing for dy -** dy = |v| / v_2 -** = sqrt(v_1^2 + v_2^2) / v_1 -** = (v_1^2 + v_2^2) / v_2^2 -** = v_1^2 / v_2^2 + 1 -** -** This can be simplified (for some obscure reason): -** dx = |1 / v_1| -** dy = |1 / v_2| -*/ - -t_vector get_delta(t_vector ray) -{ - t_vector delta; - - delta.x = vector_norm(ray) / ray.x; - delta.y = vector_norm(ray) / ray.y; - return (delta); -} - -/* -** first delta between player position and first grid unit -** -** current x and y are the perpendicular distance to the nearest wall, -** we multiply them by their corresponding delta. -** 0 <= perpendicular distance <= 1 is a ratio, how much of the full delta we need to take. -** -** if (ray.x < 0) -** current.x = state->pos.x - map_pos.x; -** else -** current.x = fabs(state->pos.x - map_pos.x + 1.0); -** if (ray.y < 0) -** current.y = state->pos.y - map_pos.y; -** else -** current.y = fabs(state->pos.y - map_pos.y + 1.0); -** current.x *= delta.x; -** current.y *= delta.y; -*/ - -t_vector get_init_delta(t_state *state, t_vector *ray, t_vector *map_pos, t_vector *delta) -{ - t_vector current; - - current = vector_apply(&fabs, VECTOR_SUB(state->pos, *map_pos)); - if (ray.x > 0) - current.x += 1.0; - if (ray.y > 0) - current.y += 1.0; - current.x *= delta.x; - current.y *= delta.y; - return (current); -} - -/* -** perpendicular distance between the wall hit and the camera plane. -** We don't use euclidean distance because it would cause a fisheye effect. -** -** ====================X========== wall -** | /| -** | <------ / | -----+ -** | / | | -** plane | / | <- perpendicular distance -** | | / | -** v | / | -** <-------^----/----------------- camera plane -** | / -** dir -> | / -** | / <- euclidean distance -** |/ -** x <- pos -** -** In this case the perpendicular distance (p) is the difference -** of the y-coord of the hit point and the y-coord of the pos + dir vector. -** We use the y component because we hit the wall from a south/north percepective, -** if we had hit it form west/east, we would use the x component instead. -*/ - -double get_perp_dist(t_state *state, t_vector *hit_point, t_side side) -{ - if (side == SIDE_NS) - return hit_point->y - state->pos.y + state->dir.y); - else if (side == SIDE_NS) - return hit_point->x - state->pos.x + state->dir.x); -} - -/* -** 0 <= 1 / perp_dist <= 1 -** height * (1 / perp_dist) is how much of the screen height do we take -*/ - -int get_line_height(t_state *state, double prep_dist, t_side side) -{ - return ((int)((double)state->window.height / perp_wall_dist)); -} - -void helper_ray_next(t_vector *current, t_vector *map_pos, - t_vector delta, t_vector map_step) -{ - if (current->x < current->y) - { - current->x += delta.x; - map_pos->x += map_step.x; - } - else - { - current->y += delta.y; - map_pos->y += map_step.y; - } -} - -t_image *get_tex(t_state *state, t_side side) -{ - if (side == SIDE_NS) - { - if (hit_point->y < state->pos.y) - return (state->textures[TEX_NORTH]); - else - return (state->textures[TEX_SOUTH]); - } - else if (side == SIDE_WE) - { - if (hit_point->x < state->pos.x) - return (state->textures[TEX_WEST]); - else - return (state->textures[TEX_EAST]); - } - return (NULL); -} - -/* -** Since we're drawing each column, all the texels we want to draw on the window -** are on a single column of the texture. -** First we find the x-coord relative to the wall we hit -*/ - -int get_tex_x() -{ - //calculate value of wall_x - double wall_x; //where exactly the wall was hit - if (side == 0) wall_x = state->pos.y + perp_dist * ray.y; - else wall_x = state->pos.x + perp_dist * ray.x; - wall_x -= floor(wall_x); - //x coordinate on the texture - int tex_x = (int)(wall_x * (double)texWidth); - if(side == 0 && ray.x > 0) tex_x = texture_width - tex_x - 1; - if(side == 1 && ray.y < 0) tex_x = texture_width - tex_x - 1; - return (tex_x); -} diff --git a/libft b/libft -Subproject 7fbd92d957e5d30d3478b94ec0abd07aacc054b +Subproject fbd1d450b0c2da394cbb02fd61ab75b2719bfb7 @@ -6,13 +6,12 @@ /* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/11/15 06:39:39 by cacharle #+# #+# */ -/* Updated: 2020/01/11 13:27:19 by cacharle ### ########.fr */ +/* Updated: 2020/01/15 15:08:45 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ #include "cub3d.h" - int main(int argc, char **argv) { t_state *state; @@ -6,7 +6,7 @@ /* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/01/11 13:37:17 by cacharle #+# #+# */ -/* Updated: 2020/01/12 15:45:03 by cacharle ### ########.fr */ +/* Updated: 2020/01/15 15:09:32 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -40,65 +40,65 @@ void render_update_window(t_state *state) void render_column(t_state *state, int x) { - t_vector ray; - t_vector map_pos; - t_vector delta; - t_side side; - int line_height; + t_render_state rstate; - ray = get_ray(state, x); - map_pos = vector_new((double)((int)state->pos.x), (double)((int)state->pos.y)); - delta = get_delta(ray); - current = get_init_delta(state, ray, map_pos, delta); - map_step = vector_new(ray.x < 0.0 ? -1.0 : 1.0, ray.y < 0.0 ? -1.0 : 1.0)); + rstate.x = x; + rstate_ray(state, &rstate); + vector_new((double)((int)state->pos.x), (double)((int)state->pos.y)); + rstate_delta(&rstate); + rstate_init_probe(state, &rstate); + vector_new(rstate.ray.x < 0.0 ? -1.0 : 1.0, rstate.ray.y < 0.0 ? -1.0 : 1.0); while (TRUE) { - side = current.x < current.y ? SIDE_WE : SIDE_WE; - helper_ray_next(¤t, map_pos, delta, map_step); - if (state->map[(int)map_pos.y][(int)map_pos.x] == CELL_WALL) - break; + rstate.side = rstate.probe.x < rstate.probe.y ? SIDE_WE : SIDE_WE; + rstate_next_probe(&rstate); + if (state->map[(int)rstate.map_pos.y][(int)rstate.map_pos.x] == CELL_WALL) + break ; } - line_height = get_line_height(state, get_perp_dist(state, ¤t, side), side); - render_window_column(state, x, side, WINDOW_MID_HEIGHT(state) - line_height / 2, - WINDOW_MID_HEIGHT(state) + line_height / 2); + rstate_line_height(state, &rstate); + render_window_column(state, &rstate); + // WINDOW_MID_HEIGHT(state) - line_height / 2 + // WINDOW_MID_HEIGHT(state) + line_height / 2 } -void render_window_column(t_state *state, int x, t_side side, int start, int end) +void render_window_column(t_state *state, t_render_state *rstate) { int i; t_color white; white.hexcode = 0x00ffffff; i = -1; - while (++i < draw_start) - ((t_color*)state->window.data)[i * state->window.width + x] = state->ceilling_color; - i = render_texture(state, side, start, end); - while (++i < state->window_height) - ((t_color*)state->window.data)[i * state->window.width + x] = state->floor_color; + /* while (++i < draw_start) */ + /* ((t_color*)state->window.data)[i * state->window.width + rstate->x] = */ + /* state->ceilling_color; */ + /* i = render_texture(state, rstate); */ + /* while (++i < state->window_height) */ + /* ((t_color*)state->window.data)[i * state->window.width + rstate->x] = */ + /* state->floor_color; */ } -int render_texture(t_state *state, t_side side, int start, int end) -{ - int i; - int tex_x; - double step; - double tex_pos; - int tex_y; - t_image *texture; - - texture = get_tex(state, side); - tex_x = get_tex_x(); - - step = 1.0 * texture->height / line_height; - texPos = (start - state->window.height / 2 + line_height / 2) * step; - - i = start - 1; - while (++i < end) - { - tex_y = (int)tex_pos & (texture->height - 1); - tex_pos += step; - ((t_color*)state->window.data)[i * state->window.width + x] = - texture[texHeight * texY + texX]; - } - return (end); -} +/* int render_texture(t_state *state, t_render_state *rstate)) */ +/* { */ + /* int i; */ + /* int tex_x; */ + /* double step; */ + /* double tex_pos; */ + /* int tex_y; */ + /* t_image *texture; */ + /* */ + /* texture = get_tex(state, side); */ + /* tex_x = get_tex_x(); */ + /* */ + /* step = 1.0 * texture->height / line_height; */ + /* texPos = (start - state->window.height / 2 + line_height / 2) * step; */ + /* */ + /* i = start - 1; */ + /* while (++i < end) */ + /* { */ + /* tex_y = (int)tex_pos & (texture->height - 1); */ + /* tex_pos += step; */ + /* ((t_color*)state->window.data)[i * state->window.width + x] = */ + /* texture[texHeight * texY + texX]; */ + /* } */ + /* return (end); */ +/* } */ diff --git a/render_state.c b/render_state.c new file mode 100644 index 0000000..a539016 --- /dev/null +++ b/render_state.c @@ -0,0 +1,187 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* render_state.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/01/15 14:40:14 by cacharle #+# #+# */ +/* Updated: 2020/01/15 15:06:39 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "cub3d.h" + +/* +** -1 0 1 <-- camera_x +** v v v +** ################ +** # | # <-- screen +** # | # +** ################ +** +** camera_x is the x column from the camera percpective +** scaling the plane vector and adding it to the direction vector +** to create a vector in the *direction* of the column x. +*/ + +void rstate_ray(t_state *state, t_render_state *rstate) +{ + double camera_x; + + camera_x = 2 * rstate->x / (double)state->window.width - 1; + rstate->ray = vector_add(state->dir, vector_scale(state->plane, camera_x)); +} + +/* +** delta between each grid unit form the vector percpective +** +** if we have a vector v = [2 3]: +** dx = |v| / v_1 +** = sqrt(v_1^2 + v_2^2) / v_1 +** = (v_1^2 + v_2^2) / v_1^2 +** = 1 + v_2^2 / v_1^2 +** Same thing for dy +** dy = |v| / v_2 +** = sqrt(v_1^2 + v_2^2) / v_1 +** = (v_1^2 + v_2^2) / v_2^2 +** = v_1^2 / v_2^2 + 1 +** +** This can be simplified (for some obscure reason): +** dx = |1 / v_1| +** dy = |1 / v_2| +*/ + +void rstate_delta(t_render_state *rstate) +{ + rstate->delta.x = vector_norm(rstate->ray) / rstate->ray.x; + rstate->delta.y = vector_norm(rstate->ray) / rstate->ray.y; +} + +/* +** first delta between player position and first grid unit +** +** current x and y are the perpendicular distance to the nearest wall, +** we multiply them by their corresponding delta. +** 0 <= perpendicular distance <= 1 is a ratio, how much of the full delta we need to take. +** +** if (ray.x < 0) +** current.x = state->pos.x - map_pos.x; +** else +** current.x = fabs(state->pos.x - map_pos.x + 1.0); +** if (ray.y < 0) +** current.y = state->pos.y - map_pos.y; +** else +** current.y = fabs(state->pos.y - map_pos.y + 1.0); +** current.x *= delta.x; +** current.y *= delta.y; +*/ + +void rstate_init_probe(t_state *state, t_render_state *rstate) +{ + rstate->probe = vector_apply(VECTOR_SUB(state->pos, rstate->map_pos), &fabs); + if (rstate->ray.x > 0) + rstate->probe.x += 1.0; + if (rstate->ray.y > 0) + rstate->probe.y += 1.0; + rstate->probe.x *= rstate->delta.x; + rstate->probe.y *= rstate->delta.y; +} + +/* +** perpendicular distance between the wall hit and the camera plane. +** We don't use euclidean distance because it would cause a fisheye effect. +** +** ====================X========== wall +** | /| +** | <------ / | -----+ +** | / | | +** plane | / | <- perpendicular distance +** | | / | +** v | / | +** <-------^----/----------------- camera plane +** | / +** dir -> | / +** | / <- euclidean distance +** |/ +** x <- pos +** +** In this case the perpendicular distance (p) is the difference +** of the y-coord of the hit point and the y-coord of the pos + dir vector. +** We use the y component because we hit the wall +** from a south/north percepective, +** if we had hit it form west/east, we would use the x component instead. +*/ + +double rstate_perp_dist(t_state *state, t_render_state *rstate) +{ + if (rstate->side == SIDE_NS) + return (rstate->probe.y - state->pos.y + state->dir.y); + else if (rstate->side == SIDE_NS) + return (rstate->probe.x - state->pos.x + state->dir.x); + return (0.0); +} + +/* +** 0 <= 1 / perp_dist <= 1 +** height * (1 / perp_dist) is how much of the screen height do we take +*/ + +void rstate_line_height(t_state *state, t_render_state *rstate) +{ + rstate->line_height = + (int)((double)state->window.height / rstate_perp_dist(state, rstate)); +} + +void rstate_next_probe(t_render_state *rstate) +{ + if (rstate->probe.x < rstate->probe.y) + { + rstate->probe.x += rstate->delta.x; + rstate->map_pos.x += rstate->map_step.x; + } + else + { + rstate->probe.y += rstate->delta.y; + rstate->map_pos.y += rstate->map_step.y; + } +} + +t_image *get_tex(t_state *state, t_render_state *rstate) +{ + if (rstate->side == SIDE_NS) + { + if (rstate->probe.y < state->pos.y) + return (state->textures + TEX_NORTH); + else + return (state->textures + TEX_SOUTH); + } + else if (rstate->side == SIDE_WE) + { + if (rstate->probe.x < state->pos.x) + return (state->textures + TEX_WEST); + else + return (state->textures + TEX_EAST); + } + return (NULL); +} + +/* +** Since we're drawing each column, all the texels we want to draw on the window +** are on a single column of the texture. +** First we find the x-coord relative to the wall we hit +*/ + +/* int get_tex_x() */ +/* { */ +/* //calculate value of wall_x */ +/* double wall_x; //where exactly the wall was hit */ +/* if (side == 0) wall_x = state->pos.y + perp_dist * ray.y; */ +/* else wall_x = state->pos.x + perp_dist * ray.x; */ +/* wall_x -= floor(wall_x); */ +/* //x coordinate on the texture */ +/* int tex_x = (int)(wall_x * (double)texWidth); */ +/* if(side == 0 && ray.x > 0) tex_x = texture_width - tex_x - 1; */ +/* if(side == 1 && ray.y < 0) tex_x = texture_width - tex_x - 1; */ +/* return (tex_x); */ +/* } */ @@ -6,7 +6,7 @@ /* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/11/19 16:39:57 by cacharle #+# #+# */ -/* Updated: 2020/01/12 10:37:38 by cacharle ### ########.fr */ +/* Updated: 2020/01/15 15:13:06 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -45,7 +45,6 @@ t_state *state_new(t_state *state) /* printf("%x\n", state->floor_color.rgb.g); */ /* printf("%x\n", state->floor_color.rgb.b); */ /* printf("endian %d", state->window.endian); */ - /* return NULL; */ return (state); } @@ -6,16 +6,12 @@ /* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/11/18 01:28:01 by cacharle #+# #+# */ -/* Updated: 2020/01/12 14:39:34 by cacharle ### ########.fr */ +/* Updated: 2020/01/15 15:09:08 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ #include "cub3d.h" -#define VECTOR_MINUS(v) vector_scale(v, -1.0) -#define VECTOR_SUB(v, w) vector_add(v, VECTOR_MINUS(w)) -#define VECTOR_ADD_CONST(v, c) vector_add(v, vector_new(c, c)) - t_vector vector_add(t_vector a, t_vector b) { a.x += b.x; @@ -51,7 +47,7 @@ double vector_norm(t_vector v) t_vector vector_new(double x, double y) { t_vector v; - + v.x = x; v.y = y; return (v); |
