summaryrefslogtreecommitdiff
path: root/test/raytracer/simplify.c
diff options
context:
space:
mode:
authorGravatar xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e>2008-08-09 08:06:33 +0000
committerGravatar xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e>2008-08-09 08:06:33 +0000
commit285f5bec5bb03d4e825e5d866e94008088dd6155 (patch)
tree9df69ded9ed4f4049e0b3887fdd99fcdf3b1746f /test/raytracer/simplify.c
parenta83f0c1710cc5143dd885e84c94e14f7d3216f93 (diff)
Ajout nouveaux tests
git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@708 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
Diffstat (limited to 'test/raytracer/simplify.c')
-rw-r--r--test/raytracer/simplify.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/test/raytracer/simplify.c b/test/raytracer/simplify.c
new file mode 100644
index 0000000..7a4a545
--- /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;
+ }
+}
+