summaryrefslogtreecommitdiffstats
path: root/libdimension/cone.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdimension/cone.c')
-rw-r--r--libdimension/cone.c113
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;
}