aboutsummaryrefslogtreecommitdiff
path: root/src/render_sprite.c
blob: 0570a710ad5c4ad84f0d66d2e21a9f62452ab2c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   render_sprite.c                                    :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: cacharle <marvin@42.fr>                    +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2020/02/02 17:39:07 by cacharle          #+#    #+#             */
/*   Updated: 2020/02/02 23:52:29 by cacharle         ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "cub3d.h"

int		sprite_compar(const void *a, const void *b)
{
	const t_sprite	*sprite_a;
	const t_sprite	*sprite_b;

	sprite_a = a;
	sprite_b = b;
	if (sprite_a->dist > sprite_b->dist)
		return -1;
	if (sprite_a->dist < sprite_b->dist)
		return 1;
	return 0;
}

void	sprites_dist(t_state *state)
{
	int	i;

	i = -1;
	while (++i < state->sprites_num)
		state->sprites[i].dist = vector_norm(vector_sub(state->sprites[i].pos, state->pos));
}

void	render_update_sprite(t_state *state)
{
	sprites_dist(state);
	ft_qsort(state->sprites, state->sprites_num, sizeof(t_sprite), sprite_compar);
	for(int i = 0; i < state->sprites_num; i++)
	{
		double sprite_x = state->sprites[i].pos.x - state->pos.x;
		double sprite_y = state->sprites[i].pos.y - state->pos.y;

		double inverse_det = 1.0 / (state->plane.x * state->dir.y - state->dir.x * state->plane.y);
		double transform_x = inverse_det * (state->dir.y * sprite_x - state->dir.x * sprite_y);
		double transform_y = inverse_det * (-state->plane.y * sprite_x + state->plane.x * sprite_y);
		int sprite_window_x = (int)((state->window.width / 2) * (1 + transform_x / transform_y));

		int sprite_height = abs((int)(state->window.height / (transform_y)));
		int draw_start = -sprite_height / 2 + state->window.height / 2;
		if(draw_start < 0)
		   	draw_start = 0;
		int draw_end_y = sprite_height / 2 + state->window.height / 2;
		if(draw_end_y >= state->window.height)
		   	draw_end_y = state->window.height - 1;

		int sprite_width = abs( (int) (state->window.height / (transform_y)));
		int draw_start_x = -sprite_width / 2 + sprite_window_x;
		if (draw_start_x < 0)
			draw_start_x = 0;
		int draw_end_x = sprite_width / 2 + sprite_window_x;
		if (draw_end_x >= state->window.width)
			draw_end_x = state->window.width - 1;

		for(int stripe = draw_start_x; stripe < draw_end_x; stripe++)
		{
			int tex_width = state->textures[TEX_SPRITE].width;
			int tex_height = state->textures[TEX_SPRITE].height;
			int tex_x = (int)(256 * (stripe - (-sprite_width / 2 + sprite_window_x)) * tex_width / sprite_width) / 256;
			if(transform_y > 0 && stripe > 0 && stripe < state->window.width && transform_y < state->z_buffer[stripe])
				for(int y = draw_start; y < draw_end_y; y++)
				{
					int d = y * 256 - state->window.height * 128 + sprite_height * 128; 
					int tex_y = ((d * tex_height) / sprite_height) / 256;
					t_color color = ((t_color*)state->textures[TEX_SPRITE].data)[tex_width * tex_y + tex_x];
					if ((color.hexcode & 0x00FFFFFF) != 0) // if not empty pixel
						((t_color*)state->window.data)[y * state->window.width + stripe] = color;
				}
		}
	}
}