summaryrefslogtreecommitdiffstats
path: root/libdimension/cylinder.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2010-08-14 18:05:59 -0600
committerTavian Barnes <tavianator@gmail.com>2010-08-14 18:05:59 -0600
commit97efd0601d412131635766fa221ddb946e05b337 (patch)
tree3b9819a06fdd7e18658a751a342449de7a11ea42 /libdimension/cylinder.c
parentea6ea322433b583df411d4a5643115e5cff7ebd5 (diff)
downloaddimension-97efd0601d412131635766fa221ddb946e05b337.tar.xz
Support closed cylinders.
Diffstat (limited to 'libdimension/cylinder.c')
-rw-r--r--libdimension/cylinder.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/libdimension/cylinder.c b/libdimension/cylinder.c
index fb9c12c..2020fa2 100644
--- a/libdimension/cylinder.c
+++ b/libdimension/cylinder.c
@@ -34,13 +34,16 @@ static bool dmnsn_cylinder_inside_fn(const dmnsn_object *cylinder,
/* Allocate a new cylinder object */
dmnsn_object *
-dmnsn_new_cylinder()
+dmnsn_new_cylinder(bool open)
{
dmnsn_object *cylinder = dmnsn_new_object();
cylinder->intersection_fn = &dmnsn_cylinder_intersection_fn;
cylinder->inside_fn = &dmnsn_cylinder_inside_fn;
cylinder->bounding_box.min = dmnsn_new_vector(-1.0, -1.0, -1.0);
cylinder->bounding_box.max = dmnsn_new_vector(1.0, 1.0, 1.0);
+ if (open) {
+ cylinder->ptr = cylinder; /* (bool)cyliner->ptr == open */
+ }
return cylinder;
}
@@ -57,7 +60,6 @@ dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder, dmnsn_line line,
b = 2.0*(l.n.x*l.x0.x + l.n.z*l.x0.z);
c = l.x0.x*l.x0.x + l.x0.z*l.x0.z - 1.0;
-
if (b*b - 4.0*a*c >= 0.0) {
t = (-b - sqrt(b*b - 4.0*a*c))/(2.0*a);
dmnsn_vector p = dmnsn_line_point(l, t);
@@ -65,19 +67,42 @@ dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder, dmnsn_line line,
if (t < 0.0 || p.y <= -1.0 || p.y >= 1.0) {
t = (-b + sqrt(b*b - 4.0*a*c))/(2.0*a);
p = dmnsn_line_point(l, t);
-
- if (t < 0.0 || p.y <= -1.0 || p.y >= 1.0)
- return false;
}
- p.y = 0;
+ if (!cylinder->ptr) {
+ /* Test for cap intersections */
+ double tcap = (-1.0 - l.x0.y)/l.n.y;
+ dmnsn_vector pcap = dmnsn_line_point(l, tcap);
+ dmnsn_vector norm = dmnsn_new_vector(0.0, -1.0, 0.0);
+
+ if (tcap < 0.0 || pcap.x*pcap.x + pcap.z*pcap.z >= 1.0) {
+ tcap = (+1.0 - l.x0.y)/l.n.y;
+ pcap = dmnsn_line_point(l, tcap);
+ norm = dmnsn_new_vector(0.0, 1.0, 0.0);
+ }
- intersection->ray = line;
- intersection->t = t;
- intersection->normal = dmnsn_transform_normal(cylinder->trans, p);
- intersection->texture = cylinder->texture;
- intersection->interior = cylinder->interior;
- return true;
+ if (tcap >= 0.0
+ && (tcap < t || p.y <= -1.0 || p.y >= 1.0)
+ && pcap.x*pcap.x + pcap.z*pcap.z < 1.0)
+ {
+ intersection->ray = line;
+ intersection->t = tcap;
+ intersection->normal = dmnsn_transform_normal(cylinder->trans, norm);
+ intersection->texture = cylinder->texture;
+ intersection->interior = cylinder->interior;
+ return true;
+ }
+ }
+
+ if (t >= 0.0 && p.y > -1.0 && p.y < 1.0) {
+ p.y = 0;
+ intersection->ray = line;
+ intersection->t = t;
+ intersection->normal = dmnsn_transform_normal(cylinder->trans, p);
+ intersection->texture = cylinder->texture;
+ intersection->interior = cylinder->interior;
+ return true;
+ }
}
return false;