/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* fdf_drawing.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: narnaud +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* 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); }