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 969bbf55d3833753fbdd4d9dc62641d66015b3eb
parent 3446ed1eb3fd3f8ce1966c0f169847416afd5843
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 27 Mar 2015 12:21:15 +0100

Add and test the s3d_scene_<begin|end>_trace functions

Diffstat:
Msrc/s3d.h | 14+++++++++++---
Msrc/s3d_scene.c | 90++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/s3d_scene_c.h | 8++++++++
Msrc/test_s3d_scene.c | 9+++++++--
Msrc/test_s3d_trace_ray.c | 18+++++++++++++++---
5 files changed, 103 insertions(+), 36 deletions(-)

diff --git a/src/s3d.h b/src/s3d.h @@ -212,10 +212,18 @@ s3d_scene_clear (struct s3d_scene* scn); /* Synchronize the scene geometry with the geometry of its attached shapes. If - * one is tracing rays into the scene, it waits for the end of the ray-tracing - * to effectively update the scene representation */ + * a s3d_scene_begin_trace call is currently active on an attached instance a + * RES_BAD_OP error is returned. On success no other begin trace can be invoked + * on `scn' and its 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. */ S3D_API res_T -s3d_scene_build +s3d_scene_begin_trace + (struct s3d_scene* scn); + +/* End the trace operation on the scene */ +S3D_API res_T +s3d_scene_end_trace (struct s3d_scene* scn); /* Trace a ray into the scene and return the closest intersection. The ray is diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -44,6 +44,11 @@ * Helper functions ******************************************************************************/ static res_T +scene_build + (struct s3d_scene* scn, + const enum build_type type); + +static res_T scene_build_register_mesh(struct s3d_scene* scn, struct mesh* mesh) { ASSERT(scn && mesh); @@ -113,9 +118,15 @@ scene_build_clear(struct s3d_scene* scn) ninstances = darray_geom2inst_size_get(&scn->geom2inst); instances = darray_geom2inst_data_get(&scn->geom2inst); - FOR_EACH(i, 0, ninstances) if(instances[i]) instance_ref_put(instances[i]); + FOR_EACH(i, 0, ninstances) { + if(instances[i]) { + scene_build_clear(instances[i]->scene); + instance_ref_put(instances[i]); + } + } darray_geom2inst_clear(&scn->geom2inst); scn->is_rtc_scn_outdated = 0; + scn->build_type = BUILD_NONE; } static res_T @@ -229,7 +240,7 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) ASSERT(scn && shape && shape->type == SHAPE_INSTANCE); /* Recursuvely update the scene */ - res = s3d_scene_build(shape->data.instance->scene); + res = scene_build(shape->data.instance->scene, BUILD_INDIRECT); if(res != RES_OK) goto error; pinst = htable_inst_find(&scn->instances, &shape); @@ -328,6 +339,40 @@ 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) +{ + struct list_node* node; + res_T res = RES_OK; + ASSERT(scn && (type == BUILD_DIRECT || type == BUILD_INDIRECT)); + + if(scn->build_type != BUILD_NONE) { + res = RES_BAD_OP; + goto error; + } + + LIST_FOR_EACH(node, &scn->shapes) { + struct s3d_shape* shape = CONTAINER_OF + (node, struct s3d_shape, scene_attachment); + switch(shape->type) { + case SHAPE_INSTANCE: res = scene_setup_shape_instance(scn, shape); break; + case SHAPE_MESH: res = scene_setup_shape_mesh(scn, shape); break; + default: FATAL("Unreachable code\n"); break; + } + if(res != RES_OK) + goto error; + } + if(scn->is_rtc_scn_outdated) + rtcCommit(scn->rtc_scn); + + scn->build_type = type; + +exit: + return res; +error: + goto exit; +} + static void scene_release(ref_T* ref) { @@ -374,6 +419,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->rtc_scn = rtcNewScene (RTC_SCENE_DYNAMIC | RTC_SCENE_INCOHERENT | RTC_SCENE_ROBUST, RTC_INTERSECT1 | RTC_INTERSECT4); @@ -493,35 +539,21 @@ s3d_scene_clear(struct s3d_scene* scn) } res_T -s3d_scene_build(struct s3d_scene* scn) +s3d_scene_begin_trace(struct s3d_scene* scn) { - struct list_node* node; - res_T res = RES_OK; - - if(!scn) { - res = RES_BAD_ARG; - goto error; - } + if(!scn) return RES_BAD_ARG; + return scene_build(scn, BUILD_DIRECT); +} +res_T +s3d_scene_end_trace(struct s3d_scene* scn) +{ + if(!scn) + return RES_BAD_ARG; + if(scn->build_type != BUILD_DIRECT) + return RES_BAD_OP; scene_build_clear(scn); - LIST_FOR_EACH(node, &scn->shapes) { - struct s3d_shape* shape = CONTAINER_OF - (node, struct s3d_shape, scene_attachment); - switch(shape->type) { - case SHAPE_INSTANCE: res = scene_setup_shape_instance(scn, shape); break; - case SHAPE_MESH: res = scene_setup_shape_mesh(scn, shape); break; - default: FATAL("Unreachable code\n"); break; - } - if(res != RES_OK) - goto error; - } - if(scn->is_rtc_scn_outdated) - rtcCommit(scn->rtc_scn); - -exit: - return res; -error: - goto exit; + return RES_OK; } res_T @@ -537,6 +569,8 @@ s3d_scene_trace_ray return RES_BAD_ARG; if(!f3_is_normalized(dir)) return RES_BAD_ARG; + if(scn->build_type == BUILD_NONE) + return RES_BAD_OP; if(range[0] > range[1]) { *hit = S3D_HIT_NULL; return RES_OK; diff --git a/src/s3d_scene_c.h b/src/s3d_scene_c.h @@ -58,6 +58,12 @@ #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_mesh meshes; /* List of meshes associated to a shape */ @@ -67,6 +73,8 @@ struct s3d_scene { RTCScene rtc_scn; char is_rtc_scn_outdated; + enum build_type build_type; + struct s3d_device* dev; ref_T ref; }; diff --git a/src/test_s3d_scene.c b/src/test_s3d_scene.c @@ -82,8 +82,13 @@ main(int argc, char** argv) CHECK(s3d_scene_clear(scn), RES_OK); CHECK(s3d_scene_instantiate(scn, shapes + 2), RES_OK); - CHECK(s3d_scene_build(NULL), RES_BAD_ARG); - CHECK(s3d_scene_build(scn), 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_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_shape_ref_put(shapes[0]), RES_OK); CHECK(s3d_shape_ref_put(shapes[1]), RES_OK); diff --git a/src/test_s3d_trace_ray.c b/src/test_s3d_trace_ray.c @@ -125,6 +125,7 @@ main(int argc, char** argv) (shape, ntris, cbox_get_ids, nverts, attribs, &desc), RES_OK); CHECK(s3d_scene_attach_shape(scn, shape), RES_OK); + CHECK(s3d_scene_begin_trace(scn), 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); @@ -157,10 +158,13 @@ main(int argc, char** argv) CHECK(s3d_scene_trace_ray(scn, NULL, dir, range, &hit), RES_BAD_ARG); CHECK(s3d_scene_trace_ray(NULL, org, dir, range, &hit), RES_BAD_ARG); CHECK(s3d_scene_trace_ray(scn, org, dir, range, &hit), RES_OK); - CHECK(s3d_scene_build(scn), RES_OK); 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); + + f3(dir, 0.f, 1.f, 0.f); + CHECK(s3d_scene_trace_ray(scn, org, dir, range, &hit), RES_BAD_OP); /* Update the shape with the CBox tall block mesh */ ntris = sizeof(cbox_block_ids)/sizeof(unsigned[3]); @@ -169,7 +173,8 @@ main(int argc, char** argv) desc.indices = cbox_block_ids; CHECK(s3d_mesh_setup_indexed_vertices (shape, ntris, cbox_get_ids, nverts, attribs, &desc), RES_OK); - CHECK(s3d_scene_build(scn), RES_OK); + CHECK(s3d_scene_begin_trace(scn), RES_OK); + CHECK(s3d_scene_end_trace(scn), RES_OK); /* Update the shape vertices */ desc.vertices = cbox_tall_block; @@ -202,7 +207,12 @@ main(int argc, char** argv) CHECK(s3d_scene_instantiate(scn, &shape), RES_OK); CHECK(s3d_scene_attach_shape(scn2, shape), RES_OK); CHECK(s3d_instance_set_position(shape, org), RES_OK); - CHECK(s3d_scene_build(scn2), 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); camera_init(&cam); FOR_EACH(iy, 0, IMG_HEIGHT) { @@ -253,6 +263,8 @@ main(int argc, char** argv) } } } + CHECK(s3d_scene_end_trace(scn2), RES_OK); + if(argc > 1) { CHECK(image_ppm_write(argv[1], IMG_WIDTH, IMG_HEIGHT, 3, img), RES_OK); }