|
| 1 | +/* ************************************************************************** */ |
| 2 | +/* */ |
| 3 | +/* ::: :::::::: */ |
| 4 | +/* hit_cone.c :+: :+: :+: */ |
| 5 | +/* +:+ +:+ +:+ */ |
| 6 | +/* By: smatsuo <[email protected]> +#+ +:+ +#+ */ |
| 7 | +/* +#+#+#+#+#+ +#+ */ |
| 8 | +/* Created: 2023/12/27 20:22:42 by smatsuo #+# #+# */ |
| 9 | +/* Updated: 2023/12/27 22:40:01 by smatsuo ### ########.fr */ |
| 10 | +/* */ |
| 11 | +/* ************************************************************************** */ |
| 12 | + |
| 13 | +#include "tracer.h" |
| 14 | + |
| 15 | +static bool set_rec(t_object *cone, t_ray ray, double t, t_hit_record *rec) |
| 16 | +{ |
| 17 | + const t_cone_conf conf = *(t_cone_conf *)cone->conf; |
| 18 | + const t_vec3 pc = vec3_sub(ray_at(ray, t), conf.apex); |
| 19 | + |
| 20 | + rec->t = t; |
| 21 | + rec->point = ray_at(ray, t); |
| 22 | + rec->normal = vec3_normalize(vec3_sub(pc, vec3_scale(conf.axis, |
| 23 | + vec3_dot(pc, pc) / vec3_dot(conf.axis, pc)))); |
| 24 | + rec->material = cone->material; |
| 25 | + rec->object_color = conf.color; |
| 26 | + return (true); |
| 27 | +} |
| 28 | + |
| 29 | +static bool is_hit_side(t_cone_conf conf, t_ray ray, double t) |
| 30 | +{ |
| 31 | + const t_vec3 co = vec3_sub(ray_at(ray, t), conf.apex); |
| 32 | + |
| 33 | + return (vec3_dot(co, conf.axis) > 0 |
| 34 | + && vec3_length(vec3_project(co, conf.axis)) <= conf.height); |
| 35 | +} |
| 36 | + |
| 37 | +static bool hit_cone_cap(t_object *cone, t_ray ray, double tmin, |
| 38 | + t_hit_record *rec) |
| 39 | +{ |
| 40 | + const t_cone_conf conf = *(t_cone_conf *)cone->conf; |
| 41 | + t_object circle; |
| 42 | + |
| 43 | + circle = (t_object){ |
| 44 | + .type = OBJ_CIRCLE, |
| 45 | + .conf = &(t_circle_conf){ |
| 46 | + .center = vec3_add_scaled(conf.apex, conf.axis, conf.height), |
| 47 | + .normal = conf.axis, |
| 48 | + .radius = conf.radius, |
| 49 | + .color = conf.color}, |
| 50 | + .material = cone->material}; |
| 51 | + return (hit_circle(&circle, ray, tmin, rec)); |
| 52 | +} |
| 53 | + |
| 54 | +bool hit_cone(t_object *cone, t_ray ray, double tmin, t_hit_record *rec) |
| 55 | +{ |
| 56 | + const t_cone_conf conf = *(t_cone_conf *)cone->conf; |
| 57 | + t_quadratic q; |
| 58 | + const double cos_2 = pow(cos(atan2(conf.radius, conf.height)), 2); |
| 59 | + const t_vec3 oc = vec3_sub(ray.origin, conf.apex); |
| 60 | + |
| 61 | + q.a = pow(vec3_dot(ray.direction, conf.axis), 2) |
| 62 | + - vec3_length_squared(ray.direction) * cos_2; |
| 63 | + q.half_b = vec3_dot(ray.direction, conf.axis) * vec3_dot(oc, conf.axis) |
| 64 | + - vec3_dot(ray.direction, vec3_scale(oc, cos_2)); |
| 65 | + q.c = pow(vec3_dot(oc, conf.axis), 2) |
| 66 | + - vec3_dot(oc, vec3_scale(oc, cos_2)); |
| 67 | + solve_quadratic(&q); |
| 68 | + if (!q.solved) |
| 69 | + return (false); |
| 70 | + if (q.t1 > tmin && is_hit_side(conf, ray, q.t1)) |
| 71 | + return (set_rec(cone, ray, q.t1, rec)); |
| 72 | + if (hit_cone_cap(cone, ray, tmin, rec)) |
| 73 | + return (true); |
| 74 | + if (q.t2 > tmin && is_hit_side(conf, ray, q.t2)) |
| 75 | + return (set_rec(cone, ray, q.t2, rec)); |
| 76 | + return (false); |
| 77 | +} |
0 commit comments