From 58261e54bfd281273a67c4c8e06ffc5164ad8ba1 Mon Sep 17 00:00:00 2001 From: Charles Date: Tue, 14 Jan 2020 14:02:53 +0100 Subject: WIP: render texture, raycasting algorithm doc --- helper.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 34 deletions(-) (limited to 'helper.c') diff --git a/helper.c b/helper.c index 1499687..ddf1349 100644 --- a/helper.c +++ b/helper.c @@ -59,7 +59,7 @@ void helper_init_dir_plane(t_state *state, int y, int x) ** # | # <-- 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. @@ -76,23 +76,38 @@ t_vector get_ray(t_state *state, int x) /* ** delta between each grid unit form the vector percpective ** -** This can be simplified like (for some obscure reason): -** delta.x = fabs(1.0 / ray.x); -** delta.y = fabs(1.0 / ray.y); +** 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 = sqrt(1.0 + (SQUARE(ray.y) / SQUARE(ray.x))); - delta.y = sqrt(1.0 + (SQUARE(ray.x) / SQUARE(ray.y))); + 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 @@ -101,11 +116,6 @@ t_vector get_delta(t_vector ray) ** current.y = state->pos.y - map_pos.y; ** else ** current.y = fabs(state->pos.y - map_pos.y + 1.0); -** -** 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. -** ** current.x *= delta.x; ** current.y *= delta.y; */ @@ -124,35 +134,46 @@ t_vector get_init_delta(t_state *state, t_vector *ray, t_vector *map_pos, t_vect return (current); } -t_vector get_map_step(t_vector *ray) -{ - return (vector_new(ray.x < 0 ? -1 : 1, - ray.y < 0 ? -1 : 1)); -} +/* +** 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. +*/ -t_vector get_perp_dist(t_state *state, t_vector *ray, t_vector *map_pos) +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); } -int get_line_height(t_state *state, int prep_dist, t_side side) -{ - int line_height; - - if (perp_wall_dist <= 0) - line_height = state->window_height; - else - line_height = (int)(state->window.height / perp_wall_dist); - return (line_height); -} +/* +** 0 <= 1 / perp_dist <= 1 +** height * (1 / perp_dist) is how much of the screen height do we take +*/ -int get_perp_wall_dist(t_state *state, t_vector *map_pos, - t_vector *ray, int map_step_x, int map_step_y) +int get_line_height(t_state *state, double prep_dist, t_side side) { - if (side == SIDE_WEST_EAST) - perp_wall_dist = ((double)map_x - state->pos.x + (map_step_x == -1 ? 1 : 0)) / ray.x; - else if (side == SIDE_NORTH_SOUTH) - perp_wall_dist = ((double)map_y - state->pos.y + (map_step_y == -1 ? 1 : 0)) / ray.y; + return ((int)((double)state->window.height / perp_wall_dist)); } void helper_ray_next(t_vector *current, t_vector *map_pos, @@ -169,3 +190,42 @@ void helper_ray_next(t_vector *current, t_vector *map_pos, 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); +} -- cgit