From 4dde640671a8278ff6c41ef21f03ba351828009c Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sat, 17 Dec 2011 16:43:19 -0500 Subject: Make triangles smooth. --- libdimension-python/dimension.pxd | 8 +++++++- libdimension-python/dimension.pyx | 15 ++++++++++++--- libdimension/dimension/objects.h | 22 ++++++++++++++++++---- libdimension/tests/render.c | 2 +- libdimension/triangle.c | 34 ++++++++++++++++++++++++++++++---- 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 /** - * 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); +} -- cgit v1.2.3