diff options
Diffstat (limited to 'libdimension/cone.c')
-rw-r--r-- | libdimension/cone.c | 113 |
1 files changed, 58 insertions, 55 deletions
diff --git a/libdimension/cone.c b/libdimension/cone.c index a2d2d55..fe01e85 100644 --- a/libdimension/cone.c +++ b/libdimension/cone.c @@ -26,18 +26,19 @@ #include "dimension.h" #include <math.h> -/** Cone payload type. */ -typedef struct dmnsn_cone_payload { +/** Cone type. */ +typedef struct dmnsn_cone { + dmnsn_object object; double r1, r2; -} dmnsn_cone_payload; +} dmnsn_cone; /** Intersection callback for a cone. */ static bool -dmnsn_cone_intersection_fn(const dmnsn_object *cone, dmnsn_line l, +dmnsn_cone_intersection_fn(const dmnsn_object *object, dmnsn_line l, dmnsn_intersection *intersection) { - const dmnsn_cone_payload *payload = cone->ptr; - double r1 = payload->r1, r2 = payload->r2; + const dmnsn_cone *cone = (const dmnsn_cone *)object; + double r1 = cone->r1, r2 = cone->r2; /* Solve (x0 + nx*t)^2 + (z0 + nz*t)^2 == (((r2 - r1)*(y0 + ny*t) + r1 + r2)/2)^2 */ @@ -79,22 +80,29 @@ dmnsn_cone_intersection_fn(const dmnsn_object *cone, dmnsn_line l, /** Inside callback for a cone. */ static bool -dmnsn_cone_inside_fn(const dmnsn_object *cone, dmnsn_vector point) +dmnsn_cone_inside_fn(const dmnsn_object *object, dmnsn_vector point) { - const dmnsn_cone_payload *payload = cone->ptr; - double r1 = payload->r1, r2 = payload->r2; + const dmnsn_cone *cone = (const dmnsn_cone *)cone; + double r1 = cone->r1, r2 = cone->r2; double r = (point.y*(r2 - r1) + r1 + r2)/2.0; return point.x*point.x + point.z*point.z < r*r && point.y > -1.0 && point.y < 1.0; } +/** Cone cap type. */ +typedef struct dmnsn_cone_cap { + dmnsn_object object; + double r; +} dmnsn_cone_cap; + /** Cone cap intersection function. */ static bool -dmnsn_cone_cap_intersection_fn(const dmnsn_object *cap, dmnsn_line l, +dmnsn_cone_cap_intersection_fn(const dmnsn_object *object, dmnsn_line l, dmnsn_intersection *intersection) { if (l.n.y != 0.0) { - double *rptr = cap->ptr, r = *rptr; + const dmnsn_cone_cap *cap = (const dmnsn_cone_cap *)object; + double r = cap->r; double t = -l.x0.y/l.n.y; dmnsn_vector p = dmnsn_line_point(l, t); if (t >= 0.0 && p.x*p.x + p.z*p.z <= r*r) { @@ -109,7 +117,7 @@ dmnsn_cone_cap_intersection_fn(const dmnsn_object *cap, dmnsn_line l, /** Inside callback for a cone cap. */ static bool -dmnsn_cone_cap_inside_fn(const dmnsn_object *cone, dmnsn_vector point) +dmnsn_cone_cap_inside_fn(const dmnsn_object *object, dmnsn_vector point) { return false; } @@ -118,57 +126,52 @@ dmnsn_cone_cap_inside_fn(const dmnsn_object *cone, dmnsn_vector point) dmnsn_object * dmnsn_new_cone_cap(double r) { - dmnsn_object *cap = dmnsn_new_object(); - cap->intersection_fn = dmnsn_cone_cap_intersection_fn; - cap->inside_fn = dmnsn_cone_cap_inside_fn; - cap->bounding_box.min = dmnsn_new_vector(-r, 0.0, -r); - cap->bounding_box.max = dmnsn_new_vector(+r, 0.0, +r); - - double *payload = DMNSN_MALLOC(double); - *payload = r; - cap->ptr = payload; - cap->free_fn = dmnsn_free; - - return cap; + dmnsn_cone_cap *cap = DMNSN_MALLOC(dmnsn_cone_cap); + dmnsn_init_object(&cap->object); + cap->object.intersection_fn = dmnsn_cone_cap_intersection_fn; + cap->object.inside_fn = dmnsn_cone_cap_inside_fn; + cap->object.bounding_box.min = dmnsn_new_vector(-r, 0.0, -r); + cap->object.bounding_box.max = dmnsn_new_vector(+r, 0.0, +r); + cap->r = r; + return &cap->object; } /* Allocate a new cone object */ dmnsn_object * dmnsn_new_cone(double r1, double r2, bool open) { - dmnsn_object *cone = dmnsn_new_object(); - cone->intersection_fn = dmnsn_cone_intersection_fn; - cone->inside_fn = dmnsn_cone_inside_fn; + dmnsn_cone *cone = DMNSN_MALLOC(dmnsn_cone); + dmnsn_init_object(&cone->object); + cone->object.intersection_fn = dmnsn_cone_intersection_fn; + cone->object.inside_fn = dmnsn_cone_inside_fn; double rmax = dmnsn_max(r1, r2); - cone->bounding_box.min = dmnsn_new_vector(-rmax, -1.0, -rmax); - cone->bounding_box.max = dmnsn_new_vector(rmax, 1.0, rmax); - - dmnsn_cone_payload *payload = DMNSN_MALLOC(dmnsn_cone_payload); - payload->r1 = r1; - payload->r2 = r2; - cone->ptr = payload; - cone->free_fn = dmnsn_free; + cone->object.bounding_box.min = dmnsn_new_vector(-rmax, -1.0, -rmax); + cone->object.bounding_box.max = dmnsn_new_vector(rmax, 1.0, rmax); + cone->r1 = r1; + cone->r2 = r2; - /* Implement closed cones as a union with the caps */ - if (!open) { - dmnsn_object *cap1 = dmnsn_new_cone_cap(r1); - dmnsn_object *cap2 = dmnsn_new_cone_cap(r2); - cap1->intrinsic_trans = dmnsn_translation_matrix( - dmnsn_new_vector(0.0, -1.0, 0.0) - ); - cap2->intrinsic_trans = dmnsn_translation_matrix( - dmnsn_new_vector(0.0, +1.0, 0.0) - ); - /* Flip the normal around for the top cap */ - cap2->intrinsic_trans.n[1][1] = -1.0; - - dmnsn_array *withcaps = dmnsn_new_array(sizeof(dmnsn_object *)); - dmnsn_array_push(withcaps, &cone); - dmnsn_array_push(withcaps, &cap1); - dmnsn_array_push(withcaps, &cap2); - cone = dmnsn_new_csg_union(withcaps); - dmnsn_delete_array(withcaps); + if (open) { + return &cone->object; } - return cone; + /* Implement closed cones as a union with the caps */ + dmnsn_object *cap1 = dmnsn_new_cone_cap(r1); + dmnsn_object *cap2 = dmnsn_new_cone_cap(r2); + cap1->intrinsic_trans = dmnsn_translation_matrix( + dmnsn_new_vector(0.0, -1.0, 0.0) + ); + cap2->intrinsic_trans = dmnsn_translation_matrix( + dmnsn_new_vector(0.0, +1.0, 0.0) + ); + /* Flip the normal around for the top cap */ + cap2->intrinsic_trans.n[1][1] = -1.0; + + dmnsn_array *withcaps = dmnsn_new_array(sizeof(dmnsn_object *)); + dmnsn_array_push(withcaps, &cone); + dmnsn_array_push(withcaps, &cap1); + dmnsn_array_push(withcaps, &cap2); + dmnsn_object *cone_cap_union = dmnsn_new_csg_union(withcaps); + dmnsn_delete_array(withcaps); + + return cone_cap_union; } |