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 9f0d3be7042c3d74306d64e9d1581e3bc607dee7
parent 1014b516425347daf33c0e11aecc262336e076e6
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed,  9 Sep 2015 11:43:30 +0200

Replace <begin|end>_trace by <begin|end>_session

Diffstat:
Msrc/s3d.h | 29+++++++++++++++++------------
Msrc/s3d_scene.c | 123+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/s3d_scene_c.h | 14++++----------
Msrc/test_s3d_scene.c | 34++++++++++++++++++----------------
Msrc/test_s3d_trace_ray.c | 26+++++++++++++-------------
5 files changed, 112 insertions(+), 114 deletions(-)

diff --git a/src/s3d.h b/src/s3d.h @@ -155,6 +155,12 @@ static const struct s3d_hit S3D_HIT_NULL = FLT_MAX }; +enum s3d_session_flag { + S3D_SESSION_NONE = 0, + S3D_SESSION_TRACE = BIT(0), + S3D_SESSION_SAMPLE = BIT(1) +}; + /* Helper macro that defines whether or not the hit is valid, i.e. the ray * intersects a shape or not */ #define S3D_HIT_NONE(Hit) ((Hit)->distance >= FLT_MAX) @@ -243,26 +249,25 @@ s3d_scene_clear (struct s3d_scene* scn); /* Synchronize the scene geometry with the geometry of its attached shapes. If - * a s3d_scene_begin_trace is already active on `scn' or one of its attached + * a s3d_scene_begin_session is already active on `scn' or one of its attached * instance a RES_BAD_OP error is returned. On success neither another begin - * trace nor a clear or shape_detach can be invoked on `scn' and its attached - * instances until s3d_scene_end_trace is called. A s3d_scene_trace_ray - * operation can be invoked on `scn' only between a s3d_scene_begin_trace and - * s3d_scene_end_trace call. */ + * session nor a clear or shape_detach can be invoked on `scn' and its attached + * instances until s3d_scene_end_session is called. A s3d_scene_trace_ray + * operation can be invoked on if a S3D_SESSION_TRACE session is active on scn*/ S3D_API res_T -s3d_scene_begin_trace - (struct s3d_scene* scn); +s3d_scene_begin_session + (struct s3d_scene* scn, + const int session_mask); /* Combination of s3d_session_flag */ -/* End the trace operation on the `scn' */ +/* End the session on the `scn' */ S3D_API res_T -s3d_scene_end_trace +s3d_scene_end_session (struct s3d_scene* scn); -/* Define if the begin scene is currently invoked on `scn' */ S3D_API res_T -s3d_scene_is_traceable +s3d_scene_get_session_mask (struct s3d_scene* scn, - char* is_traceable); + int* mask); /* Trace a ray into the `scn' and return the closest intersection. The ray is * defined by `origin' + t*`direction' = 0 with t in [`range[0]', `range[1]'). diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -40,13 +40,16 @@ #include <rsys/mem_allocator.h> #include <rsys/mutex.h> +/* Flag used to define session of enabled on instantiated scene */ +#define S3D_SESSION_INSTANCE (BIT(sizeof(int)*8 - 1)) + /******************************************************************************* * Helper functions ******************************************************************************/ static res_T -scene_build +scene_sync (struct s3d_scene* scn, - const enum build_type type); + const int mask);/* combination of s3d_session_flag & S3D_SESSION_INSTANCE */ static INLINE void scene_geometry_flush_enable_state @@ -68,43 +71,26 @@ scene_geometry_flush_enable_state } static res_T -scene_build_register_mesh(struct s3d_scene* scn, struct geometry* geom) +scene_register_embree_geometry(struct s3d_scene* scn, struct geometry* geom) { - ASSERT(scn && geom && geom->type == GEOM_MESH); + ASSERT(scn && geom && (geom->type==GEOM_MESH || geom->type==GEOM_INSTANCE)); + /* Create the Embree geometry if it is not valid */ if(geom->irtc == RTC_INVALID_GEOMETRY_ID) { - geom->irtc = rtcNewTriangleMesh(scn->rtc_scn, RTC_GEOMETRY_DYNAMIC, - mesh_get_ntris(geom->data.mesh), mesh_get_nverts(geom->data.mesh)); - if(geom->irtc == RTC_INVALID_GEOMETRY_ID) - return RES_UNKNOWN_ERR; - scn->is_rtc_scn_outdated = 1; - } - - if(geom->irtc >= darray_geom_size_get(&scn->embree2geoms)) { - res_T res = darray_geom_resize(&scn->embree2geoms, geom->irtc + 1); - if(res != RES_OK) { - rtcDeleteGeometry(scn->rtc_scn, geom->irtc); - geom->irtc = RTC_INVALID_GEOMETRY_ID; - return res; + switch(geom->type) { + case GEOM_MESH: + geom->irtc = rtcNewTriangleMesh(scn->rtc_scn, RTC_GEOMETRY_DYNAMIC, + mesh_get_ntris(geom->data.mesh), mesh_get_nverts(geom->data.mesh)); + break; + case GEOM_INSTANCE: + geom->irtc = rtcNewInstance + (scn->rtc_scn, geom->data.instance->scene->rtc_scn); + break; + default: FATAL("Unreachable code\n"); break; } - } - geometry_ref_get(geom); - darray_geom_data_get(&scn->embree2geoms)[geom->irtc] = geom; - return RES_OK; -} - -static res_T -scene_build_register_instance(struct s3d_scene* scn, struct geometry* geom) -{ - ASSERT(scn && geom && geom->data.instance->scene && geom->type==GEOM_INSTANCE); - /* The instance should not contain instances, i.e. one instancing level is - * supported */ - ASSERT(geom->data.instance->scene->instances_count == 0); - - if(geom->irtc == RTC_INVALID_GEOMETRY_ID) { - geom->irtc = rtcNewInstance(scn->rtc_scn, geom->data.instance->scene->rtc_scn); if(geom->irtc == RTC_INVALID_GEOMETRY_ID) return RES_UNKNOWN_ERR; + scn->is_rtc_scn_outdated = 1; } @@ -122,7 +108,7 @@ scene_build_register_instance(struct s3d_scene* scn, struct geometry* geom) } static void -scene_build_clear(struct s3d_scene* scn) +scene_session_clear(struct s3d_scene* scn) { struct geometry** geoms; size_t ngeoms; @@ -135,18 +121,19 @@ scene_build_clear(struct s3d_scene* scn) if(!geoms[i]) continue; if(geoms[i]->type == GEOM_INSTANCE) - scene_build_clear(geoms[i]->data.instance->scene); + scene_session_clear(geoms[i]->data.instance->scene); geometry_ref_put(geoms[i]); } darray_geom_clear(&scn->embree2geoms); - scn->build_type = BUILD_NONE; + scn->session_mask = S3D_SESSION_NONE; } static res_T -scene_setup_shape_mesh +scene_register_mesh (struct s3d_scene* scn, - struct s3d_shape* shape) + struct s3d_shape* shape, + const int session_mask) { struct geometry** pgeom = NULL; struct geometry* geom = NULL; @@ -226,7 +213,7 @@ scene_setup_shape_mesh /* Update the cached mesh states */ geom->flip_surface = shape->flip_surface; - res = scene_build_register_mesh(scn, geom); + res = scene_register_embree_geometry(scn, geom); if(res != RES_OK) goto error; if(upd_pos) { /* Update the Embree vertex buffer if necessary */ @@ -255,7 +242,10 @@ error: } static res_T -scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) +scene_register_instance + (struct s3d_scene* scn, + struct s3d_shape* shape, + const int session_mask) { struct geometry** pgeom = NULL; struct geometry* geom = NULL; @@ -263,7 +253,8 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) ASSERT(scn && shape && shape->type == GEOM_INSTANCE); /* Recursuvely update the scene */ - res = scene_build(shape->data.instance->scene, BUILD_INDIRECT); + res = scene_sync(shape->data.instance->scene, + session_mask|S3D_SESSION_INSTANCE); if(res != RES_OK) goto error; pgeom = htable_geom_find(&scn->cached_geoms, &shape); @@ -294,7 +285,7 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) } /* Create the Embree instance */ - res = scene_build_register_instance(scn, geom); + res = scene_register_embree_geometry(scn, geom); if(res != RES_OK) goto error; /* Update the Embree instance transformation */ @@ -344,13 +335,13 @@ scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape) } static res_T -scene_build(struct s3d_scene* scn, const enum build_type type) +scene_sync(struct s3d_scene* scn, const int session_mask) { struct list_node* node; res_T res = RES_OK; - ASSERT(scn && (type == BUILD_DIRECT || type == BUILD_INDIRECT)); + ASSERT(scn); - if(scn->build_type != BUILD_NONE) { + if(scn->session_mask != S3D_SESSION_NONE) { res = RES_BAD_OP; goto error; } @@ -359,8 +350,12 @@ scene_build(struct s3d_scene* scn, const enum build_type type) struct s3d_shape* shape = CONTAINER_OF (node, struct s3d_shape, scene_attachment); switch(shape->type) { - case GEOM_INSTANCE: res = scene_setup_shape_instance(scn, shape); break; - case GEOM_MESH: res = scene_setup_shape_mesh(scn, shape); break; + case GEOM_INSTANCE: + res = scene_register_instance(scn, shape, session_mask); + break; + case GEOM_MESH: + res = scene_register_mesh(scn, shape, session_mask); + break; default: FATAL("Unreachable code\n"); break; } if(res != RES_OK) @@ -370,8 +365,7 @@ scene_build(struct s3d_scene* scn, const enum build_type type) rtcCommit(scn->rtc_scn); scn->is_rtc_scn_outdated = 0; } - - scn->build_type = type; + scn->session_mask = session_mask; exit: return res; @@ -388,7 +382,7 @@ scene_release(ref_T* ref) scn = CONTAINER_OF(ref, struct s3d_scene, ref); S3D(scene_clear(scn)); dev = scn->dev; - scene_build_clear(scn); + scene_session_clear(scn); if(scn->rtc_scn) rtcDeleteScene(scn->rtc_scn); htable_geom_release(&scn->cached_geoms); darray_geom_release(&scn->embree2geoms); @@ -421,7 +415,7 @@ s3d_scene_create(struct s3d_device* dev, struct s3d_scene** out_scn) ref_init(&scn->ref); S3D(device_ref_get(dev)); scn->dev = dev; - scn->build_type = BUILD_NONE; + scn->session_mask = S3D_SESSION_NONE; scn->rtc_scn = rtcNewScene (RTC_SCENE_DYNAMIC | RTC_SCENE_INCOHERENT | RTC_SCENE_ROBUST, RTC_INTERSECT1 | RTC_INTERSECT4); @@ -510,7 +504,7 @@ s3d_scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape) { char is_attached; if(!scn || !shape) return RES_BAD_ARG; - if(scn->build_type != BUILD_NONE) return RES_BAD_OP; + if(scn->session_mask != S3D_SESSION_NONE) return RES_BAD_OP; if(!(S3D(shape_is_attached(shape, &is_attached)), is_attached)) return RES_BAD_ARG; #ifndef NDEBUG @@ -533,7 +527,7 @@ s3d_scene_clear(struct s3d_scene* scn) { struct list_node* node, *tmp; if(!scn) return RES_BAD_ARG; - if(scn->build_type != BUILD_NONE) return RES_BAD_OP; + if(scn->session_mask != S3D_SESSION_NONE) return RES_BAD_OP; LIST_FOR_EACH_SAFE(node, tmp, &scn->shapes) { struct s3d_shape* shape = CONTAINER_OF (node, struct s3d_shape, scene_attachment); @@ -543,29 +537,32 @@ s3d_scene_clear(struct s3d_scene* scn) } res_T -s3d_scene_begin_trace(struct s3d_scene* scn) +s3d_scene_begin_session(struct s3d_scene* scn, const int session_mask) { - if(!scn) return RES_BAD_ARG; - return scene_build(scn, BUILD_DIRECT); + if(!scn) + return RES_BAD_ARG; + if(!(session_mask&S3D_SESSION_TRACE) && !(session_mask&S3D_SESSION_SAMPLE)) + return RES_BAD_ARG; + return scene_sync(scn, session_mask); } res_T -s3d_scene_end_trace(struct s3d_scene* scn) +s3d_scene_end_session(struct s3d_scene* scn) { if(!scn) return RES_BAD_ARG; - if(scn->build_type != BUILD_DIRECT) + if(scn->session_mask & S3D_SESSION_INSTANCE || !scn->session_mask) return RES_BAD_OP; - scene_build_clear(scn); + scene_session_clear(scn); return RES_OK; } res_T -s3d_scene_is_traceable(struct s3d_scene* scn, char* is_traceable) +s3d_scene_get_session_mask(struct s3d_scene* scn, int* session_mask) { - if(!scn || !is_traceable) + if(!scn || !session_mask) return RES_BAD_ARG; - *is_traceable = scn->build_type != BUILD_NONE; + *session_mask = scn->session_mask & (~S3D_SESSION_INSTANCE); return RES_OK; } @@ -582,7 +579,7 @@ s3d_scene_trace_ray return RES_BAD_ARG; if(!f3_is_normalized(dir)) return RES_BAD_ARG; - if(scn->build_type == BUILD_NONE) + if(scn->session_mask == S3D_SESSION_NONE) return RES_BAD_OP; if(range[0] > range[1]) { *hit = S3D_HIT_NULL; diff --git a/src/s3d_scene_c.h b/src/s3d_scene_c.h @@ -62,23 +62,17 @@ geom_ptr_init__(struct mem_allocator* alloc, struct geometry** geom) #define HTABLE_KEY struct s3d_shape* #include <rsys/hash_table.h> -enum build_type { - BUILD_NONE, /* The scene is not built */ - BUILD_DIRECT, /* The scene is directly build */ - BUILD_INDIRECT /* The scene is build as an instance */ -}; - struct s3d_scene { struct list_node shapes; /* List of attached shapes */ struct htable_geom cached_geoms; /* Cached shape geometries */ struct darray_geom embree2geoms; /* Shape geometries index by embree id */ - size_t instances_count; /* # instances int the scene */ + size_t instances_count; /* # instances in the scene */ - RTCScene rtc_scn; - char is_rtc_scn_outdated; + RTCScene rtc_scn; /* Embree scene */ + char is_rtc_scn_outdated; /* Must the embree scene rebuild */ - enum build_type build_type; + int session_mask; /* Combination of enum s3d_session_flag */ struct s3d_device* dev; ref_T ref; diff --git a/src/test_s3d_scene.c b/src/test_s3d_scene.c @@ -43,7 +43,7 @@ main(int argc, char** argv) const size_t nshapes = sizeof(shapes)/sizeof(struct s3d_shape*); size_t i; unsigned id; - char b; + int mask; (void)argc, (void)argv; mem_init_proxy_allocator(&allocator, &mem_default_allocator); @@ -90,29 +90,31 @@ main(int argc, char** argv) CHECK(s3d_scene_clear(scn), RES_OK); CHECK(s3d_scene_instantiate(scn, shapes + 2), RES_OK); - CHECK(s3d_scene_is_traceable(NULL, NULL), RES_BAD_ARG); - CHECK(s3d_scene_is_traceable(scn, NULL), RES_BAD_ARG); - CHECK(s3d_scene_is_traceable(NULL, &b), RES_BAD_ARG); - CHECK(s3d_scene_is_traceable(scn, &b), RES_OK); - CHECK(b, 0); + CHECK(s3d_scene_get_session_mask(NULL, NULL), RES_BAD_ARG); + CHECK(s3d_scene_get_session_mask(scn, NULL), RES_BAD_ARG); + CHECK(s3d_scene_get_session_mask(NULL, &mask), RES_BAD_ARG); + CHECK(s3d_scene_get_session_mask(scn, &mask), RES_OK); + CHECK(mask, S3D_SESSION_NONE); CHECK(s3d_scene_attach_shape(scn, shapes[0]), RES_OK); - CHECK(s3d_scene_begin_trace(NULL), RES_BAD_ARG); - CHECK(s3d_scene_begin_trace(scn), RES_OK); - CHECK(s3d_scene_begin_trace(scn), RES_BAD_OP); + 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_SESSION_TRACE), RES_OK); + CHECK(s3d_scene_begin_session(scn, S3D_SESSION_TRACE), RES_BAD_OP); - CHECK(s3d_scene_is_traceable(scn, &b), RES_OK); - CHECK(b, 1); + CHECK(s3d_scene_get_session_mask(scn, &mask), RES_OK); + CHECK(mask & S3D_SESSION_TRACE, S3D_SESSION_TRACE); + CHECK(mask & S3D_SESSION_SAMPLE, 0); CHECK(s3d_scene_clear(scn), RES_BAD_OP); CHECK(s3d_scene_detach_shape(scn, shapes[0]), RES_BAD_OP); - CHECK(s3d_scene_end_trace(NULL), RES_BAD_ARG); - CHECK(s3d_scene_end_trace(scn), RES_OK); - CHECK(s3d_scene_end_trace(scn), RES_BAD_OP); + CHECK(s3d_scene_end_session(NULL), RES_BAD_ARG); + CHECK(s3d_scene_end_session(scn), RES_OK); + CHECK(s3d_scene_end_session(scn), RES_BAD_OP); - CHECK(s3d_scene_is_traceable(scn, &b), RES_OK); - CHECK(b, 0); + CHECK(s3d_scene_get_session_mask(scn, &mask), RES_OK); + CHECK(mask, 0); CHECK(s3d_scene_detach_shape(scn, shapes[0]), RES_OK); diff --git a/src/test_s3d_trace_ray.c b/src/test_s3d_trace_ray.c @@ -133,7 +133,7 @@ main(int argc, char** argv) CHECK(s3d_scene_attach_shape(scn, walls), RES_OK); CHECK(s3d_shape_ref_put(walls), RES_OK); - CHECK(s3d_scene_begin_trace(scn), RES_OK); + CHECK(s3d_scene_begin_session(scn, S3D_SESSION_TRACE), RES_OK); CHECK(s3d_scene_trace_ray(NULL, NULL, NULL, NULL, NULL), RES_BAD_ARG); CHECK(s3d_scene_trace_ray(scn, NULL, NULL, NULL, NULL), RES_BAD_ARG); CHECK(s3d_scene_trace_ray(NULL, org, NULL, NULL, NULL), RES_BAD_ARG); @@ -169,7 +169,7 @@ main(int argc, char** argv) CHECK(s3d_scene_trace_ray(scn, org, dir, range, &hit), RES_OK); f3(dir, 1.f, 1.f, 1.f); CHECK(s3d_scene_trace_ray(scn, org, dir, range, &hit), RES_BAD_ARG); - CHECK(s3d_scene_end_trace(scn), RES_OK); + CHECK(s3d_scene_end_session(scn), RES_OK); f3(dir, 0.f, 1.f, 0.f); CHECK(s3d_scene_trace_ray(scn, org, dir, range, &hit), RES_BAD_OP); @@ -237,27 +237,27 @@ main(int argc, char** argv) CHECK(s3d_shape_enable(inst, 0), RES_OK); - CHECK(s3d_scene_begin_trace(scn), RES_OK); - CHECK(s3d_scene_begin_trace(scn2), RES_BAD_OP); - CHECK(s3d_scene_end_trace(scn), RES_OK); - CHECK(s3d_scene_begin_trace(scn2), RES_OK); - CHECK(s3d_scene_begin_trace(scn), RES_BAD_OP); - CHECK(s3d_scene_end_trace(scn), RES_BAD_OP); + CHECK(s3d_scene_begin_session(scn, S3D_SESSION_TRACE), RES_OK); + CHECK(s3d_scene_begin_session(scn2, S3D_SESSION_TRACE), RES_BAD_OP); + CHECK(s3d_scene_end_session(scn), RES_OK); + CHECK(s3d_scene_begin_session(scn2, S3D_SESSION_TRACE), RES_OK); + CHECK(s3d_scene_begin_session(scn, S3D_SESSION_TRACE), RES_BAD_OP); + CHECK(s3d_scene_end_session(scn), RES_BAD_OP); CHECK(s3d_scene_clear(scn2), RES_BAD_OP); CHECK(s3d_scene_clear(scn), RES_BAD_OP); - CHECK(s3d_scene_end_trace(scn2), RES_OK); + CHECK(s3d_scene_end_session(scn2), RES_OK); CHECK(s3d_shape_enable(inst, 1), RES_OK); - CHECK(s3d_scene_begin_trace(scn2), RES_OK); - CHECK(s3d_scene_end_trace(scn2), RES_OK); + CHECK(s3d_scene_begin_session(scn2, S3D_SESSION_TRACE), RES_OK); + CHECK(s3d_scene_end_session(scn2), RES_OK); CHECK(s3d_scene_clear(scn), RES_OK); CHECK(s3d_scene_attach_shape(scn, walls), RES_OK); CHECK(s3d_scene_attach_shape(scn, short_block), RES_OK); CHECK(s3d_scene_attach_shape(scn, tall_block), RES_OK); - CHECK(s3d_scene_begin_trace(scn2), RES_OK); + CHECK(s3d_scene_begin_session(scn2, S3D_SESSION_TRACE), RES_OK); camera_init(&cam); FOR_EACH(iy, 0, IMG_HEIGHT) { @@ -325,7 +325,7 @@ main(int argc, char** argv) } } } - CHECK(s3d_scene_end_trace(scn2), RES_OK); + CHECK(s3d_scene_end_session(scn2), RES_OK); if(argc > 1) { CHECK(image_ppm_write(argv[1], IMG_WIDTH, IMG_HEIGHT, 3, img), RES_OK);