From 285f5bec5bb03d4e825e5d866e94008088dd6155 Mon Sep 17 00:00:00 2001 From: xleroy Date: Sat, 9 Aug 2008 08:06:33 +0000 Subject: Ajout nouveaux tests git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@708 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e --- test/raytracer/simplify.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 test/raytracer/simplify.c (limited to 'test/raytracer/simplify.c') diff --git a/test/raytracer/simplify.c b/test/raytracer/simplify.c new file mode 100644 index 00000000..7a4a5457 --- /dev/null +++ b/test/raytracer/simplify.c @@ -0,0 +1,177 @@ +#include "config.h" +#include "point.h" +#include "vector.h" +#include "arrays.h" +#include "matrix.h" +#include "eval.h" +#include "object.h" +#include "simplify.h" + +#define INFINITE_RADIUS 1e300 + +static flt cone_radius = 1.0; +static flt cube_radius = 0.86602540378443859659; /* sqrt(3)/2 */ +static flt cylinder_radius = 1.11803398874989490253; /* sqrt(5)/2 */ +static flt sphere_radius = 1.0; + +static struct point cone_center = { 0.0, 1.0, 0.0 }; +static struct point cube_center = { 0.5, 0.5, 0.5 }; +static struct point cylinder_center = { 0.0, 0.5, 0.0 }; +static struct point sphere_center = { 0, 0, 0 }; +static struct point plane_center = { 0, 0, 0 }; + +static struct point origin = { 0, 0, 0 }; + +static inline void set_infinite(struct object * t) +{ + t->radius = INFINITE_RADIUS; +} + +static inline void union_bs(struct object * t1, struct object * t2, + struct object * obj) +{ + struct vector c1c2; + flt dd2, rr, rr2, d, alpha; + + if (t1->radius >= INFINITE_RADIUS || t2->radius >= INFINITE_RADIUS) { + obj->radius = INFINITE_RADIUS; + return; + } + between(&t1->center, &t2->center, &c1c2); + dd2 = vlength2(&c1c2); + rr = t2->radius - t1->radius; + rr2 = rr * rr; + if (dd2 <= rr2) { + /* take the biggest sphere */ + if (t1->radius <= t2->radius) { + ASSIGN(obj->center, t2->center); + obj->radius = t2->radius; + set_infinite(t2); + } else { + ASSIGN(obj->center, t1->center); + obj->radius = t1->radius; + set_infinite(t1); + } + return; + } + d = sqrt(dd2); + alpha = rr / (2 * d) + 0.5; + point_along(&t1->center, &c1c2, alpha, &obj->center); + obj->radius = (d + t1->radius + t2->radius) / 2; +} + +static inline void intersection_bs(struct object * t1, struct object * t2, + struct object * obj) +{ + struct vector c1c2; + flt dd2, rr, rr2, rpr, rpr2, diff, d, te1, te2, te3, te4, te, alpha; + + if (t1->radius >= INFINITE_RADIUS) { + ASSIGN(obj->center, t2->center); + obj->radius = t2->radius; + return; + } + if (t2->radius >= INFINITE_RADIUS) { + ASSIGN(obj->center, t1->center); + obj->radius = t1->radius; + return; + } + between(&t1->center, &t2->center, &c1c2); + dd2 = vlength2(&c1c2); + rr = t1->radius - t2->radius; + rr2 = rr * rr; + if (dd2 <= rr2) { + /* take the smallest sphere */ + if (t2->radius <= t1->radius) { + ASSIGN(obj->center, t2->center); + obj->radius = t2->radius; + set_infinite(t2); + } else { + ASSIGN(obj->center, t1->center); + obj->radius = t1->radius; + set_infinite(t1); + } + return; + } + rpr = t1->radius + t2->radius; + rpr2 = rpr * rpr; + if (dd2 > rpr2) { + ASSIGN(obj->center, origin); + obj->radius = 0.0; + return; + } + diff = t1->radius * t1->radius - t2->radius * t2->radius; + if (dd2 <= diff) { + ASSIGN(obj->center, t2->center); + obj->radius = t2->radius; + set_infinite(t2); + return; + } + if (dd2 <= -diff) { + ASSIGN(obj->center, t1->center); + obj->radius = t1->radius; + set_infinite(t1); + return; + } + d = sqrt(dd2); + te1 = t1->radius + d + t2->radius; + te2 = t1->radius + d - t2->radius; + te3 = t2->radius + d - t1->radius; + te4 = t1->radius + t2->radius - d; + te = (sqrt (te1 * te2 * te3 * te4)) / (2 * d); + alpha = + (t1->radius * t1->radius - t2->radius * t2->radius) / (2 * dd2) + 0.5; + point_along(&t1->center, &c1c2, alpha, &obj->center); + obj->radius = te; +} + +static inline void difference_bs(struct object * t1, struct object * t2, + struct object * obj) +{ + ASSIGN(obj->center, t1->center); + obj->radius = t1->radius; + set_infinite(t1); +} + +void compute_bounding_spheres(struct object * obj) +{ + if (obj->radius >= 0.0) return; /* already computed */ + switch (obj->kind) { + case Cone: + apply_to_point(obj->obj2world, &cone_center, &obj->center); + obj->radius = obj->max_scale_applied * cone_radius; + break; + case Cube: + apply_to_point(obj->obj2world, &cube_center, &obj->center); + obj->radius = obj->max_scale_applied * cube_radius; + break; + case Cylinder: + apply_to_point(obj->obj2world, &cylinder_center, &obj->center); + obj->radius = obj->max_scale_applied * cylinder_radius; + break; + case Plane: + ASSIGN(obj->center, plane_center); + obj->radius = INFINITE_RADIUS; + break; + case Sphere: + apply_to_point(obj->obj2world, &sphere_center, &obj->center); + obj->radius = obj->max_scale_applied * sphere_radius; + break; + case Union: + compute_bounding_spheres(obj->o1); + compute_bounding_spheres(obj->o2); + union_bs(obj->o1, obj->o2, obj); + break; + case Intersection: + compute_bounding_spheres(obj->o1); + compute_bounding_spheres(obj->o2); + intersection_bs(obj->o1, obj->o2, obj); + break; + case Difference: + compute_bounding_spheres(obj->o1); + compute_bounding_spheres(obj->o2); + difference_bs(obj->o1, obj->o2, obj); + break; + } +} + -- cgit