commit 34db303d59561b6aa251b7ddf6908c6fa7cb6f60
parent 7baa0b0ab07f6c844f3c4344585efbc338171c9e
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 5 Oct 2015 17:04:03 +0200
Add and test the s3d_scene_get_aabb function
Return the Axis Aligned Bounding Box of a scene.
Diffstat:
8 files changed, 138 insertions(+), 10 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -57,7 +57,7 @@ rcmake_append_runtime_dirs(_runtime_dirs RSys Embree)
# Configure and define targets
################################################################################
set(VERSION_MAJOR 0)
-set(VERSION_MINOR 2)
+set(VERSION_MINOR 3)
set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
diff --git a/src/s3d.h b/src/s3d.h
@@ -336,6 +336,14 @@ s3d_scene_compute_volume
(struct s3d_scene* scn,
float* volume);
+/* Retrieve the Axis Aligned Bounding Box of the scene. Can be called only if a
+ * session is active on `scn' */
+S3D_API res_T
+s3d_scene_get_aabb
+ (struct s3d_scene* scn,
+ float lower[3], /* AABB lower bound */
+ float upper[3]); /* AABB upper bound */
+
/*******************************************************************************
* Shape API - A shape defines a geometry that can be attached to *one* scene.
******************************************************************************/
diff --git a/src/s3d_mesh.c b/src/s3d_mesh.c
@@ -454,6 +454,7 @@ mesh_setup_indexed_vertices
unsigned iattr;
char has_position = 0;
res_T res = RES_OK;
+ ASSERT(mesh);
if(!ntris || !nverts || !attribs) {
res = RES_BAD_ARG;
@@ -523,3 +524,24 @@ error:
goto exit;
}
+void
+mesh_compute_aabb(struct mesh* mesh, float lower[3], float upper[3])
+{
+ float* pos;
+ size_t ivert, nverts;
+ ASSERT(mesh && lower && upper);
+
+ f3_splat(lower, FLT_MAX);
+ f3_splat(upper,-FLT_MAX);
+
+ nverts = mesh_get_nverts(mesh);
+ if(!nverts) return;
+
+ pos = mesh_get_pos(mesh);
+ FOR_EACH(ivert, 0, nverts) {
+ const size_t ipos = ivert * 3;
+ f3_min(lower, lower, pos + ipos);
+ f3_max(upper, upper, pos + ipos);
+ }
+}
+
diff --git a/src/s3d_mesh.h b/src/s3d_mesh.h
@@ -130,5 +130,11 @@ mesh_setup_indexed_vertices
struct s3d_vertex_data attribs[],
void* data);
+extern LOCAL_SYM void
+mesh_compute_aabb
+ (struct mesh* mesh,
+ float lower[3],
+ float upper[3]);
+
#endif /* S3D_MESH_H */
diff --git a/src/s3d_scene.c b/src/s3d_scene.c
@@ -393,6 +393,45 @@ error:
goto exit;
}
+static void
+scene_compute_aabb(struct s3d_scene* scn)
+{
+ struct list_node* node;
+ struct s3d_shape* shape;
+ struct geometry** pgeom;
+ struct geometry* geom;
+ struct instance* inst;
+ float lower[3], upper[3];
+
+ f3_splat(scn->lower, FLT_MAX);
+ f3_splat(scn->upper,-FLT_MAX);
+
+ LIST_FOR_EACH(node, &scn->shapes) {
+ shape = CONTAINER_OF(node, struct s3d_shape, scene_attachment);
+ pgeom = htable_geom_find(&scn->cached_geoms, &shape);
+ ASSERT(pgeom != NULL);
+ geom = *pgeom;
+
+ if(!geom->is_enabled) continue;
+
+ switch(geom->type) {
+ case GEOM_MESH: mesh_compute_aabb(geom->data.mesh, lower, upper); break;
+ case GEOM_INSTANCE:
+ inst = geom->data.instance;
+ scene_compute_aabb(inst->scene);
+ /* Transform local scene AABB in world space */
+ f33_mulf3(lower, inst->transform, inst->scene->lower);
+ f33_mulf3(upper, inst->transform, inst->scene->upper);
+ f3_add(lower, inst->transform + 9, lower);
+ f3_add(upper, inst->transform + 9, upper);
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ f3_min(scn->lower, scn->lower, lower);
+ f3_max(scn->upper, scn->upper, upper);
+ }
+}
+
static FINLINE bool
operator < (const struct fltui& it, const float val)
{
@@ -530,6 +569,8 @@ scene_sync(struct s3d_scene* scn, const int session_mask)
}
scn->session_mask = session_mask;
+ scene_compute_aabb(scn);
+
exit:
return res;
error:
@@ -593,6 +634,9 @@ s3d_scene_create(struct s3d_device* dev, struct s3d_scene** out_scn)
/* Commit empty scene => the scene can be ray traced without any build */
rtcCommit(scn->rtc_scn);
+ f3_splat(scn->lower, FLT_MAX);
+ f3_splat(scn->upper,-FLT_MAX);
+
exit:
if(out_scn) *out_scn = scn;
return res;
@@ -1212,5 +1256,15 @@ exit:
return res;
error:
goto exit;
+}
+res_T
+s3d_scene_get_aabb(struct s3d_scene* scn, float lower[3], float upper[3])
+{
+ if(!scn || !lower || !upper) return RES_BAD_ARG;
+ if(!scn->session_mask) return RES_BAD_OP;
+ f3_set(lower, scn->lower);
+ f3_set(upper, scn->upper);
+ return RES_OK;
}
+
diff --git a/src/s3d_scene_c.h b/src/s3d_scene_c.h
@@ -81,6 +81,8 @@ struct s3d_scene {
struct darray_fltui cdf; /* Unormalized CDF */
struct darray_nprims_cdf nprims_cdf;
+ float lower[3], upper[3]; /* AABB of the scene */
+
size_t instances_count; /* # instances in the scene */
RTCScene rtc_scn; /* Embree scene */
diff --git a/src/test_s3d_scene.c b/src/test_s3d_scene.c
@@ -98,7 +98,7 @@ main(int argc, char** argv)
void* data = (void*)&cbox_walls_desc;
size_t i;
size_t nprims;
- float area, volume;
+ float area, volume, lower[3], upper[3];
unsigned id;
int mask;
(void)argc, (void)argv;
@@ -159,7 +159,7 @@ main(int argc, char** argv)
CHECK(s3d_scene_attach_shape(scn, shapes[0]), RES_OK);
CHECK(s3d_scene_begin_session(NULL, 0), RES_BAD_ARG);
CHECK(s3d_scene_begin_session(scn, 0), RES_BAD_ARG);
- CHECK(s3d_scene_begin_session(scn, S3D_TRACE), RES_OK);
+ CHECK(s3d_scene_begin_session(scn, S3D_TRACE|S3D_GET_PRIMITIVE), RES_OK);
CHECK(s3d_scene_begin_session(scn, S3D_TRACE), RES_BAD_OP);
CHECK(s3d_scene_get_session_mask(scn, &mask), RES_OK);
@@ -186,16 +186,36 @@ main(int argc, char** argv)
CHECK(s3d_scene_compute_area(scn2, &area), RES_OK);
CHECK(area, 0.f);
+ CHECK(s3d_scene_compute_volume(NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_compute_volume(scn2, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_compute_volume(NULL, &volume), RES_BAD_ARG);
+ CHECK(s3d_scene_compute_volume(scn2, &volume), RES_OK);
+ CHECK(volume, 0.f);
+
CHECK(s3d_scene_primitives_count(NULL, NULL), RES_BAD_ARG);
CHECK(s3d_scene_primitives_count(scn2, NULL), RES_BAD_ARG);
CHECK(s3d_scene_primitives_count(NULL, &nprims), RES_BAD_ARG);
CHECK(s3d_scene_primitives_count(scn2, &nprims), RES_OK);
CHECK(nprims, 0);
+ CHECK(s3d_scene_get_aabb(NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_get_aabb(scn2, NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_get_aabb(NULL, lower, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_get_aabb(scn2, lower, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_get_aabb(NULL, NULL, upper), RES_BAD_ARG);
+ CHECK(s3d_scene_get_aabb(scn2, NULL, upper), RES_BAD_ARG);
+ CHECK(s3d_scene_get_aabb(NULL, lower, upper), RES_BAD_ARG);
+ CHECK(s3d_scene_get_aabb(scn2, lower, upper), RES_OK);
+ CHECK(lower[0] > upper[0], 1);
+ CHECK(lower[1] > upper[1], 1);
+ CHECK(lower[2] > upper[2], 1);
+
CHECK(s3d_scene_end_session(scn2), RES_OK);
CHECK(s3d_scene_compute_area(scn2, &area), RES_BAD_OP);
+ CHECK(s3d_scene_compute_volume(scn2, &volume), RES_BAD_OP);
CHECK(s3d_scene_primitives_count(scn2, &nprims), RES_BAD_OP);
+ CHECK(s3d_scene_get_aabb(scn2, lower, upper), RES_BAD_OP);
CHECK(s3d_scene_instantiate(scn2, shapes + 3), RES_OK);
CHECK(s3d_scene_attach_shape(scn3, shapes[3]), RES_OK);
@@ -233,13 +253,13 @@ main(int argc, char** argv)
CHECK(eq_epsf(area, 1532296.f, 1.e-6f), 1);
CHECK(s3d_scene_primitives_count(scn, &nprims), RES_OK);
CHECK(nprims, 10);
- CHECK(s3d_scene_end_session(scn), RES_OK);
-
- CHECK(s3d_scene_begin_session(scn, S3D_TRACE), RES_OK);
- CHECK(s3d_scene_compute_area(scn, &area), RES_OK);
- CHECK(eq_epsf(area, 1532296.f, 1.e-6f), 1);
- CHECK(s3d_scene_primitives_count(scn, &nprims), RES_OK);
- CHECK(nprims, 10);
+ CHECK(s3d_scene_get_aabb(scn, lower, upper), RES_OK);
+ CHECK(eq_epsf(lower[0], 0.f, 1.e-6f), 1);
+ CHECK(eq_epsf(lower[1], 0.f, 1.e-6f), 1);
+ CHECK(eq_epsf(lower[2], 0.f, 1.e-6f), 1);
+ CHECK(eq_epsf(upper[0], 552.f, 1.e-6f), 1);
+ CHECK(eq_epsf(upper[1], 559.f, 1.e-6f), 1);
+ CHECK(eq_epsf(upper[2], 548.f, 1.e-6f), 1);
CHECK(s3d_scene_end_session(scn), RES_OK);
CHECK(s3d_scene_instantiate(scn, shapes + 1), RES_OK);
@@ -250,6 +270,13 @@ main(int argc, char** argv)
CHECK(eq_epsf(area, 1532296.f, 1.e-6f), 1);
CHECK(s3d_scene_primitives_count(scn, &nprims), RES_OK);
CHECK(nprims, 10);
+ CHECK(s3d_scene_get_aabb(scn, lower, upper), RES_OK);
+ CHECK(eq_epsf(lower[0], 0.f, 1.e-6f), 1);
+ CHECK(eq_epsf(lower[1], 0.f, 1.e-6f), 1);
+ CHECK(eq_epsf(lower[2], 0.f, 1.e-6f), 1);
+ CHECK(eq_epsf(upper[0], 552.f, 1.e-6f), 1);
+ CHECK(eq_epsf(upper[1], 559.f, 1.e-6f), 1);
+ CHECK(eq_epsf(upper[2], 548.f, 1.e-6f), 1);
CHECK(s3d_scene_end_session(scn2), RES_OK);
CHECK(s3d_scene_begin_session(scn2, S3D_GET_PRIMITIVE), RES_OK);
diff --git a/src/test_s3d_trace_ray.c b/src/test_s3d_trace_ray.c
@@ -101,6 +101,7 @@ main(int argc, char** argv)
unsigned ntris, nverts;
size_t nprims;
size_t ix, iy;
+ float lower[3], upper[3];
float org[3] = { 0.f, 0.f, 0.f };
float dir[3] = { 0.f, 1.f, 0.f };
float range[2] = { 0.f, FLT_MAX };
@@ -257,6 +258,14 @@ main(int argc, char** argv)
CHECK(s3d_scene_primitives_count(scn2, &nprims), RES_OK);
CHECK(nprims, 30);
+ CHECK(s3d_scene_get_aabb(scn2, lower, upper), RES_OK);
+ CHECK(eq_epsf(lower[0], -100.f, 1.e-6f), 1);
+ CHECK(eq_epsf(lower[1], 0.f, 1.e-6f), 1);
+ CHECK(eq_epsf(lower[2], -2.f, 1.e-6f), 1);
+ CHECK(eq_epsf(upper[0], 452.f, 1.e-6f), 1);
+ CHECK(eq_epsf(upper[1], 559.f, 1.e-6f), 1);
+ CHECK(eq_epsf(upper[2], 546.f, 1.e-6f), 1);
+
FOR_EACH(i, 0, nprims) {
size_t j;
CHECK(s3d_scene_get_primitive(scn2, (unsigned)i, prims + i), RES_OK);