/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* bump.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: vvobis +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/11/05 14:45:43 by vvobis #+# #+# */ /* Updated: 2024/12/17 13:36:39 by vvobis ### ########.fr */ /* */ /* ************************************************************************** */ #include "../../minirt.h" #define BUMP_BUFFER_SIZE 10000 static void bump_map_create(t_bump_map *map, t_buffer *buffer, int fd) { uint buffer_ptr; buffer_ptr = 0; while (buffer->empty == false) { while (buffer->empty == false) { map->map[buffer_ptr++] = ft_atoi(&buffer->bytes[buffer->start]); buffer_move_next_whitespace(buffer); } buffer_read(buffer, fd); if (contains_nan(buffer->bytes, buffer->end) \ || buffer_ptr - 1 > map->width * map->height) return (ft_fprintf(2, "Invalid Bump Map Format\n"), \ close(fd), lst_memory(NULL, NULL, FAIL)); buffer_allignment_set(buffer); } if (map->width * map->height != buffer_ptr) { close(fd); ft_fprintf(STDERR_FILENO, \ "Invalid Bump Map format for %s\n", map->path); lst_memory(NULL, NULL, FAIL); } } void bump_map_read(char *map_path, t_bump_map *map) { int fd; t_buffer buffer; char stack_buffer[BUMP_BUFFER_SIZE]; if (map->map) lst_memory(map->map, NULL, FREE); ft_bzero(map, sizeof(*map)); ft_open(&fd, map_path, O_RDONLY, 0644); ft_memcpy(map->path, map_path, ft_strlen(map_path)); ft_bzero(stack_buffer, sizeof(stack_buffer)); buffer = buffer_init(BUMP_BUFFER_SIZE, stack_buffer); buffer_read(&buffer, fd); if (contains_nan(buffer.bytes, buffer.end)) { ft_fprintf(2, "Invalid Bump Map Format\n"); return (close(fd), lst_memory(NULL, NULL, FAIL)); } map->width = ft_atoi(&buffer.bytes[buffer.start]); buffer_move_next_whitespace(&buffer); map->height = ft_atoi(&buffer.bytes[buffer.start]); buffer_move_next_whitespace(&buffer); map->map = ft_calloc(map->width * map->height, sizeof(double)); lst_memory(map->map, free, ADD); bump_map_create(map, &buffer, fd); ft_close(fd); } double bilinear_sample(double u, double v, t_bump_map *map) { int x2; int y2; double f0; double f1; u = u * (map->width - 1); v = v * (map->height - 1); x2 = (int)u; y2 = (int)v; if ((int)u + 1 < (int)map->width) x2++; if ((int)v + 1 < (int)map->height) y2++; f0 = (double)(map->map[(int)v * map->width + (int)u] * 0.5) \ * (1 - (u - (int)u)) + map->map[(int)v * map->width + x2] \ * (u - (int)u); f1 = map->map[y2 * map->width + (int)u] \ * (1 - (u - (int)u)) + (double)(map->map[y2 * map->width + x2] * 0.5) \ * (u - (int)u); return (f0 * (1 - (v - (int)v)) + f1 * (v - (int)v)); } void perturb_normal(t_vector *normal, t_bump_map *map, double u, double v) { double h00; double h01; double h10; double dhdu; double dhdv; if (u < 0) u += 1.0; if (v < 0) v += 1.0; h00 = bilinear_sample(u, v, map); h01 = bilinear_sample(u + 1.0 / map->width, v, map); h10 = bilinear_sample(u, v + 1.0 / map->height, map); dhdu = -(h01 - h00); dhdv = -(h10 - h00); *normal = (t_vector){\ normal->x + 1 * dhdu + 0 * dhdv, \ normal->y + 0 * dhdu + 1 * dhdv, \ normal->z + 0 * dhdu + 0 * dhdv \ }; normalize_vector(normal); }