From 1374b946398544a28ac989c75570d4b7c6937873 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 14 Sep 2011 18:56:08 -0400 Subject: Transform normals as pseudovectors, not vectors. Also clarify the vector transformation API. Instead of dmnsn_transform_vector(), we have: - dmnsn_transform_point() - dmnsn_transform_direction() - dmnsn_transform_normal() --- libdimension/dimension/geometry.h | 41 ++++++++++++++++++++++++++++++++------- libdimension/dimension/object.h | 27 +++++--------------------- 2 files changed, 39 insertions(+), 29 deletions(-) (limited to 'libdimension/dimension') diff --git a/libdimension/dimension/geometry.h b/libdimension/dimension/geometry.h index 45aa6c6..d2ad362 100644 --- a/libdimension/dimension/geometry.h +++ b/libdimension/dimension/geometry.h @@ -375,9 +375,9 @@ dmnsn_matrix dmnsn_matrix_inverse(dmnsn_matrix A); /** Multiply two matricies. */ dmnsn_matrix dmnsn_matrix_mul(dmnsn_matrix lhs, dmnsn_matrix rhs); -/** Transform a vector by a matrix. */ +/** Transform a point by a matrix. */ DMNSN_INLINE dmnsn_vector -dmnsn_transform_vector(dmnsn_matrix T, dmnsn_vector v) +dmnsn_transform_point(dmnsn_matrix T, dmnsn_vector v) { /* 9 multiplications, 9 additions */ dmnsn_vector r; @@ -387,6 +387,36 @@ dmnsn_transform_vector(dmnsn_matrix T, dmnsn_vector v) return r; } +/** Transform a direction by a matrix. */ +DMNSN_INLINE dmnsn_vector +dmnsn_transform_direction(dmnsn_matrix T, dmnsn_vector v) +{ + /* 9 multiplications, 9 additions */ + dmnsn_vector r; + r.x = T.n[0][0]*v.x + T.n[0][1]*v.y + T.n[0][2]*v.z; + r.y = T.n[1][0]*v.x + T.n[1][1]*v.y + T.n[1][2]*v.z; + r.z = T.n[2][0]*v.x + T.n[2][1]*v.y + T.n[2][2]*v.z; + return r; +} + +/** + * Transform a pseudovector by a matrix. + * @param[in] Tinv The inverse of the transformation matrix. + * @param[in] v The pseudovector to transform + * @return The transformed pseudovector. + */ +DMNSN_INLINE dmnsn_vector +dmnsn_transform_normal(dmnsn_matrix Tinv, dmnsn_vector v) +{ + /* Multiply by the transpose of the inverse + (9 multiplications, 6 additions) */ + dmnsn_vector r; + r.x = Tinv.n[0][0]*v.x + Tinv.n[1][0]*v.y + Tinv.n[2][0]*v.z; + r.y = Tinv.n[0][1]*v.x + Tinv.n[1][1]*v.y + Tinv.n[2][1]*v.z; + r.z = Tinv.n[0][2]*v.x + Tinv.n[1][2]*v.y + Tinv.n[2][2]*v.z; + return r; +} + /** Transform a bounding box by a matrix. */ dmnsn_bounding_box dmnsn_transform_bounding_box(dmnsn_matrix T, dmnsn_bounding_box box); @@ -401,11 +431,8 @@ dmnsn_transform_line(dmnsn_matrix T, dmnsn_line l) { /* 18 multiplications, 24 additions */ dmnsn_line ret; - ret.x0 = dmnsn_transform_vector(T, l.x0); - ret.n = dmnsn_vector_sub( - dmnsn_transform_vector(T, dmnsn_vector_add(l.x0, l.n)), - ret.x0 - ); + ret.x0 = dmnsn_transform_point(T, l.x0); + ret.n = dmnsn_transform_direction(T, l.n); return ret; } diff --git a/libdimension/dimension/object.h b/libdimension/dimension/object.h index 8254782..8b497ce 100644 --- a/libdimension/dimension/object.h +++ b/libdimension/dimension/object.h @@ -111,24 +111,6 @@ void dmnsn_delete_object(dmnsn_object *object); */ void dmnsn_initialize_object(dmnsn_object *object); -/** - * Transform a surface normal vector. - * @param[in] trans The transformation matrix. - * @param[in] normal The normal vector to transform - * @return The transformed normal vector. - */ -DMNSN_INLINE dmnsn_vector -dmnsn_transform_normal(dmnsn_matrix trans, dmnsn_vector normal) -{ - return dmnsn_vector_normalized( - dmnsn_vector_sub( - dmnsn_transform_vector(trans, normal), - /* Optimized form of dmnsn_transform_vector(trans, dmnsn_zero) */ - dmnsn_new_vector(trans.n[0][3], trans.n[1][3], trans.n[2][3]) - ) - ); -} - /** * Appropriately transform a ray, then test for an intersection. * @param[in] object The object to test. @@ -144,9 +126,10 @@ dmnsn_object_intersection(const dmnsn_object *object, dmnsn_line line, intersection->object = NULL; if (object->intersection_fn(object, line_trans, intersection)) { /* Get us back into world coordinates */ - intersection->ray = line; - intersection->normal = dmnsn_transform_normal(object->trans, - intersection->normal); + intersection->ray = line; + intersection->normal = dmnsn_vector_normalized( + dmnsn_transform_normal(object->trans_inv, intersection->normal) + ); if (!intersection->object) { intersection->object = object; } @@ -166,6 +149,6 @@ dmnsn_object_intersection(const dmnsn_object *object, dmnsn_line line, DMNSN_INLINE bool dmnsn_object_inside(const dmnsn_object *object, dmnsn_vector point) { - point = dmnsn_transform_vector(object->trans_inv, point); + point = dmnsn_transform_point(object->trans_inv, point); return object->inside_fn(object, point); } -- cgit v1.2.3