summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2011-12-17 16:43:19 -0500
committerTavian Barnes <tavianator@gmail.com>2011-12-17 17:49:00 -0500
commit4dde640671a8278ff6c41ef21f03ba351828009c (patch)
tree4ab145084a16a6af07ff53d606c40464f8cabec0
parent65b1d1998f560c03c7cc204b0ee4f5c9c4f517e0 (diff)
downloaddimension-4dde640671a8278ff6c41ef21f03ba351828009c.tar.xz
Make triangles smooth.
-rw-r--r--libdimension-python/dimension.pxd8
-rw-r--r--libdimension-python/dimension.pyx15
-rw-r--r--libdimension/dimension/objects.h22
-rw-r--r--libdimension/tests/render.c2
-rw-r--r--libdimension/triangle.c34
5 files changed, 68 insertions, 13 deletions
diff --git a/libdimension-python/dimension.pxd b/libdimension-python/dimension.pxd
index 0d0fcc4..3f89e71 100644
--- a/libdimension-python/dimension.pxd
+++ b/libdimension-python/dimension.pxd
@@ -321,9 +321,15 @@ cdef extern from "../libdimension/dimension.h":
dmnsn_object *dmnsn_new_object()
void dmnsn_delete_object(dmnsn_object *object)
+ dmnsn_object *dmnsn_new_flat_triangle(dmnsn_vector a,
+ dmnsn_vector b,
+ dmnsn_vector c)
dmnsn_object *dmnsn_new_triangle(dmnsn_vector a,
dmnsn_vector b,
- dmnsn_vector c)
+ dmnsn_vector c,
+ dmnsn_vector na,
+ dmnsn_vector nb,
+ dmnsn_vector nc)
dmnsn_object *dmnsn_new_plane(dmnsn_vector normal)
dmnsn_object *dmnsn_new_sphere()
dmnsn_object *dmnsn_new_cube()
diff --git a/libdimension-python/dimension.pyx b/libdimension-python/dimension.pyx
index 6a76974..a34d2eb 100644
--- a/libdimension-python/dimension.pyx
+++ b/libdimension-python/dimension.pyx
@@ -1124,16 +1124,25 @@ cdef class Object(_Transformable):
cdef class Triangle(Object):
"""A triangle."""
- def __init__(self, a, b, c, *args, **kwargs):
+ def __init__(self, a, b, c, a_normal = None, b_normal = None, c_normal = None,
+ *args, **kwargs):
"""
Create a Triangle.
Keyword arguments:
- a, b, c -- the corners of the triangle
+ a, b, c -- the corners of the triangle
+ a_normal, b_normal, c_normal -- the optional normal vectors at those corners
Additionally, Triangle() accepts any arguments that Object() accepts.
"""
- self._object = dmnsn_new_triangle(Vector(a)._v, Vector(b)._v, Vector(c)._v)
+ if a_normal is None and b_normal is None and c_normal is None:
+ a_normal = cross(b - a, c - a)
+ b_normal = a_normal
+ c_normal = a_normal
+ self._object = dmnsn_new_triangle(Vector(a)._v, Vector(b)._v, Vector(c)._v,
+ Vector(a_normal)._v,
+ Vector(b_normal)._v,
+ Vector(c_normal)._v)
Object.__init__(self, *args, **kwargs)
cdef class Plane(Object):
diff --git a/libdimension/dimension/objects.h b/libdimension/dimension/objects.h
index 001cb3d..9ce9e46 100644
--- a/libdimension/dimension/objects.h
+++ b/libdimension/dimension/objects.h
@@ -26,14 +26,28 @@
#include <stdbool.h>
/**
- * A triangle.
+ * A triangle, with normals interpolated between the points.
+ * @param[in] a The first corner of the triangle.
+ * @param[in] b The second corner of the triangle.
+ * @param[in] c The third corner of the triangle.
+ * @param[in] na The normal at \p a.
+ * @param[in] nb The normal at \p b.
+ * @param[in] nc The normal at \p c.
+ */
+dmnsn_object *dmnsn_new_triangle(
+ dmnsn_vector a, dmnsn_vector b, dmnsn_vector c,
+ dmnsn_vector na, dmnsn_vector nb, dmnsn_vector nc
+);
+
+/**
+ * A flat triangle, without normal interpolation.
* @param[in] a The first corner of the triangle.
* @param[in] b The second corner of the triangle.
* @param[in] c The third corner of the triangle.
*/
-dmnsn_object *dmnsn_new_triangle(dmnsn_vector a,
- dmnsn_vector b,
- dmnsn_vector c);
+dmnsn_object *dmnsn_new_flat_triangle(
+ dmnsn_vector a, dmnsn_vector b, dmnsn_vector c
+);
/**
* A plane.
diff --git a/libdimension/tests/render.c b/libdimension/tests/render.c
index 41b19b4..58a7930 100644
--- a/libdimension/tests/render.c
+++ b/libdimension/tests/render.c
@@ -240,7 +240,7 @@ dmnsn_test_scene_add_triangle_strip(dmnsn_scene *scene)
strip_textures[2]->pigment =
dmnsn_new_solid_pigment(DMNSN_TCOLOR(dmnsn_yellow));
for (unsigned int i = 0; i < 128; ++i) {
- dmnsn_object *triangle = dmnsn_new_triangle(a, b, c);
+ dmnsn_object *triangle = dmnsn_new_flat_triangle(a, b, c);
triangle->texture = strip_textures[i%3];
DMNSN_INCREF(triangle->texture);
dmnsn_array_push(strip_array, &triangle);
diff --git a/libdimension/triangle.c b/libdimension/triangle.c
index f224aa9..a176414 100644
--- a/libdimension/triangle.c
+++ b/libdimension/triangle.c
@@ -26,7 +26,7 @@
#include "dimension.h"
typedef struct dmnsn_triangle_payload {
- dmnsn_vector a, ab, ac, normal;
+ dmnsn_vector a, ab, ac, na, nab, nac, normal;
} dmnsn_triangle_payload;
/** Triangle intersection callback. */
@@ -43,7 +43,13 @@ dmnsn_triangle_intersection_fn(const dmnsn_object *triangle, dmnsn_line l,
double v = -dmnsn_vector_dot(l.n, dmnsn_vector_cross(payload->ab, ax0))/den;
if (t >= 0.0 && u >= 0.0 && v >= 0.0 && u + v <= 1.0) {
intersection->t = t;
- intersection->normal = payload->normal;
+ intersection->normal = dmnsn_vector_add(
+ payload->na,
+ dmnsn_vector_add(
+ dmnsn_vector_mul(u, payload->nab),
+ dmnsn_vector_mul(v, payload->nac)
+ )
+ );
return true;
}
@@ -59,17 +65,24 @@ dmnsn_triangle_inside_fn(const dmnsn_object *triangle, dmnsn_vector point)
/* Allocate a new triangle */
dmnsn_object *
-dmnsn_new_triangle(dmnsn_vector a, dmnsn_vector b, dmnsn_vector c)
+dmnsn_new_triangle(dmnsn_vector a, dmnsn_vector b, dmnsn_vector c,
+ dmnsn_vector na, dmnsn_vector nb, dmnsn_vector nc)
{
- dmnsn_object *triangle = dmnsn_new_object();
+ na = dmnsn_vector_normalized(na);
+ nb = dmnsn_vector_normalized(nb);
+ nc = dmnsn_vector_normalized(nc);
dmnsn_triangle_payload *payload =
dmnsn_malloc(sizeof(dmnsn_triangle_payload));
payload->a = a;
+ payload->na = na;
payload->ab = dmnsn_vector_sub(b, a);
+ payload->nab = dmnsn_vector_sub(nb, na);
payload->ac = dmnsn_vector_sub(c, a);
+ payload->nac = dmnsn_vector_sub(nc, na);
payload->normal = dmnsn_vector_cross(payload->ab, payload->ac);
+ dmnsn_object *triangle = dmnsn_new_object();
triangle->ptr = payload;
triangle->intersection_fn = dmnsn_triangle_intersection_fn;
triangle->inside_fn = dmnsn_triangle_inside_fn;
@@ -78,3 +91,16 @@ dmnsn_new_triangle(dmnsn_vector a, dmnsn_vector b, dmnsn_vector c)
triangle->bounding_box.max = dmnsn_vector_max(dmnsn_vector_max(a, b), c);
return triangle;
}
+
+/* Allocate a new flat triangle */
+dmnsn_object *
+dmnsn_new_flat_triangle(dmnsn_vector a, dmnsn_vector b, dmnsn_vector c)
+{
+ /* Flat triangles are just smooth triangles with identical normals at all
+ verticies */
+ dmnsn_vector normal = dmnsn_vector_cross(
+ dmnsn_vector_sub(b, a),
+ dmnsn_vector_sub(c, a)
+ );
+ return dmnsn_new_triangle(a, b, c, normal, normal, normal);
+}