summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension/cylinder.c49
-rw-r--r--libdimension/dimension/objects.h4
-rw-r--r--tests/libdimension/render.c4
3 files changed, 42 insertions, 15 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;
diff --git a/libdimension/dimension/objects.h b/libdimension/dimension/objects.h
index 4db161c..8f30eae 100644
--- a/libdimension/dimension/objects.h
+++ b/libdimension/dimension/objects.h
@@ -25,6 +25,8 @@
#ifndef DIMENSION_OBJECTS_H
#define DIMENSION_OBJECTS_H
+#include <stdbool.h>
+
/* A plane through the origin, with the given normal */
dmnsn_object *dmnsn_new_plane(dmnsn_vector normal);
@@ -35,6 +37,6 @@ dmnsn_object *dmnsn_new_sphere(void);
dmnsn_object *dmnsn_new_cube(void);
/* A cylinder, of radius 1, from y = -1 to y = 1 */
-dmnsn_object *dmnsn_new_cylinder(void);
+dmnsn_object *dmnsn_new_cylinder(bool open);
#endif /* DIMENSION_OBJECTS_H */
diff --git a/tests/libdimension/render.c b/tests/libdimension/render.c
index 7a55320..3f4525d 100644
--- a/tests/libdimension/render.c
+++ b/tests/libdimension/render.c
@@ -106,11 +106,11 @@ dmnsn_new_test_scene(void)
plane->texture->pigment = dmnsn_new_solid_pigment(dmnsn_white);
dmnsn_array_push(scene->objects, &plane);
- dmnsn_object *cylinder = dmnsn_new_cylinder();
+ dmnsn_object *cylinder = dmnsn_new_cylinder(false);
cylinder->trans =
dmnsn_matrix_mul(
dmnsn_rotation_matrix(dmnsn_new_vector(dmnsn_radians(-45.0), 0.0, 0.0)),
- dmnsn_scale_matrix(dmnsn_new_vector(0.1, 1.5, 0.1))
+ dmnsn_scale_matrix(dmnsn_new_vector(0.1, 1.25, 0.1))
);
cylinder->texture = dmnsn_new_texture();
cylinder->texture->pigment = dmnsn_new_solid_pigment(dmnsn_red);