star-3d

Surface structuring for efficient 3D geometric queries
git clone git://git.meso-star.fr/star-3d.git
Log | Files | Refs | README | LICENSE

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:
Mcmake/CMakeLists.txt | 2+-
Msrc/s3d.h | 8++++++++
Msrc/s3d_mesh.c | 22++++++++++++++++++++++
Msrc/s3d_mesh.h | 6++++++
Msrc/s3d_scene.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/s3d_scene_c.h | 2++
Msrc/test_s3d_scene.c | 45++++++++++++++++++++++++++++++++++++---------
Msrc/test_s3d_trace_ray.c | 9+++++++++
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);