122 lines
4.1 KiB
C
122 lines
4.1 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* bump.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: vvobis <marvin@42.fr> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* 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);
|
|
}
|