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 547e4c9d03d7b1bccb72672b112e108bad13466f
parent 71014d55ed7358feeb153a39196cc5fba14abafa
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 27 Mar 2015 09:20:56 +0100

Make robust a scene build to the shape removal/scene clear operations

Diffstat:
Msrc/s3d.h | 17+++++++++++++++++
Msrc/s3d_instance.c | 18++++++++++++++++++
Msrc/s3d_instance.h | 11+++++++++++
Msrc/s3d_mesh.c | 21+++++++++++++++++++++
Msrc/s3d_mesh.h | 10++++++++++
Msrc/s3d_scene.c | 104+++++++++++++++++++++++++++++++++++++------------------------------------------
6 files changed, 126 insertions(+), 55 deletions(-)

diff --git a/src/s3d.h b/src/s3d.h @@ -132,6 +132,7 @@ static const struct s3d_hit S3D_HIT_NULL = /* Forward declaration of s3d opaque data types */ struct s3d_device; /* Entry point of the library */ +struct s3d_rt_session; /* Ray tracing session */ struct s3d_scene; /* Collection of shapes */ struct s3d_shape; /* Untyped geometry */ @@ -317,6 +318,22 @@ s3d_instance_translate const enum s3d_transform_space space, const float translation[3]); +/******************************************************************************* + * RT Session + ******************************************************************************/ +S3D_API res_T +s3d_rt_session_create + (struct s3d_scene* scn, + struct s3d_rt_session** session); + +S3D_API res_T +s3d_rt_session_ref_get + (struct s3d_rt_session* session); + +S3D_API res_T +s3d_rt_session_ref_put + (struct s3d_rt_session* session); + END_DECLS #endif /* S3D_H */ diff --git a/src/s3d_instance.c b/src/s3d_instance.c @@ -49,6 +49,8 @@ instance_release(ref_T* ref) ASSERT(ref); inst = CONTAINER_OF(ref, struct instance, ref); scn = inst->scene; + if(inst->rtc_geom != RTC_INVALID_GEOMETRY_ID) + instance_delete_rtc_geom(inst); MEM_FREE(scn->dev->allocator, inst); S3D(scene_ref_put(scn)); } @@ -103,3 +105,19 @@ instance_ref_put(struct instance* inst) ref_put(&inst->ref, instance_release); } +void +instance_create_rtc_geom(struct instance* inst, RTCScene scn) +{ + ASSERT(inst && inst->rtc_geom == RTC_INVALID_GEOMETRY_ID && scn); + inst->rtc_geom = rtcNewInstance(scn, inst->scene->rtc_scn); + inst->rtc_scn = scn; +} + +void +instance_delete_rtc_geom(struct instance* inst) +{ + ASSERT(inst && inst->rtc_geom != RTC_INVALID_GEOMETRY_ID && inst->rtc_scn); + rtcDeleteGeometry(inst->rtc_scn, inst->rtc_geom); + inst->rtc_geom = RTC_INVALID_GEOMETRY_ID; + inst->rtc_scn = NULL; +} diff --git a/src/s3d_instance.h b/src/s3d_instance.h @@ -38,6 +38,8 @@ struct instance { float transform[12]; /* local to world 3x4 column major matrix */ char update_transform; + + RTCScene rtc_scn; unsigned rtc_geom; struct s3d_scene* scene; @@ -57,5 +59,14 @@ extern LOCAL_SYM void instance_ref_put (struct instance* inst); +extern LOCAL_SYM void +instance_create_rtc_geom + (struct instance* inst, + RTCScene rtc_scn); + +extern LOCAL_SYM void +instance_delete_rtc_geom + (struct instance* inst); + #endif /* S3D_INSTANCE_H */ diff --git a/src/s3d_mesh.c b/src/s3d_mesh.c @@ -215,6 +215,8 @@ mesh_release(ref_T* ref) mesh = CONTAINER_OF(ref, struct mesh, ref); mesh_clear(mesh); dev = mesh->dev; + if(mesh->rtc_geom != RTC_INVALID_GEOMETRY_ID) + mesh_delete_rtc_geom(mesh); MEM_FREE(dev->allocator, mesh); S3D(device_ref_put(dev)); } @@ -235,6 +237,7 @@ mesh_create(struct s3d_device* dev, struct mesh** out_mesh) goto error; } mesh->rtc_geom = RTC_INVALID_GEOMETRY_ID; + mesh->rtc_scn = NULL; ref_init(&mesh->ref); S3D(device_ref_get(dev)); mesh->dev = dev; @@ -265,6 +268,24 @@ mesh_ref_put(struct mesh* mesh) } void +mesh_create_rtc_geom(struct mesh* mesh, RTCScene scn) +{ + ASSERT(mesh && mesh->rtc_geom == RTC_INVALID_GEOMETRY_ID && scn); + mesh->rtc_geom = rtcNewTriangleMesh(scn, RTC_GEOMETRY_DYNAMIC, + mesh_get_ntris(mesh), mesh_get_nverts(mesh)); + mesh->rtc_scn = scn; +} + +void +mesh_delete_rtc_geom(struct mesh* mesh) +{ + ASSERT(mesh && mesh->rtc_geom != RTC_INVALID_GEOMETRY_ID && mesh->rtc_scn); + rtcDeleteGeometry(mesh->rtc_scn, mesh->rtc_geom); + mesh->rtc_geom = RTC_INVALID_GEOMETRY_ID; + mesh->rtc_scn = NULL; +} + +void mesh_clear(struct mesh* mesh) { size_t iattr; diff --git a/src/s3d_mesh.h b/src/s3d_mesh.h @@ -64,6 +64,7 @@ struct mesh { /* Triangular mesh */ int resize_mask; /* Combination of buffer_type */ int update_mask; /* Combination of buffer_type */ + RTCScene rtc_scn; /* Embree scene from which rtc_geom was created */ unsigned rtc_geom; /* Embree geometry */ struct s3d_device* dev; @@ -84,6 +85,15 @@ mesh_ref_put (struct mesh* mesh); extern LOCAL_SYM void +mesh_create_rtc_geom + (struct mesh* mesh, + RTCScene rtc_scn); + +extern LOCAL_SYM void +mesh_delete_rtc_geom + (struct mesh* mesh); + +extern LOCAL_SYM void mesh_clear (struct mesh* mesh); diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -44,73 +44,73 @@ * Helper functions ******************************************************************************/ static res_T -scene_create_mesh_rtc_geometry(struct s3d_scene* scn, struct mesh* mesh) +scene_build_register_mesh(struct s3d_scene* scn, struct mesh* mesh) { - ASSERT(scn && mesh && mesh->rtc_geom == RTC_INVALID_GEOMETRY_ID); - mesh->rtc_geom = rtcNewTriangleMesh(scn->rtc_scn, RTC_GEOMETRY_DYNAMIC, - mesh_get_ntris(mesh), mesh_get_nverts(mesh)); + ASSERT(scn && mesh); + /* Create the Embree geometry if it is not valid */ + if(mesh->rtc_geom == RTC_INVALID_GEOMETRY_ID) { + mesh_create_rtc_geom(mesh, scn->rtc_scn); + scn->is_rtc_scn_outdated = 1; + } - /* Map the Embree geometry to its scene mesh */ if(mesh->rtc_geom >= darray_geom2mesh_size_get(&scn->geom2mesh)) { res_T res = darray_geom2mesh_resize(&scn->geom2mesh, mesh->rtc_geom + 1); if(res != RES_OK) { rtcDeleteGeometry(scn->rtc_scn, mesh->rtc_geom); mesh->rtc_geom = RTC_INVALID_GEOMETRY_ID; return res; - } else { - /* Check that no other mesh is mapped to this Embree geometry */ - ASSERT(!darray_geom2mesh_data_get(&scn->geom2mesh)[mesh->rtc_geom]); } + mesh_ref_get(mesh); darray_geom2mesh_data_get(&scn->geom2mesh)[mesh->rtc_geom] = mesh; - scn->is_rtc_scn_outdated = 1; } return RES_OK; } -static void -scene_delete_mesh_rtc_geometry(struct s3d_scene* scn, struct mesh* mesh) -{ - ASSERT(scn && mesh && mesh->rtc_geom != RTC_INVALID_GEOMETRY_ID); - ASSERT(darray_geom2mesh_size_get(&scn->geom2mesh) > mesh->rtc_geom); - darray_geom2mesh_data_get(&scn->geom2mesh)[mesh->rtc_geom] = NULL; - rtcDeleteGeometry(scn->rtc_scn, mesh->rtc_geom); - mesh->rtc_geom = RTC_INVALID_GEOMETRY_ID; - scn->is_rtc_scn_outdated = 1; -} - static res_T -scene_create_instance_rtc_geometry(struct s3d_scene* scn, struct instance* inst) +scene_build_register_instance(struct s3d_scene* scn, struct instance* inst) { - ASSERT(scn && inst && inst->scene && inst->rtc_geom == RTC_INVALID_GEOMETRY_ID); + ASSERT(scn && inst && inst->scene); /* The instance should not contain instances */ ASSERT(!darray_geom2inst_size_get(&inst->scene->geom2inst)); - inst->rtc_geom = rtcNewInstance(scn->rtc_scn, inst->scene->rtc_scn); + if(inst->rtc_geom) { + instance_create_rtc_geom(inst, scn->rtc_scn); + scn->is_rtc_scn_outdated = 1; + } + if(inst->rtc_geom >= darray_geom2inst_size_get(&scn->geom2inst)) { res_T res = darray_geom2inst_resize(&scn->geom2inst, inst->rtc_geom + 1); if(res != RES_OK) { rtcDeleteGeometry(scn->rtc_scn, inst->rtc_geom); inst->rtc_geom = RTC_INVALID_GEOMETRY_ID; return res; - } else { - /* Check that no other scene is mapped to this Embree geometry */ - ASSERT(!darray_geom2inst_data_get(&scn->geom2inst)[inst->rtc_geom]); } + instance_ref_get(inst); darray_geom2inst_data_get(&scn->geom2inst)[inst->rtc_geom] = inst; - scn->is_rtc_scn_outdated = 1; } return RES_OK; } static void -scene_delete_instance_rtc_geometry(struct s3d_scene* scn, struct instance* inst) +scene_build_clear(struct s3d_scene* scn) { - ASSERT(scn && inst && inst->rtc_geom != RTC_INVALID_GEOMETRY_ID); - ASSERT(darray_geom2inst_size_get(&scn->geom2inst) > inst->rtc_geom); - darray_geom2inst_data_get(&scn->geom2inst)[inst->rtc_geom] = NULL; - rtcDeleteGeometry(scn->rtc_scn, inst->rtc_geom); - inst->rtc_geom = RTC_INVALID_GEOMETRY_ID; - scn->is_rtc_scn_outdated = 1; + struct mesh** meshes; + struct instance** instances; + size_t nmeshes; + size_t ninstances; + size_t i; + ASSERT(scn); + + nmeshes = darray_geom2mesh_size_get(&scn->geom2mesh); + meshes = darray_geom2mesh_data_get(&scn->geom2mesh); + FOR_EACH(i, 0, nmeshes) if(meshes[i]) mesh_ref_put(meshes[i]); + darray_geom2mesh_clear(&scn->geom2mesh); + + 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]); + darray_geom2inst_clear(&scn->geom2inst); + scn->is_rtc_scn_outdated = 0; } static res_T @@ -139,8 +139,10 @@ scene_setup_shape_mesh /* Discard the shape mesh that is not geometrically valid */ if(!shape->data.mesh->indices || !shape->data.mesh->attribs[S3D_POSITION]) { - if(mesh->rtc_geom != RTC_INVALID_GEOMETRY_ID) - scene_delete_mesh_rtc_geometry(scn, mesh); + if(mesh->rtc_geom != RTC_INVALID_GEOMETRY_ID) { + mesh_delete_rtc_geom(mesh); + scn->is_rtc_scn_outdated = 1; + } mesh_clear(mesh); goto exit; } @@ -181,14 +183,12 @@ scene_setup_shape_mesh /* The shape mesh was resize => the Embree geometry is no more valid */ if(shape->data.mesh->resize_mask && mesh->rtc_geom!=RTC_INVALID_GEOMETRY_ID) { - scene_delete_mesh_rtc_geometry(scn, mesh); + mesh_delete_rtc_geom(mesh); + scn->is_rtc_scn_outdated = 1; } - /* Create the Embree geometry of the scene mesh */ - if(mesh->rtc_geom == RTC_INVALID_GEOMETRY_ID) { - res = scene_create_mesh_rtc_geometry(scn, mesh); - if(res != RES_OK) goto error; - } + res = scene_build_register_mesh(scn, mesh); + if(res != RES_OK) goto error; if(upd_pos) { /* Update the Embree vertex buffer if necessary */ rtcSetBuffer(scn->rtc_scn, mesh->rtc_geom, RTC_VERTEX_BUFFER, @@ -247,10 +247,8 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) } /* Create the Embree instance */ - if(inst->rtc_geom == RTC_INVALID_GEOMETRY_ID) { - res = scene_create_instance_rtc_geometry(scn, inst); - if(res != RES_OK) goto error; - } + res = scene_build_register_instance(scn, inst); + if(res != RES_OK) goto error; /* Update the Embree instance transformation */ if(shape->data.instance->update_transform) { @@ -278,10 +276,8 @@ scene_detach_shape_mesh(struct s3d_scene* scn, struct s3d_shape* shape) ASSERT(shape->type == SHAPE_MESH); pmesh = htable_mesh_find(&scn->meshes, &shape); - if(pmesh) { /* The shape mesh is registered into the scene */ + if(pmesh) { /* The shape mesh is cached into the scene */ struct mesh* mesh = *pmesh; - if(mesh->rtc_geom != RTC_INVALID_GEOMETRY_ID) /* Rm the Embree geometry */ - scene_delete_mesh_rtc_geometry(scn, mesh); mesh_ref_put(mesh); htable_mesh_erase(&scn->meshes, &shape); } @@ -297,10 +293,8 @@ scene_detach_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) ASSERT(shape->type == SHAPE_INSTANCE); pinst = htable_inst_find(&scn->instances, &shape); - if(pinst) { /* The shape instance is registered into the scene */ + if(pinst) { /* The shape instance is cached into the scene */ struct instance* inst = *pinst; - if(inst->rtc_geom != RTC_INVALID_GEOMETRY_ID) - scene_delete_instance_rtc_geometry(scn, inst); instance_ref_put(inst); htable_inst_erase(&scn->instances, &shape); } @@ -328,6 +322,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); if(scn->rtc_scn) rtcDeleteScene(scn->rtc_scn); htable_mesh_release(&scn->meshes); htable_inst_release(&scn->instances); @@ -493,6 +488,7 @@ s3d_scene_build(struct s3d_scene* scn) goto error; } + scene_build_clear(scn); LIST_FOR_EACH(node, &scn->shapes) { struct s3d_shape* shape = CONTAINER_OF (node, struct s3d_shape, scene_attachment); @@ -504,10 +500,8 @@ s3d_scene_build(struct s3d_scene* scn) if(res != RES_OK) goto error; } - if(scn->is_rtc_scn_outdated) { + if(scn->is_rtc_scn_outdated) rtcCommit(scn->rtc_scn); - scn->is_rtc_scn_outdated = 0; - } exit: return res;