commit 2032710b9aab7c02cc55bf4af237d4ade1f479a3
parent 33e91495fd3f5db1d379b5944a6b90be0c4b15dd
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 17 Jun 2015 12:16:54 +0200
Fix the scene clear|detach_shape function
The `clear' and `detach_shape' process could be called on a scene on
which a `begin_trace' was invoked. These actions deleted back-end data
that must be valid during the whole trace session.
Now, the `clear' and `detach_shape' functions return a RES_BAD_OP code if
they are called on a traceable scene.
Diffstat:
3 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/src/s3d.h b/src/s3d.h
@@ -221,10 +221,11 @@ s3d_scene_clear
/* 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
- * instance a RES_BAD_OP error is returned. On success no other begin trace 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. */
+ * 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. */
S3D_API res_T
s3d_scene_begin_trace
(struct s3d_scene* scn);
diff --git a/src/s3d_scene.c b/src/s3d_scene.c
@@ -144,7 +144,6 @@ scene_build_clear(struct s3d_scene* scn)
}
}
darray_inst_clear(&scn->instances);
- scn->is_rtc_scn_outdated = 0;
scn->build_type = BUILD_NONE;
}
@@ -326,6 +325,7 @@ scene_detach_shape_mesh(struct s3d_scene* scn, struct s3d_shape* shape)
if(mesh->geom.irtc != RTC_INVALID_GEOMETRY_ID) {
rtcDeleteGeometry(scn->rtc_scn, mesh->geom.irtc);
mesh->geom.irtc = RTC_INVALID_GEOMETRY_ID;
+ scn->is_rtc_scn_outdated = 1;
}
mesh_ref_put(mesh);
htable_mesh_erase(&scn->cached_meshes, &shape);
@@ -389,8 +389,10 @@ scene_build(struct s3d_scene* scn, const enum build_type type)
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;
+ }
scn->build_type = type;
@@ -533,6 +535,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(!(S3D(shape_is_attached(shape, &is_attached)), is_attached))
return RES_BAD_ARG;
#ifndef NDEBUG
@@ -554,9 +557,8 @@ res_T
s3d_scene_clear(struct s3d_scene* scn)
{
struct list_node* node, *tmp;
- if(!scn)
- return RES_BAD_ARG;
-
+ if(!scn) return RES_BAD_ARG;
+ if(scn->build_type != BUILD_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);
diff --git a/src/test_s3d_scene.c b/src/test_s3d_scene.c
@@ -89,6 +89,7 @@ main(int argc, char** argv)
CHECK(s3d_scene_is_traceable(scn, &b), RES_OK);
CHECK(b, 0);
+ 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);
@@ -96,6 +97,9 @@ main(int argc, char** argv)
CHECK(s3d_scene_is_traceable(scn, &b), RES_OK);
CHECK(b, 1);
+ 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);
@@ -103,6 +107,8 @@ main(int argc, char** argv)
CHECK(s3d_scene_is_traceable(scn, &b), RES_OK);
CHECK(b, 0);
+ CHECK(s3d_scene_detach_shape(scn, shapes[0]), RES_OK);
+
CHECK(s3d_shape_ref_put(shapes[0]), RES_OK);
CHECK(s3d_shape_ref_put(shapes[1]), RES_OK);
CHECK(s3d_shape_ref_put(shapes[2]), RES_OK);