From 3037c067f2937b68bfd0c7f906f7e7ecadd4b8d5 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 15 Apr 2010 00:06:22 -0400 Subject: Add transformations to textures and pigments. Also, object intersection callbacks are now responsible for handling their own transformations. --- libdimension/bvst.c | 33 ++-------- libdimension/canvas_pigment.c | 2 + libdimension/csg.c | 131 +++++++++++++++------------------------ libdimension/cube.c | 35 ++++++----- libdimension/dimension/object.h | 4 ++ libdimension/dimension/texture.h | 11 ++++ libdimension/object.c | 25 ++++++++ libdimension/sphere.c | 18 +++--- libdimension/texture.c | 21 +++++++ 9 files changed, 149 insertions(+), 131 deletions(-) diff --git a/libdimension/bvst.c b/libdimension/bvst.c index 9f9e94b..c0888bb 100644 --- a/libdimension/bvst.c +++ b/libdimension/bvst.c @@ -101,10 +101,9 @@ static void dmnsn_bvst_node_swallow(dmnsn_bvst_node *node, void dmnsn_bvst_insert(dmnsn_bvst *tree, dmnsn_object *object) { - dmnsn_bvst_node *node = dmnsn_new_bvst_node(), *parent = tree->root; + dmnsn_object_precompute(object); - /* Store the inverse of the transformation matrix */ - object->trans_inv = dmnsn_matrix_inverse(object->trans); + dmnsn_bvst_node *node = dmnsn_new_bvst_node(), *parent = tree->root; node->contains = NULL; node->container = NULL; @@ -112,8 +111,7 @@ dmnsn_bvst_insert(dmnsn_bvst *tree, dmnsn_object *object) node->object = object; /* Calculate the new bounding box */ - node->bounding_box = dmnsn_matrix_bounding_box_mul(object->trans, - object->bounding_box); + node->bounding_box = object->bounding_box; /* Now insert the node */ @@ -283,7 +281,6 @@ static bool dmnsn_ray_box_intersection(dmnsn_line ray, dmnsn_bounding_box box, static dmnsn_bvst_search_result dmnsn_bvst_search_recursive(dmnsn_bvst_node *node, dmnsn_line ray, double t) { - dmnsn_line ray_trans; dmnsn_bvst_search_result result_temp, result = { .node = NULL, .intersected = false @@ -303,14 +300,11 @@ dmnsn_bvst_search_recursive(dmnsn_bvst_node *node, dmnsn_line ray, double t) if (dmnsn_bounding_box_contains(node->bounding_box, ray.x0) || dmnsn_ray_box_intersection(ray, node->bounding_box, t)) { - /* Transform the ray according to the object */ - ray_trans = dmnsn_matrix_line_mul(node->object->trans_inv, ray); - - if (dmnsn_bounding_box_contains(node->object->bounding_box, ray_trans.x0) - || dmnsn_ray_box_intersection(ray_trans, node->object->bounding_box, t)) + if (dmnsn_bounding_box_contains(node->object->bounding_box, ray.x0) + || dmnsn_ray_box_intersection(ray, node->object->bounding_box, t)) { result_temp.intersected = - (*node->object->intersection_fn)(node->object, ray_trans, + (*node->object->intersection_fn)(node->object, ray, &result_temp.intersection); if (result_temp.intersected @@ -319,21 +313,6 @@ dmnsn_bvst_search_recursive(dmnsn_bvst_node *node, dmnsn_line ray, double t) result.intersected = true; result.intersection = result_temp.intersection; t = result.intersection.t; - - /* Transform the intersection back to the observer's view */ - result.intersection.ray = ray; - result.intersection.normal = dmnsn_vector_normalize( - dmnsn_vector_sub( - dmnsn_matrix_vector_mul( - node->object->trans, - result.intersection.normal - ), - dmnsn_matrix_vector_mul( - node->object->trans, - dmnsn_zero - ) - ) - ); } } diff --git a/libdimension/canvas_pigment.c b/libdimension/canvas_pigment.c index b4c6823..ad68fe1 100644 --- a/libdimension/canvas_pigment.c +++ b/libdimension/canvas_pigment.c @@ -40,6 +40,8 @@ dmnsn_new_canvas_pigment(dmnsn_canvas *canvas) static dmnsn_color dmnsn_canvas_pigment_fn(const dmnsn_pigment *pigment, dmnsn_vector v) { + v = dmnsn_matrix_vector_mul(pigment->trans_inv, v); + dmnsn_canvas *canvas = pigment->ptr; int x = v.x*(canvas->x - 1) + 0.5; diff --git a/libdimension/csg.c b/libdimension/csg.c index f5156f3..14f2980 100644 --- a/libdimension/csg.c +++ b/libdimension/csg.c @@ -36,25 +36,15 @@ dmnsn_csg_union_intersection_fn(const dmnsn_object *csg, dmnsn_line line, dmnsn_intersection *intersection) { - const dmnsn_object **params = csg->ptr; + dmnsn_line line_trans = dmnsn_matrix_line_mul(csg->trans_inv, line); - dmnsn_line line1 = dmnsn_matrix_line_mul(params[0]->trans_inv, line); - dmnsn_line line2 = dmnsn_matrix_line_mul(params[1]->trans_inv, line); + const dmnsn_object **params = csg->ptr; dmnsn_intersection i1, i2; - bool is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1); - bool is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2); + bool is_i1 = (*params[0]->intersection_fn)(params[0], line_trans, &i1); + bool is_i2 = (*params[1]->intersection_fn)(params[1], line_trans, &i2); if (is_i1) { - /* Transform the intersection back to the observer's view */ - i1.ray = line; - i1.normal = dmnsn_vector_normalize( - dmnsn_vector_sub( - dmnsn_matrix_vector_mul(params[0]->trans, i1.normal), - dmnsn_matrix_vector_mul(params[0]->trans, dmnsn_zero) - ) - ); - if (!i1.texture) i1.texture = csg->texture; if (!i1.interior) @@ -62,14 +52,6 @@ dmnsn_csg_union_intersection_fn(const dmnsn_object *csg, } if (is_i2) { - i2.ray = line; - i2.normal = dmnsn_vector_normalize( - dmnsn_vector_sub( - dmnsn_matrix_vector_mul(params[1]->trans, i2.normal), - dmnsn_matrix_vector_mul(params[1]->trans, dmnsn_zero) - ) - ); - if (!i2.texture) i2.texture = csg->texture; if (!i2.interior) @@ -87,6 +69,10 @@ dmnsn_csg_union_intersection_fn(const dmnsn_object *csg, } else { *intersection = i2; } + + intersection->ray = line; + intersection->normal = dmnsn_matrix_normal_mul(csg->trans, + intersection->normal); return true; } @@ -101,8 +87,8 @@ dmnsn_csg_union_inside_fn(const dmnsn_object *csg, dmnsn_vector point) dmnsn_object * dmnsn_new_csg_union(dmnsn_object *A, dmnsn_object *B) { - A->trans_inv = dmnsn_matrix_inverse(A->trans); - B->trans_inv = dmnsn_matrix_inverse(B->trans); + dmnsn_object_precompute(A); + dmnsn_object_precompute(B); dmnsn_object *csg = dmnsn_new_object(); @@ -115,12 +101,10 @@ dmnsn_new_csg_union(dmnsn_object *A, dmnsn_object *B) csg->inside_fn = &dmnsn_csg_union_inside_fn; csg->free_fn = &dmnsn_csg_free_fn; - dmnsn_bounding_box Abox - = dmnsn_matrix_bounding_box_mul(A->trans, A->bounding_box); - dmnsn_bounding_box Bbox - = dmnsn_matrix_bounding_box_mul(B->trans, B->bounding_box); - csg->bounding_box.min = dmnsn_vector_min(Abox.min, Bbox.min); - csg->bounding_box.max = dmnsn_vector_max(Abox.max, Bbox.max); + csg->bounding_box.min + = dmnsn_vector_min(A->bounding_box.min, B->bounding_box.min); + csg->bounding_box.max + = dmnsn_vector_max(A->bounding_box.max, B->bounding_box.max); return csg; } @@ -131,29 +115,22 @@ dmnsn_csg_intersection_fn(const dmnsn_object *csg, dmnsn_line line, dmnsn_intersection *intersection, bool inside1, bool inside2) { - /* inside1 is whether the first object is allowed inside the second object; + /* inside1 is whether the second object is allowed inside the first object; respectively for inside2 */ - const dmnsn_object **params = csg->ptr; + dmnsn_line line_trans = dmnsn_matrix_line_mul(csg->trans_inv, line); - dmnsn_line line1 = dmnsn_matrix_line_mul(params[0]->trans_inv, line); - dmnsn_line line2 = dmnsn_matrix_line_mul(params[1]->trans_inv, line); + const dmnsn_object **params = csg->ptr; dmnsn_intersection i1, i2; - bool is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1); - bool is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2); + bool is_i1 = (*params[0]->intersection_fn)(params[0], line_trans, &i1); + bool is_i2 = (*params[1]->intersection_fn)(params[1], line_trans, &i2); double oldt = 0.0; while (is_i1) { - i1.ray = line; + i1.ray = line_trans; i1.t += oldt; oldt = i1.t + dmnsn_epsilon; - i1.normal = dmnsn_vector_normalize( - dmnsn_vector_sub( - dmnsn_matrix_vector_mul(params[0]->trans, i1.normal), - dmnsn_matrix_vector_mul(params[0]->trans, dmnsn_zero) - ) - ); if (!i1.texture) i1.texture = csg->texture; @@ -161,11 +138,11 @@ dmnsn_csg_intersection_fn(const dmnsn_object *csg, dmnsn_line line, i1.interior = csg->interior; dmnsn_vector point = dmnsn_line_point(i1.ray, i1.t); - point = dmnsn_matrix_vector_mul(params[1]->trans_inv, point); - if (inside1 ^ (*params[1]->inside_fn)(params[1], point)) { - line1.x0 = dmnsn_line_point(line1, i1.t); - line1 = dmnsn_line_add_epsilon(line1); - is_i1 = (*params[0]->intersection_fn)(params[0], line1, &i1); + if (inside2 ^ (*params[1]->inside_fn)(params[1], point)) { + dmnsn_line newline = line_trans; + newline.x0 = dmnsn_line_point(line_trans, i1.t); + newline = dmnsn_line_add_epsilon(newline); + is_i1 = (*params[0]->intersection_fn)(params[0], newline, &i1); } else { break; } @@ -173,15 +150,9 @@ dmnsn_csg_intersection_fn(const dmnsn_object *csg, dmnsn_line line, oldt = 0.0; while (is_i2) { - i2.ray = line; + i2.ray = line_trans; i2.t += oldt; oldt = i2.t + dmnsn_epsilon; - i2.normal = dmnsn_vector_normalize( - dmnsn_vector_sub( - dmnsn_matrix_vector_mul(params[1]->trans, i2.normal), - dmnsn_matrix_vector_mul(params[1]->trans, dmnsn_zero) - ) - ); if (!i2.texture) i2.texture = csg->texture; @@ -189,11 +160,11 @@ dmnsn_csg_intersection_fn(const dmnsn_object *csg, dmnsn_line line, i2.interior = csg->interior; dmnsn_vector point = dmnsn_line_point(i2.ray, i2.t); - point = dmnsn_matrix_vector_mul(params[0]->trans_inv, point); - if (inside2 ^ (*params[0]->inside_fn)(params[0], point)) { - line2.x0 = dmnsn_line_point(line2, i2.t); - line2 = dmnsn_line_add_epsilon(line2); - is_i2 = (*params[1]->intersection_fn)(params[1], line2, &i2); + if (inside1 ^ (*params[0]->inside_fn)(params[0], point)) { + dmnsn_line newline = line_trans; + newline.x0 = dmnsn_line_point(line_trans, i2.t); + newline = dmnsn_line_add_epsilon(newline); + is_i2 = (*params[1]->intersection_fn)(params[1], newline, &i2); } else { break; } @@ -210,6 +181,10 @@ dmnsn_csg_intersection_fn(const dmnsn_object *csg, dmnsn_line line, } else { *intersection = i2; } + + intersection->ray = line; + intersection->normal = dmnsn_matrix_normal_mul(csg->trans, + intersection->normal); return true; } @@ -234,8 +209,8 @@ dmnsn_csg_intersection_inside_fn(const dmnsn_object *csg, dmnsn_vector point) dmnsn_object * dmnsn_new_csg_intersection(dmnsn_object *A, dmnsn_object *B) { - A->trans_inv = dmnsn_matrix_inverse(A->trans); - B->trans_inv = dmnsn_matrix_inverse(B->trans); + dmnsn_object_precompute(A); + dmnsn_object_precompute(B); dmnsn_object *csg = dmnsn_new_object(); @@ -248,12 +223,10 @@ dmnsn_new_csg_intersection(dmnsn_object *A, dmnsn_object *B) csg->inside_fn = &dmnsn_csg_intersection_inside_fn; csg->free_fn = &dmnsn_csg_free_fn; - dmnsn_bounding_box Abox - = dmnsn_matrix_bounding_box_mul(A->trans, A->bounding_box); - dmnsn_bounding_box Bbox - = dmnsn_matrix_bounding_box_mul(B->trans, B->bounding_box); - csg->bounding_box.min = dmnsn_vector_max(Abox.min, Bbox.min); - csg->bounding_box.max = dmnsn_vector_min(Abox.max, Bbox.max); + csg->bounding_box.min + = dmnsn_vector_max(A->bounding_box.min, B->bounding_box.min); + csg->bounding_box.max + = dmnsn_vector_min(A->bounding_box.max, B->bounding_box.max); return csg; } @@ -265,7 +238,7 @@ dmnsn_csg_difference_intersection_fn(const dmnsn_object *csg, dmnsn_line line, dmnsn_intersection *intersection) { - return dmnsn_csg_intersection_fn(csg, line, intersection, false, true); + return dmnsn_csg_intersection_fn(csg, line, intersection, true, false); } static bool @@ -279,8 +252,8 @@ dmnsn_csg_difference_inside_fn(const dmnsn_object *csg, dmnsn_vector point) dmnsn_object * dmnsn_new_csg_difference(dmnsn_object *A, dmnsn_object *B) { - A->trans_inv = dmnsn_matrix_inverse(A->trans); - B->trans_inv = dmnsn_matrix_inverse(B->trans); + dmnsn_object_precompute(A); + dmnsn_object_precompute(B); dmnsn_object *csg = dmnsn_new_object(); @@ -292,7 +265,7 @@ dmnsn_new_csg_difference(dmnsn_object *A, dmnsn_object *B) csg->intersection_fn = &dmnsn_csg_difference_intersection_fn; csg->inside_fn = &dmnsn_csg_difference_inside_fn; csg->free_fn = &dmnsn_csg_free_fn; - csg->bounding_box = dmnsn_matrix_bounding_box_mul(A->trans, A->bounding_box); + csg->bounding_box = A->bounding_box; return csg; } @@ -318,8 +291,8 @@ dmnsn_csg_merge_inside_fn(const dmnsn_object *csg, dmnsn_vector point) dmnsn_object * dmnsn_new_csg_merge(dmnsn_object *A, dmnsn_object *B) { - A->trans_inv = dmnsn_matrix_inverse(A->trans); - B->trans_inv = dmnsn_matrix_inverse(B->trans); + dmnsn_object_precompute(A); + dmnsn_object_precompute(B); dmnsn_object *csg = dmnsn_new_object(); @@ -332,12 +305,10 @@ dmnsn_new_csg_merge(dmnsn_object *A, dmnsn_object *B) csg->inside_fn = &dmnsn_csg_merge_inside_fn; csg->free_fn = &dmnsn_csg_free_fn; - dmnsn_bounding_box Abox - = dmnsn_matrix_bounding_box_mul(A->trans, A->bounding_box); - dmnsn_bounding_box Bbox - = dmnsn_matrix_bounding_box_mul(B->trans, B->bounding_box); - csg->bounding_box.min = dmnsn_vector_min(Abox.min, Bbox.min); - csg->bounding_box.max = dmnsn_vector_max(Abox.max, Bbox.max); + csg->bounding_box.min + = dmnsn_vector_min(A->bounding_box.min, B->bounding_box.min); + csg->bounding_box.max + = dmnsn_vector_max(A->bounding_box.max, B->bounding_box.max); return csg; } diff --git a/libdimension/cube.c b/libdimension/cube.c index 19c67b9..dfd1757 100644 --- a/libdimension/cube.c +++ b/libdimension/cube.c @@ -49,15 +49,17 @@ static bool dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line, dmnsn_intersection *intersection) { + dmnsn_line line_trans = dmnsn_matrix_line_mul(cube->trans_inv, line); + double t = -1.0, t_temp; dmnsn_vector p, normal; /* Six ray-plane intersection tests (x, y, z) = +/- 1.0 */ - if (line.n.x != 0.0) { + if (line_trans.n.x != 0.0) { /* x = -1.0 */ - t_temp = (-1.0 - line.x0.x)/line.n.x; - p = dmnsn_line_point(line, t_temp); + t_temp = (-1.0 - line_trans.x0.x)/line_trans.n.x; + p = dmnsn_line_point(line_trans, t_temp); if (p.y >= -1.0 && p.y <= 1.0 && p.z >= -1.0 && p.z <= 1.0 && t_temp >= 0.0 && (t < 0.0 || t_temp < t)) { @@ -66,8 +68,8 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line, } /* x = 1.0 */ - t_temp = (1.0 - line.x0.x)/line.n.x; - p = dmnsn_line_point(line, t_temp); + t_temp = (1.0 - line_trans.x0.x)/line_trans.n.x; + p = dmnsn_line_point(line_trans, t_temp); if (p.y >= -1.0 && p.y <= 1.0 && p.z >= -1.0 && p.z <= 1.0 && t_temp >= 0.0 && (t < 0.0 || t_temp < t)) { @@ -76,10 +78,10 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line, } } - if (line.n.y != 0.0) { + if (line_trans.n.y != 0.0) { /* y = -1.0 */ - t_temp = (-1.0 - line.x0.y)/line.n.y; - p = dmnsn_line_point(line, t_temp); + t_temp = (-1.0 - line_trans.x0.y)/line_trans.n.y; + p = dmnsn_line_point(line_trans, t_temp); if (p.x >= -1.0 && p.x <= 1.0 && p.z >= -1.0 && p.z <= 1.0 && t_temp >= 0.0 && (t < 0.0 || t_temp < t)) { @@ -88,8 +90,8 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line, } /* y = 1.0 */ - t_temp = (1.0 - line.x0.y)/line.n.y; - p = dmnsn_line_point(line, t_temp); + t_temp = (1.0 - line_trans.x0.y)/line_trans.n.y; + p = dmnsn_line_point(line_trans, t_temp); if (p.x >= -1.0 && p.x <= 1.0 && p.z >= -1.0 && p.z <= 1.0 && t_temp >= 0.0 && (t < 0.0 || t_temp < t)) { @@ -98,10 +100,10 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line, } } - if (line.n.z != 0.0) { + if (line_trans.n.z != 0.0) { /* z = -1.0 */ - t_temp = (-1.0 - line.x0.z)/line.n.z; - p = dmnsn_line_point(line, t_temp); + t_temp = (-1.0 - line_trans.x0.z)/line_trans.n.z; + p = dmnsn_line_point(line_trans, t_temp); if (p.x >= -1.0 && p.x <= 1.0 && p.y >= -1.0 && p.y <= 1.0 && t_temp >= 0.0 && (t < 0.0 || t_temp < t)) { @@ -110,8 +112,8 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line, } /* z = 1.0 */ - t_temp = (1.0 - line.x0.z)/line.n.z; - p = dmnsn_line_point(line, t_temp); + t_temp = (1.0 - line_trans.x0.z)/line_trans.n.z; + p = dmnsn_line_point(line_trans, t_temp); if (p.x >= -1.0 && p.x <= 1.0 && p.y >= -1.0 && p.y <= 1.0 && t_temp >= 0.0 && (t < 0.0 || t_temp < t)) { @@ -123,7 +125,7 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line, if (t >= 0.0) { intersection->ray = line; intersection->t = t; - intersection->normal = normal; + intersection->normal = dmnsn_matrix_normal_mul(cube->trans, normal); intersection->texture = cube->texture; intersection->interior = cube->interior; return true; @@ -136,6 +138,7 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line, static bool dmnsn_cube_inside_fn(const dmnsn_object *cube, dmnsn_vector point) { + point = dmnsn_matrix_vector_mul(cube->trans_inv, point); return point.x > -1.0 && point.x < 1.0 && point.y > -1.0 && point.y < 1.0 && point.z > -1.0 && point.z < 1.0; diff --git a/libdimension/dimension/object.h b/libdimension/dimension/object.h index f0395cd..1d5f580 100644 --- a/libdimension/dimension/object.h +++ b/libdimension/dimension/object.h @@ -41,6 +41,8 @@ typedef struct dmnsn_intersection { const dmnsn_interior *interior; } dmnsn_intersection; +dmnsn_vector dmnsn_matrix_normal_mul(dmnsn_matrix trans, dmnsn_vector normal); + /* Forward-declare dmnsn_object */ typedef struct dmnsn_object dmnsn_object; @@ -80,4 +82,6 @@ dmnsn_object *dmnsn_new_object(); /* Free an object */ void dmnsn_delete_object(dmnsn_object *object); +void dmnsn_object_precompute(dmnsn_object *object); + #endif /* DIMENSION_OBJECT_H */ diff --git a/libdimension/dimension/texture.h b/libdimension/dimension/texture.h index 70cfdc5..91dda23 100644 --- a/libdimension/dimension/texture.h +++ b/libdimension/dimension/texture.h @@ -42,6 +42,9 @@ struct dmnsn_pigment { dmnsn_pigment_fn *pigment_fn; dmnsn_free_fn *free_fn; + /* Transformation matrix */ + dmnsn_matrix trans, trans_inv; + /* Generic pointer */ void *ptr; }; @@ -49,6 +52,8 @@ struct dmnsn_pigment { dmnsn_pigment *dmnsn_new_pigment(); void dmnsn_delete_pigment(dmnsn_pigment *pigment); +void dmnsn_pigment_precompute(dmnsn_pigment *pigment); + /* * Finishes */ @@ -91,11 +96,17 @@ void dmnsn_delete_finish(dmnsn_finish *finish); */ typedef struct { + /* Texture components */ dmnsn_pigment *pigment; dmnsn_finish *finish; + + /* Transformation matrix */ + dmnsn_matrix trans, trans_inv; } dmnsn_texture; dmnsn_texture *dmnsn_new_texture(); void dmnsn_delete_texture(dmnsn_texture *texture); +void dmnsn_texture_precompute(dmnsn_texture *texture); + #endif /* DIMENSION_TEXTURE_H */ diff --git a/libdimension/object.c b/libdimension/object.c index 890d0e0..3cf68c7 100644 --- a/libdimension/object.c +++ b/libdimension/object.c @@ -20,6 +20,17 @@ #include "dimension.h" +dmnsn_vector +dmnsn_matrix_normal_mul(dmnsn_matrix trans, dmnsn_vector normal) +{ + return dmnsn_vector_normalize( + dmnsn_vector_sub( + dmnsn_matrix_vector_mul(trans, normal), + dmnsn_matrix_vector_mul(trans, dmnsn_zero) + ) + ); +} + /* Allocate a dummy object */ dmnsn_object * dmnsn_new_object() @@ -45,3 +56,17 @@ dmnsn_delete_object(dmnsn_object *object) free(object); } } + +/* Precompute object properties */ +void +dmnsn_object_precompute(dmnsn_object *object) +{ + object->bounding_box + = dmnsn_matrix_bounding_box_mul(object->trans, object->bounding_box); + object->trans_inv = dmnsn_matrix_inverse(object->trans); + if (object->texture) { + object->texture->trans + = dmnsn_matrix_mul(object->trans, object->texture->trans); + dmnsn_texture_precompute(object->texture); + } +} diff --git a/libdimension/sphere.c b/libdimension/sphere.c index 09b6767..94ae44e 100644 --- a/libdimension/sphere.c +++ b/libdimension/sphere.c @@ -19,7 +19,7 @@ *************************************************************************/ #include "dimension.h" -#include /* For sqrt */ +#include /* For sqrt */ /* * Sphere @@ -50,13 +50,13 @@ static bool dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line line, dmnsn_intersection *intersection) { - double a, b, c, t; - + dmnsn_line l = dmnsn_matrix_line_mul(sphere->trans_inv, line); + /* Solve (x0 + nx*t)^2 + (y0 + ny*t)^2 + (z0 + nz*t)^2 == 1 */ - - a = line.n.x*line.n.x + line.n.y*line.n.y + line.n.z*line.n.z; - b = 2.0*(line.n.x*line.x0.x + line.n.y*line.x0.y + line.n.z*line.x0.z); - c = line.x0.x*line.x0.x + line.x0.y*line.x0.y + line.x0.z*line.x0.z - 1.0; + double a, b, c, t; + a = l.n.x*l.n.x + l.n.y*l.n.y + l.n.z*l.n.z; + b = 2.0*(l.n.x*l.x0.x + l.n.y*l.x0.y + l.n.z*l.x0.z); + c = l.x0.x*l.x0.x + l.x0.y*l.x0.y + l.x0.z*l.x0.z - 1.0; if (b*b - 4.0*a*c >= 0) { t = (-b - sqrt(b*b - 4.0*a*c))/(2*a); @@ -67,7 +67,8 @@ dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line line, if (t >= 0.0) { intersection->ray = line; intersection->t = t; - intersection->normal = dmnsn_line_point(line, t); + intersection->normal = dmnsn_matrix_normal_mul(sphere->trans, + dmnsn_line_point(l, t)); intersection->texture = sphere->texture; intersection->interior = sphere->interior; return true; @@ -81,5 +82,6 @@ dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line line, static bool dmnsn_sphere_inside_fn(const dmnsn_object *sphere, dmnsn_vector point) { + point = dmnsn_matrix_vector_mul(sphere->trans_inv, point); return point.x*point.x + point.y*point.y + point.z*point.z < 1.0; } diff --git a/libdimension/texture.c b/libdimension/texture.c index e08d595..d1047b7 100644 --- a/libdimension/texture.c +++ b/libdimension/texture.c @@ -26,6 +26,7 @@ dmnsn_new_pigment() { dmnsn_pigment *pigment = dmnsn_malloc(sizeof(dmnsn_pigment)); pigment->free_fn = NULL; + pigment->trans = dmnsn_identity_matrix(); return pigment; } @@ -41,6 +42,13 @@ dmnsn_delete_pigment(dmnsn_pigment *pigment) } } +/* Precompute pigment properties */ +void +dmnsn_pigment_precompute(dmnsn_pigment *pigment) +{ + pigment->trans_inv = dmnsn_matrix_inverse(pigment->trans); +} + /* Allocate a dummy finish */ dmnsn_finish * dmnsn_new_finish() @@ -73,6 +81,7 @@ dmnsn_new_texture() dmnsn_texture *texture = dmnsn_malloc(sizeof(dmnsn_texture)); texture->pigment = NULL; texture->finish = NULL; + texture->trans = dmnsn_identity_matrix(); return texture; } @@ -86,3 +95,15 @@ dmnsn_delete_texture(dmnsn_texture *texture) free(texture); } } + +/* Calculate matrix inverses */ +void +dmnsn_texture_precompute(dmnsn_texture *texture) +{ + texture->trans_inv = dmnsn_matrix_inverse(texture->trans); + if (texture->pigment) { + texture->pigment->trans + = dmnsn_matrix_mul(texture->trans, texture->pigment->trans); + dmnsn_pigment_precompute(texture->pigment); + } +} -- cgit v1.2.3