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/dimension/objects.h | 22 ++++++++++++++++++---- libdimension/tests/render.c | 2 +- libdimension/triangle.c | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 49 insertions(+), 9 deletions(-) (limited to 'libdimension') 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