summaryrefslogtreecommitdiffstats
path: root/libdimension
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2011-07-26 09:20:06 -0600
committerTavian Barnes <tavianator@gmail.com>2011-07-26 09:21:23 -0600
commit5f8ce1e256462a9addbe318966a70a4bc6399bad (patch)
tree148cc13bb63691d056d82424435df5347d809331 /libdimension
parente683539695c720e559139ffd58e1786fbb1ea06c (diff)
downloaddimension-5f8ce1e256462a9addbe318966a70a4bc6399bad.tar.xz
Support multiple texture assignment properly.
Diffstat (limited to 'libdimension')
-rw-r--r--libdimension/cone.c14
-rw-r--r--libdimension/cube.c7
-rw-r--r--libdimension/dimension/object.h21
-rw-r--r--libdimension/object.c16
-rw-r--r--libdimension/plane.c7
-rw-r--r--libdimension/raytrace.c62
-rw-r--r--libdimension/sphere.c7
-rw-r--r--libdimension/torus.c8
-rw-r--r--libdimension/triangle.c7
9 files changed, 80 insertions, 69 deletions
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 <stdbool.h>
+/* 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;
}