From 5f8ce1e256462a9addbe318966a70a4bc6399bad Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 26 Jul 2011 09:20:06 -0600 Subject: Support multiple texture assignment properly. --- libdimension/cone.c | 14 +++------- libdimension/cube.c | 7 ++--- libdimension/dimension/object.h | 21 ++++++++------ libdimension/object.c | 16 +++++++++-- libdimension/plane.c | 7 ++--- libdimension/raytrace.c | 62 ++++++++++++++++++++++++++--------------- libdimension/sphere.c | 7 ++--- libdimension/torus.c | 8 ++---- libdimension/triangle.c | 7 ++--- 9 files changed, 80 insertions(+), 69 deletions(-) (limited to 'libdimension') diff --git a/libdimension/cone.c b/libdimension/cone.c index 87f1fde..9f7a8fc 100644 --- a/libdimension/cone.c +++ b/libdimension/cone.c @@ -101,11 +101,8 @@ dmnsn_cone_intersection_fn(const dmnsn_object *cone, dmnsn_line l, && (tcap < t || p.y <= -1.0 || p.y >= 1.0) && pcap.x*pcap.x + pcap.z*pcap.z < r*r) { - intersection->ray = l; - intersection->t = tcap; - intersection->normal = norm; - intersection->texture = cone->texture; - intersection->interior = cone->interior; + intersection->t = tcap; + intersection->normal = norm; return true; } } @@ -114,11 +111,8 @@ dmnsn_cone_intersection_fn(const dmnsn_object *cone, dmnsn_line l, dmnsn_vector norm = dmnsn_vector_normalized( dmnsn_new_vector(p.x, -(r2 - r1)*sqrt(p.x*p.x + p.z*p.z)/2.0, p.z) ); - intersection->ray = l; - intersection->t = t; - intersection->normal = norm; - intersection->texture = cone->texture; - intersection->interior = cone->interior; + intersection->t = t; + intersection->normal = norm; return true; } } diff --git a/libdimension/cube.c b/libdimension/cube.c index 98e7345..b127557 100644 --- a/libdimension/cube.c +++ b/libdimension/cube.c @@ -112,11 +112,8 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line, } if (tmin >= 0.0) { - intersection->ray = line; - intersection->t = tmin; - intersection->normal = nmin; - intersection->texture = cube->texture; - intersection->interior = cube->interior; + intersection->t = tmin; + intersection->normal = nmin; return true; } else { return false; diff --git a/libdimension/dimension/object.h b/libdimension/dimension/object.h index 24e1bcb..673c8bc 100644 --- a/libdimension/dimension/object.h +++ b/libdimension/dimension/object.h @@ -25,6 +25,9 @@ #include +/* Forward-declare dmnsn_object */ +typedef struct dmnsn_object dmnsn_object; + /** A type to represent a ray-object intersection. */ typedef struct dmnsn_intersection { dmnsn_line ray; /**< The ray that intersected. */ @@ -33,15 +36,10 @@ typedef struct dmnsn_intersection { /** The surface normal at the intersection point. */ dmnsn_vector normal; - /** The texture at the intersection point. */ - const dmnsn_texture *texture; - /** The interior at the intersection point. */ - const dmnsn_interior *interior; + /** The object of intersection. */ + const dmnsn_object *object; } dmnsn_intersection; -/* Forward-declare dmnsn_object */ -typedef struct dmnsn_object dmnsn_object; - /** * Object initialization callback. * @param[in,out] object The object to initialize. @@ -74,8 +72,10 @@ struct dmnsn_object { dmnsn_texture *texture; /**< Surface properties. */ dmnsn_interior *interior; /**< Interior properties. */ - dmnsn_matrix trans; /**< Transformation matrix. */ + dmnsn_matrix trans; /**< Transformation matrix. */ dmnsn_matrix trans_inv; /**< Inverse of the transformation matrix. */ + dmnsn_matrix intrinsic_trans; /**< Transformations not affecting the texture. */ + dmnsn_matrix pigment_trans; /**< Inverse transformation for the texture. */ dmnsn_bounding_box bounding_box; /**< Object bounding box. */ @@ -141,11 +141,16 @@ dmnsn_object_intersection(const dmnsn_object *object, dmnsn_line line, dmnsn_intersection *intersection) { dmnsn_line line_trans = dmnsn_transform_line(object->trans_inv, 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); + if (!intersection->object) { + intersection->object = object; + } + return true; } else { return false; diff --git a/libdimension/object.c b/libdimension/object.c index bb7773d..7736880 100644 --- a/libdimension/object.c +++ b/libdimension/object.c @@ -34,6 +34,7 @@ dmnsn_new_object(void) object->texture = NULL; object->interior = NULL; object->trans = dmnsn_identity_matrix(); + object->intrinsic_trans = dmnsn_identity_matrix(); object->children = dmnsn_new_array(sizeof(dmnsn_object *)); object->split_children = false; object->intersection_fn = NULL; @@ -72,17 +73,26 @@ dmnsn_initialize_object(dmnsn_object *object) /* Initialize the texture */ if (!object->texture->initialized) { - object->texture->trans = dmnsn_matrix_mul(object->trans, - object->texture->trans); dmnsn_initialize_texture(object->texture); } + /* Precalculate object values */ + object->pigment_trans = dmnsn_matrix_inverse(object->trans); + object->trans = dmnsn_matrix_mul(object->trans, object->intrinsic_trans); + /* Initialize the object's children */ DMNSN_ARRAY_FOREACH (dmnsn_object **, child, object->children) { (*child)->trans = dmnsn_matrix_mul(object->trans, (*child)->trans); + bool pigment_cascaded = + (*child)->texture == NULL || (*child)->texture->pigment == NULL; + dmnsn_texture_cascade(object->texture, &(*child)->texture); dmnsn_interior_cascade(object->interior, &(*child)->interior); dmnsn_initialize_object(*child); + + if (pigment_cascaded) { + (*child)->pigment_trans = object->pigment_trans; + } } /* Initialization callback */ @@ -90,7 +100,7 @@ dmnsn_initialize_object(dmnsn_object *object) object->initialize_fn(object); } - /* Precalculate object values */ + /* Precalculate more object values */ object->bounding_box = dmnsn_transform_bounding_box(object->trans, object->bounding_box); object->trans_inv = dmnsn_matrix_inverse(object->trans); diff --git a/libdimension/plane.c b/libdimension/plane.c index 8931cc7..e79e003 100644 --- a/libdimension/plane.c +++ b/libdimension/plane.c @@ -63,11 +63,8 @@ dmnsn_plane_intersection_fn(const dmnsn_object *plane, dmnsn_line line, if (den != 0.0) { double t = -dmnsn_vector_dot(line.x0, *normal)/den; if (t >= 0.0) { - intersection->ray = line; - intersection->t = t; - intersection->normal = *normal; - intersection->texture = plane->texture; - intersection->interior = plane->interior; + intersection->t = t; + intersection->normal = *normal; return true; } } diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c index 5d62738..06878fd 100644 --- a/libdimension/raytrace.c +++ b/libdimension/raytrace.c @@ -109,10 +109,13 @@ typedef struct dmnsn_raytrace_state { const dmnsn_scene *scene; const dmnsn_intersection *intersection; + const dmnsn_texture *texture; + const dmnsn_interior *interior; const dmnsn_prtree *prtree; unsigned int reclevel; dmnsn_vector r; + dmnsn_vector pigment_r; dmnsn_vector viewer; dmnsn_vector reflected; dmnsn_vector light; @@ -126,6 +129,35 @@ typedef struct dmnsn_raytrace_state { dmnsn_color adc_value; } dmnsn_raytrace_state; +/** Compute a raytrace state from an intersection. */ +static inline void +dmnsn_initialize_raytrace_state(dmnsn_raytrace_state *state, + const dmnsn_intersection *intersection) +{ + state->intersection = intersection; + state->texture = intersection->object->texture; + state->interior = intersection->object->interior; + + state->r = dmnsn_line_point(intersection->ray, intersection->t); + state->pigment_r = dmnsn_transform_vector( + intersection->object->pigment_trans, + state->r + ); + state->viewer = dmnsn_vector_normalized( + dmnsn_vector_negate(intersection->ray.n) + ); + state->reflected = dmnsn_vector_sub( + dmnsn_vector_mul( + 2*dmnsn_vector_dot(state->viewer, intersection->normal), + intersection->normal), + state->viewer + ); + + state->pigment = dmnsn_black; + state->diffuse = dmnsn_black; + state->additional = dmnsn_black; +} + /** Main helper for dmnsn_raytrace_scene_impl - shoot a ray. */ static dmnsn_color dmnsn_raytrace_shoot(dmnsn_raytrace_state *state, dmnsn_line ray); @@ -191,9 +223,9 @@ dmnsn_raytrace_background(dmnsn_raytrace_state *state, dmnsn_line ray) static void dmnsn_raytrace_pigment(dmnsn_raytrace_state *state) { - dmnsn_pigment *pigment = state->intersection->texture->pigment; + dmnsn_pigment *pigment = state->texture->pigment; if (state->scene->quality & DMNSN_RENDER_PIGMENT) { - state->pigment = dmnsn_evaluate_pigment(pigment, state->r); + state->pigment = dmnsn_evaluate_pigment(pigment, state->pigment_r); } else { state->pigment = pigment->quick_color; } @@ -231,8 +263,7 @@ dmnsn_raytrace_light_ray(dmnsn_raytrace_state *state, } dmnsn_raytrace_state shadow_state = *state; - shadow_state.intersection = &shadow_caster; - shadow_state.reclevel = reclevel; + dmnsn_initialize_raytrace_state(&shadow_state, &shadow_caster); dmnsn_raytrace_pigment(&shadow_state); if ((state->scene->quality & DMNSN_RENDER_TRANSLUCENCY) @@ -261,7 +292,7 @@ dmnsn_raytrace_lighting(dmnsn_raytrace_state *state) /* The ambient color */ state->diffuse = dmnsn_black; - const dmnsn_finish *finish = &state->intersection->texture->finish; + const dmnsn_finish *finish = &state->texture->finish; if (finish->ambient) { state->diffuse = finish->ambient->ambient_fn(finish->ambient, state->pigment); @@ -306,7 +337,7 @@ dmnsn_raytrace_reflection(const dmnsn_raytrace_state *state) { dmnsn_color reflected = dmnsn_black; - const dmnsn_finish *finish = &state->intersection->texture->finish; + const dmnsn_finish *finish = &state->texture->finish; if (finish->reflection) { dmnsn_line refl_ray = dmnsn_new_line(state->r, state->reflected); refl_ray = dmnsn_line_add_epsilon(refl_ray); @@ -344,7 +375,7 @@ dmnsn_raytrace_translucency(dmnsn_raytrace_state *state) if (dmnsn_vector_dot(r, n) < 0.0) { /* We are entering an object */ - recursive_state.ior = state->intersection->interior->ior; + recursive_state.ior = state->interior->ior; recursive_state.parent = state; } else { /* We are leaving an object */ @@ -403,22 +434,7 @@ dmnsn_raytrace_shoot(dmnsn_raytrace_state *state, dmnsn_line ray) dmnsn_intersection intersection; bool reset = state->reclevel == state->scene->reclimit - 1; if (dmnsn_prtree_intersection(state->prtree, ray, &intersection, reset)) { - state->intersection = &intersection; - - state->r = dmnsn_line_point(intersection.ray, intersection.t); - state->viewer = dmnsn_vector_normalized( - dmnsn_vector_negate(intersection.ray.n) - ); - state->reflected = dmnsn_vector_sub( - dmnsn_vector_mul( - 2*dmnsn_vector_dot(state->viewer, intersection.normal), - intersection.normal), - state->viewer - ); - - state->pigment = dmnsn_black; - state->diffuse = dmnsn_black; - state->additional = dmnsn_black; + dmnsn_initialize_raytrace_state(state, &intersection); /* Pigment */ dmnsn_raytrace_pigment(state); diff --git a/libdimension/sphere.c b/libdimension/sphere.c index 5d937bd..c0f0fe4 100644 --- a/libdimension/sphere.c +++ b/libdimension/sphere.c @@ -44,11 +44,8 @@ dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line l, if (n == 2) t = dmnsn_min(t, x[1]); - intersection->ray = l; - intersection->t = t; - intersection->normal = dmnsn_line_point(l, t); - intersection->texture = sphere->texture; - intersection->interior = sphere->interior; + intersection->t = t; + intersection->normal = dmnsn_line_point(l, t); return true; } } diff --git a/libdimension/torus.c b/libdimension/torus.c index 9eb2323..be96743 100644 --- a/libdimension/torus.c +++ b/libdimension/torus.c @@ -123,11 +123,9 @@ dmnsn_torus_intersection_fn(const dmnsn_object *torus, dmnsn_line l, dmnsn_vector_normalized(dmnsn_new_vector(p.x, 0.0, p.z)) ); dmnsn_vector normal = dmnsn_vector_normalized(dmnsn_vector_sub(p, center)); - intersection->ray = l; - intersection->t = t; - intersection->normal = normal; - intersection->texture = torus->texture; - intersection->interior = torus->interior; + + intersection->t = t; + intersection->normal = normal; return true; } diff --git a/libdimension/triangle.c b/libdimension/triangle.c index bd54e1a..72cbce3 100644 --- a/libdimension/triangle.c +++ b/libdimension/triangle.c @@ -42,11 +42,8 @@ dmnsn_triangle_intersection_fn(const dmnsn_object *triangle, dmnsn_line l, double u = -dmnsn_vector_dot(l.n, dmnsn_vector_cross(ax0, payload->ac))/den; 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->ray = l; - intersection->t = t; - intersection->normal = payload->normal; - intersection->texture = triangle->texture; - intersection->interior = triangle->interior; + intersection->t = t; + intersection->normal = payload->normal; return true; } -- cgit v1.2.3