Projet de 42 : Fil de fer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
5.0 KiB

3 years ago
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* fdf_drawing.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: narnaud <narnaud@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/05 14:44:08 by narnaud #+# #+# */
/* Updated: 2022/02/24 13:45:03 by narnaud ### ########.fr */
/* */
/* ************************************************************************** */
#include "fdf.h"
/* Function : get_color
* --------------------
* return color as decimal value depending of altitude.
* point with an altitude of zero are green,
* points with negativ altitude tend to the blue
* points with positiv altitude tend to the red.
*
* db : map datas,
* x, y : points coordinates,
* coef : the position of the point through the line,
* negativ for vertical lines,
* positiv for horizontal lines,
*
* return : integer which give the color of the point formated as :
* Red * 256^2 + Green * 256 + Blue
* Red, Green and Blue beeing between 0 and 255.
*/
int get_color(t_datas *db, t_2di coord, float coef)
{
int z0;
float dz;
int height;
int color_coef;
if (coord.x > 0 && coef <= 0)
{
z0 = db->map->altitude[coord.y][coord.x - 1];
dz = (float)db->map->altitude[coord.y][coord.x] - (float)z0;
height = z0 - (int)round(coef * dz);
color_coef = (height * 254) / db->map->hightest + 1;
}
else
{
z0 = db->map->altitude[coord.y - 1][coord.x];
dz = (float)db->map->altitude[coord.y][coord.x] - (float)z0;
height = z0 + (int)round(coef * dz);
color_coef = (height * 254) / db->map->hightest + 1;
}
if (height >= 0)
return (256 * 255 + color_coef * 256 * 255);
else
return (256 * 255 - color_coef);
}
/* Function : draw_line
* --------------------
* datas :
* start :
* end :
* buffer :
*
* return :
*
*/
void draw_horiz_line(t_datas *datas, t_2di coord, int *buffer)
{
size_t i;
t_2df dp;
t_2df pos;
size_t len;
i = 0;
pos.x = (float)datas->cam->render[coord.y][coord.x - 1].x;
pos.y = (float)datas->cam->render[coord.y][coord.x - 1].y;
dp.x = (float)datas->cam->render[coord.y][coord.x].x - pos.x;
dp.y = (float)datas->cam->render[coord.y][coord.x].y - pos.y;
len = sqrt(dp.x * dp.x + dp.y * dp.y);
dp.x /= len;
dp.y /= len;
while (i < len)
{
pos.x += dp.x;
pos.y += dp.y;
if (pos.x >= 0 && pos.y >= 0 && \
pos.x < WIN_X_SZ && pos.y < WIN_Y_SZ)
buffer[datas->line_bytes * (int)floor(pos.y) + (int)floor(pos.x)] \
= get_color(datas, coord, -(float)i / (float)len);
i++;
}
}
void draw_vert_line(t_datas *datas, t_2di coord, int *buffer)
{
size_t i;
t_2df dp;
t_2df pos;
size_t len;
i = 0;
pos.x = (float)datas->cam->render[coord.y - 1][coord.x].x;
pos.y = (float)datas->cam->render[coord.y - 1][coord.x].y;
dp.x = (float)datas->cam->render[coord.y][coord.x].x - pos.x;
dp.y = (float)datas->cam->render[coord.y][coord.x].y - pos.y;
len = sqrt(dp.x * dp.x + dp.y * dp.y);
dp.x /= len;
dp.y /= len;
while (i < len)
{
pos.x += dp.x;
pos.y += dp.y;
if (pos.x >= 0 && pos.y >= 0 && \
pos.x < WIN_X_SZ && pos.y < WIN_Y_SZ)
buffer[datas->line_bytes * (int)floor(pos.y) + (int)floor(pos.x)] \
= get_color(datas, coord, (float)i / (float)len);
i++;
}
}
void get_coords(t_2di coord, t_datas *datas)
{
t_2df vars;
t_3d pt;
pt.x = coord.x - datas->map->width / 2;
pt.y = coord.y - datas->map->depth / 2;
pt.z = datas->map->altitude[coord.y][coord.x] * datas->map->z_mult;
pt.yaw.cos = datas->cam->ang.yaw.cos;
pt.yaw.sin = datas->cam->ang.yaw.sin;
pt.pitch.cos = datas->cam->ang.pitch.cos;
pt.pitch.sin = datas->cam->ang.pitch.sin;
vars.x = pt.yaw.cos * pt.x + pt.yaw.sin * pt.y;
vars.y = pt.pitch.sin * (pt.yaw.sin * pt.x - pt.yaw.cos * pt.y) - \
pt.pitch.cos * pt.z;
datas->cam->render[coord.y][coord.x].x = datas->cam->center.x + \
round(datas->cam->zoom * vars.x);
datas->cam->render[coord.y][coord.x].y = datas->cam->center.y + \
round(datas->cam->zoom * vars.y);
}
void draw_map(t_datas *datas)
{
t_2di coord;
int *buffer;
datas->img = mlx_new_image(datas->mlx, WIN_X_SZ, WIN_Y_SZ);
buffer = (int *)mlx_get_data_addr(datas->img, \
&datas->pixel_bits, &datas->line_bytes, &datas->endian);
datas->line_bytes /= 4;
coord.y = 0;
while (coord.y < datas->map->depth)
{
coord.x = 0;
while (coord.x < datas->map->width)
{
get_coords(coord, datas);
if (coord.x > 0)
draw_horiz_line(datas, coord, buffer);
if (coord.y > 0)
draw_vert_line(datas, coord, buffer);
coord.x++;
}
coord.y++;
}
mlx_put_image_to_window(datas->mlx, datas->win, datas->img, 0, 0);
draw_infos(datas);
mlx_destroy_image(datas->mlx, datas->img);
}