rtv1/src/phong.c

104 lines
3.0 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* phong.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: gbrochar <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2019/02/08 15:38:13 by gbrochar #+# #+# */
/* Updated: 2019/02/22 18:12:11 by gbrochar ### ########.fr */
/* */
/* ************************************************************************** */
#include "rtv1.h"
t_ray get_light_ray(t_ray r, double t, t_spot spot)
{
t_ray l_r;
l_r.o = vec_add(r.o, vec_mul(r.d, t));
l_r.d = vec_sub(spot.o, l_r.o);
normalize(&l_r.d);
return (l_r);
}
double get_intensity(t_env *e, t_ray r,
t_spot spot, t_obj_list obj)
{
t_ray l_r;
t_vec normal;
double length;
double i;
l_r = get_light_ray(r, obj.t, spot);
length = vec_length(vec_sub(spot.o, l_r.o));
normal = e->func.normal_obj[obj.type](obj.obj, r, obj.t);
i = dot_product(l_r.d, normal);
if (i > 0)
return ((spot.i * i) / (length * length));
return (0);
}
int intersect_phong(t_env *e, t_ray r,
t_spot spot, t_obj_list obj)
{
t_ray l_r;
double length;
t_obj_list *ret;
l_r = get_light_ray(r, obj.t, spot);
length = vec_length(vec_sub(spot.o, l_r.o));
if (!(ret = intersect_ray(e, l_r)) || ret->t > length)
return (SUCCESS);
return (FAILURE);
}
double get_specular(t_env *e, t_ray ray,
t_spot spot, t_obj_list obj)
{
t_vec normal;
t_vec i;
t_vec r;
t_vec v;
double spec_coef;
v = vec_sub(ray.o, vec_add(ray.o, vec_mul(ray.d, obj.t)));
i = vec_sub(vec_add(ray.o, vec_mul(ray.d, obj.t)), spot.o);
normal = e->func.normal_obj[obj.type](obj.obj, ray, obj.t);
normalize(&i);
r = get_r_vec(v, normal);
normalize(&r);
spec_coef = dot_product(r, i);
if (spec_coef > M_PI / 2 - e->spec_radius
&& spec_coef < M_PI / 2 + e->spec_radius
&& dot_product(normal, vec_mul(i, -1)) > 0)
return ((spec_coef + e->spec_radius - M_PI / 2) * e->spec_ratio);
return (0);
}
t_color phong(t_env *e, t_ray r, t_obj_list *obj)
{
t_spot_list *browser;
t_obj_list backup;
double i;
double specular;
i = 0;
specular = 0;
backup = *obj;
browser = e->spots;
while (browser)
{
if (SUCCESS == intersect_phong(e, r, browser->spot, backup))
i += get_intensity(e, r, browser->spot, backup);
specular += get_specular(e, r, browser->spot, backup);
browser = browser->next;
}
if (i > 1)
i = 1;
return (color_cap(color_add(
color_mul(obj->c, e->ambient
+ ((double)1 - e->ambient) * i),
color_mul(color(255, 255, 255), specular))));
}