aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helper.c128
m---------libft0
-rw-r--r--render.c39
3 files changed, 126 insertions, 41 deletions
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);
+}
diff --git a/libft b/libft
-Subproject d0c146c2274198814e106b17ea1f9461a1b0b81
+Subproject 7fbd92d957e5d30d3478b94ec0abd07aacc054b
diff --git a/render.c b/render.c
index 1ee0bc2..77eb3b9 100644
--- a/render.c
+++ b/render.c
@@ -50,7 +50,7 @@ void render_column(t_state *state, int 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 = get_map_step(&ray);
+ map_step = vector_new(ray.x < 0.0 ? -1.0 : 1.0, ray.y < 0.0 ? -1.0 : 1.0));
while (TRUE)
{
side = current.x < current.y ? SIDE_WE : SIDE_WE;
@@ -58,12 +58,12 @@ void render_column(t_state *state, int x)
if (state->map[(int)map_pos.y][(int)map_pos.x] == CELL_WALL)
break;
}
- line_height = get_line_height(state, get_perp_dist(), side);
- render_window_column(state, x, WINDOW_MID_HEIGHT(state) - line_height / 2,
- WINDOW_MID_HEIGHT(state) + line_height / 2);
+ line_height = get_line_height(state, get_perp_dist(state, &current, side), side);
+ render_window_column(state, x, side, WINDOW_MID_HEIGHT(state) - line_height / 2,
+ WINDOW_MID_HEIGHT(state) + line_height / 2);
}
-void render_window_column(t_state *state, int x, int start, int end)
+void render_window_column(t_state *state, int x, t_side side, int start, int end)
{
int i;
t_color white;
@@ -72,8 +72,33 @@ void render_window_column(t_state *state, int x, int start, int end)
i = -1;
while (++i < draw_start)
((t_color*)state->window.data)[i * state->window.width + x] = state->ceilling_color;
- while (++i < draw_end)
- ((t_color*)state->window.data)[i * state->window.width + x] = white;
+ 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;
}
+
+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);
+}