return (vec_norm(vec_diff(start, projection)));
}
+double dist_point_from_plane(const t_plane *plane, t_vec3 point)
+{
+ return (fabs(vec_scalar_mul(plane->normal,
+ vec_diff(point, plane->point))));
+}
+
int is_behind_ray(const t_ray *ray, t_vec3 point)
{
return (0 > vec_scalar_mul(ray->direction, vec_diff(point, ray->start)));
amb->brightness));
}
+t_vec3 get_cylinder_normal(t_vec3 point, const t_cylinder *cylinder)
+{
+ t_vec3 radial_vec;
+ double dist_from_round;
+ double dist_from_top;
+ double dist_from_bottom;
+ t_plane base;
+
+ radial_vec = vec_vec_mul(cylinder->rot_axis,
+ vec_diff(point, cylinder->center));
+ dist_from_round = fabs(vec_norm(radial_vec) - cylinder->radius);
+ base.normal = cylinder->rot_axis;
+ base.point = vec_add(cylinder->center,
+ vec_real_mul(cylinder->rot_axis, cylinder->height / 2));
+ dist_from_top = dist_point_from_plane(&base, point);
+ base.point = vec_diff(cylinder->center,
+ vec_real_mul(cylinder->rot_axis, cylinder->height / 2));
+ dist_from_bottom = dist_point_from_plane(&base, point);
+ if (dist_from_round < dist_from_top && dist_from_round < dist_from_bottom)
+ return (radial_vec);
+ if (dist_from_top < dist_from_bottom)
+ return (cylinder->rot_axis);
+ return (vec_real_mul(cylinder->rot_axis, -1));
+}
+
+t_vec3 get_object_normal(const t_object *object, t_vec3 point)
+{
+ if (object->type == PLANE)
+ return (object->object.plane.normal);
+ if (object->type == SPHERE)
+ return (vec_diff(point, object->object.sphere.center));
+ if (object->type == CYLINDER)
+ return (get_cylinder_normal(point, &object->object.cylinder));
+ return ((t_vec3){.x = 0, .y = 0, .z = 0});
+}
+
+t_color get_light_contribution(t_vec3 point, const t_object *object, const t_light *light, const t_scene *scene)
+{
+ t_ray new_ray;
+ const t_object *obstruction;
+ t_vec3 normal;
+ double angle_multiplier;
+
+ new_ray.start = point;
+ new_ray.direction = vec_diff(light->position, new_ray.start);
+ obstruction = find_nearest_object(&new_ray, &scene->objects);
+ normal = get_object_normal(object, point);
+ angle_multiplier = vec_scalar_mul(normal, new_ray.direction)
+ / (vec_norm(normal) * vec_norm(new_ray.direction));
+ if (angle_multiplier > 0 && (!obstruction
+ || 1 < get_intersection_arg(&new_ray, obstruction)
+ || get_intersection_arg(&new_ray, obstruction) < 0))
+ return (vec_real_mul(
+ vec_elwise_mul(light->color, object->object.plane.color),
+ light->brightness * angle_multiplier));
+ else
+ return ((t_color){.x = 0, .y = 0, .z = 0});
+}
+
t_color get_object_color(const t_ray *ray, const t_object *object,
const t_scene *scene)
{
t_color result;
const t_light *light;
size_t i;
- t_ray new_ray;
- const t_object *obstruction;
result = (t_color){.x = 0, .y = 0, .z = 0};
i = 0;
while (i < scene->lights.size)
{
light = ft_vec_caccess(&scene->lights, i);
- new_ray.start = vec_add(ray->start, vec_real_mul(ray->direction,
- get_intersection_arg(ray, object)));
- new_ray.direction = vec_diff(light->position, new_ray.start);
- obstruction = find_nearest_object(&new_ray, &scene->objects);
- if (!obstruction || 1 < get_intersection_arg(&new_ray, obstruction)
- || get_intersection_arg(&new_ray, obstruction) < 0)
- result = vec_add(result, vec_real_mul(vec_elwise_mul(light->color,
- object->object.plane.color), light->brightness));
+ result = vec_add(result, get_light_contribution(
+ ray_point(ray, get_intersection_arg(ray, object)),
+ object, light, scene));
++i;
}
result = vec_add(result, get_ambient_color(object, &scene->ambient_light));