aboutsummaryrefslogtreecommitdiff
path: root/src/render_sprite.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/render_sprite.c')
-rw-r--r--src/render_sprite.c94
1 files changed, 64 insertions, 30 deletions
diff --git a/src/render_sprite.c b/src/render_sprite.c
index 379f67a..2ca34c0 100644
--- a/src/render_sprite.c
+++ b/src/render_sprite.c
@@ -6,47 +6,80 @@
/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2020/02/02 17:39:07 by cacharle #+# #+# */
-/* Updated: 2020/02/04 03:38:53 by cacharle ### ########.fr */
+/* Updated: 2020/02/04 23:25:21 by cacharle ### ########.fr */
/* */
/* ************************************************************************** */
#include "cub3d.h"
+/*
+** 1: While raycasting the walls, store the perpendicular distance
+** of each vertical stripe in a 1D ZBuffer
+** 2: Calculate the distance of each sprite to the player
+** 3: Use this distance to sort the sprites, from furthest away
+** to closest to the camera
+** 4: Project the sprite on the camera plane (in 2D):
+** subtract the player position from the sprite position,
+** then multiply the result with the inverse of the 2x2 camera matrix
+** 5: Calculate the size of the sprite on the screen
+** (both in x and y direction) by using the perpendicular distance
+** 6: Draw the sprites vertical stripe by vertical stripe,
+** don't draw the vertical stripe if the distance is further away
+** than the 1D ZBuffer of the walls of the current stripe
+** 7: Draw the vertical stripe pixel by pixel, make sure there's
+** an invisible color or all sprites would be rectangles
+*/
+
+static void draw_stripe_pixels(t_state *state, t_sprite_state *sstate,
+ int stripe, int tex_x)
+{
+ int y;
+ int d;
+ int tex_y;
+ t_color color;
+
+ y = sstate->draw_start - 1;
+ while (++y < sstate->draw_end_y)
+ {
+ d = y * 256 - state->window.height * 128 + sstate->sprite_height * 128;
+ tex_y = (d * state->textures[TEX_SPRITE].height)
+ / (sstate->sprite_height * 256);
+ color = ((t_color*)state->textures[TEX_SPRITE].data)
+ [state->textures[TEX_SPRITE].width * tex_y + tex_x];
+ if ((color.hexcode & 0x00FFFFFF) != 0)
+ ((t_color*)state->window.data)[y * state->window.width + stripe] =
+ color;
+ }
+}
+
static void draw_stripe(t_state *state, t_sprite_state *sstate, int stripe)
{
int tex_width;
int tex_height;
int tex_x;
- int y;
tex_width = state->textures[TEX_SPRITE].width;
tex_height = state->textures[TEX_SPRITE].height;
- tex_x = (int)(256 * (stripe - (-sstate->sprite_width / 2 + sstate->sprite_window_x))
- * tex_width / sstate->sprite_width) / 256;
- if (!(sstate->transform.y > 0 && stripe > 0 && stripe < state->window.width && sstate->transform.y < state->z_buffer[stripe]))
+ tex_x = (int)(256 * (stripe - (-sstate->sprite_width / 2
+ + sstate->sprite_window_x))
+ * tex_width / sstate->sprite_width) / 256;
+ if (!(sstate->transform.y > 0 && stripe > 0 && stripe < state->window.width
+ && sstate->transform.y < state->z_buffer[stripe]))
return ;
- y = sstate->draw_start - 1;
- while (++y < sstate->draw_end_y)
- {
- int d = y * 256 - state->window.height * 128 + sstate->sprite_height * 128;
- int tex_y = ((d * tex_height) / sstate->sprite_height) / 256;
- t_color color = ((t_color*)state->textures[TEX_SPRITE].data)[tex_width * tex_y + tex_x];
- if ((color.hexcode & 0x00FFFFFF) != 0)
- ((t_color*)state->window.data)[y * state->window.width + stripe] = color;
- }
+ draw_stripe_pixels(state, sstate, stripe, tex_x);
}
-static void sprite_boundary(t_state *state, t_sprite_state *sstate)
+static void sprite_boundary(t_state *state, t_sprite_state *sstate)
{
sstate->sprite_height = ft_abs((int)(state->window.height
/ (sstate->transform.y)));
sstate->draw_start = -sstate->sprite_height / 2 + state->window.height / 2;
- if(sstate->draw_start < 0)
+ if (sstate->draw_start < 0)
sstate->draw_start = 0;
sstate->draw_end_y = sstate->sprite_height / 2 + state->window.height / 2;
- if(sstate->draw_end_y >= state->window.height)
+ if (sstate->draw_end_y >= state->window.height)
sstate->draw_end_y = state->window.height - 1;
- sstate->sprite_width = ft_abs( (int) (state->window.height
+ sstate->sprite_width = ft_abs((int)(state->window.height
/ (sstate->transform.y)));
sstate->draw_start_x = -sstate->sprite_width / 2 + sstate->sprite_window_x;
if (sstate->draw_start_x < 0)
@@ -56,28 +89,29 @@ static void sprite_boundary(t_state *state, t_sprite_state *sstate)
sstate->draw_end_x = state->window.width - 1;
}
-static void render_sprite(t_state *state, int i)
+static void render_sprite(t_state *state, int i)
{
int stripe;
t_sprite_state sstate;
+ double inverse_det;
+ t_vector sprite;
- sstate.sprite.x = state->sprites[i].pos.x - state->pos.x;
- sstate.sprite.y = state->sprites[i].pos.y - state->pos.y;
- sstate.inverse_det = 1.0 / (state->plane.x
- * state->dir.y - state->dir.x * state->plane.y);
- sstate.transform.x = sstate.inverse_det
- * (state->dir.y * sstate.sprite.x - state->dir.x * sstate.sprite.y);
- sstate.transform.y = sstate.inverse_det * (-state->plane.y
- * sstate.sprite.x + state->plane.x * sstate.sprite.y);
- sstate.sprite_window_x = (int)((state->window.width / 2)
- * (1 + sstate.transform.x / sstate.transform.y));
+ sprite = vector_add(state->sprites[i].pos, vector_scale(state->pos, -1.0));
+ inverse_det = 1.0 / (state->plane.x * state->dir.y
+ - state->dir.x * state->plane.y);
+ sstate.transform.x = state->dir.y * sprite.x - state->dir.x * sprite.y;
+ sstate.transform.y =
+ -state->plane.y * sprite.x + state->plane.x * sprite.y;
+ sstate.transform = vector_scale(sstate.transform, inverse_det);
+ sstate.sprite_window_x = (int)((state->window.width / 2.0)
+ * (1.0 + sstate.transform.x / sstate.transform.y));
sprite_boundary(state, &sstate);
stripe = sstate.draw_start_x - 1;
while (++stripe < sstate.draw_end_x)
draw_stripe(state, &sstate, stripe);
}
-void render_update_sprite(t_state *state)
+void render_update_sprite(t_state *state)
{
int i;