commit 0adf9cbf36058cd40f74ce3307a9f089273f766c
parent 6b9694436ac338c095077be3e97511ad5fb95465
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 22 Feb 2017 10:34:59 +0100
Add the ssol_scene_for_each_instance function
Diffstat:
3 files changed, 62 insertions(+), 15 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -476,6 +476,12 @@ ssol_scene_detach_atmosphere
(struct ssol_scene* scn,
struct ssol_atmosphere* atm);
+SSOL_API res_T
+ssol_scene_for_each_instance
+ (struct ssol_scene* scn,
+ res_T (*func)(struct ssol_instance* instance, void* ctx),
+ void* ctx);
+
/*******************************************************************************
* Shape API - Define a geometry that can be generated from a quadric equation
* or from a triangular mesh.
diff --git a/src/ssol_scene.c b/src/ssol_scene.c
@@ -115,15 +115,18 @@ res_T
ssol_scene_attach_instance
(struct ssol_scene* scene, struct ssol_instance* instance)
{
+ enum { ATTACH_S3D, SET_INSTANCE_RT };
unsigned id;
struct ssol_instance** pinst;
+ int mask = 0;
res_T res;
if(!scene || !instance) return RES_BAD_ARG;
/* Attach the instantiated s3d shape to ray-trace to the RT scene */
res = s3d_scene_attach_shape(scene->scn_rt, instance->shape_rt);
- if(res != RES_OK) return res;
+ if(res != RES_OK) goto error;
+ mask |= BIT(ATTACH_S3D);
/* Register the instance against the scene */
S3D(shape_get_id(instance->shape_rt, &id));
@@ -131,15 +134,26 @@ ssol_scene_attach_instance
if(pinst) {
/* already attached */
ASSERT(*pinst == instance); /* cannot be attached to another instance! */
- return RES_OK;
+ goto exit;
}
+
res = htable_instance_set(&scene->instances_rt, &id, &instance);
- if(res != RES_OK) {
+ if(res != RES_OK) goto error;
+ mask |= BIT(SET_INSTANCE_RT);
+
+ SSOL(instance_ref_get(instance));
+
+exit:
+ return res;
+error:
+ if(mask & BIT(ATTACH_S3D)) {
S3D(scene_detach_shape(scene->scn_rt, instance->shape_rt));
- return res;
}
- SSOL(instance_ref_get(instance));
- return RES_OK;
+ if(mask & BIT(SET_INSTANCE_RT)) {
+ const size_t n = htable_instance_erase(&scene->instances_rt, &id);
+ ASSERT(n == 1); (void)n;
+ }
+ goto exit;
}
res_T
@@ -192,9 +206,8 @@ ssol_scene_clear(struct ssol_scene* scene)
htable_instance_clear(&scene->instances_samp);
S3D(scene_clear(scene->scn_rt));
S3D(scene_clear(scene->scn_samp));
- if (scene->sun) ssol_scene_detach_sun(scene, scene->sun);
- if (scene->atmosphere)
- ssol_scene_detach_atmosphere(scene, scene->atmosphere);
+ if(scene->sun) SSOL(scene_detach_sun(scene, scene->sun));
+ if(scene->atmosphere) SSOL(scene_detach_atmosphere(scene, scene->atmosphere));
return RES_OK;
}
@@ -204,13 +217,11 @@ ssol_scene_attach_sun(struct ssol_scene* scene, struct ssol_sun* sun)
if(!scene || ! sun)
return RES_BAD_ARG;
if(sun->scene_attachment || scene->sun) {
- /* already attached: must be linked together */
+ /* Already attached: must be linked together */
if(sun->scene_attachment != scene || scene->sun != sun) {
- /* if not detach first! */
- return RES_BAD_ARG;
+ return RES_BAD_ARG; /* If not detach first! */
} else {
- /* nothing to change */
- return RES_OK;
+ return RES_OK; /* Nothing to change */
}
}
/* no previous attachment */
@@ -269,6 +280,36 @@ ssol_scene_detach_atmosphere(struct ssol_scene* scene, struct ssol_atmosphere* a
return RES_OK;
}
+res_T
+ssol_scene_for_each_instance
+ (struct ssol_scene* scn,
+ res_T (*func)(struct ssol_instance* instance, void* ctx),
+ void* ctx)
+{
+ struct htable_instance_iterator it, end;
+ res_T res = RES_OK;
+
+ if(!scn || !func) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ htable_instance_begin(&scn->instances_rt, &it);
+ htable_instance_end(&scn->instances_rt, &end);
+ while(!htable_instance_iterator_eq(&it, &end)) {
+ struct ssol_instance* inst = *htable_instance_iterator_data_get(&it);
+ htable_instance_iterator_next(&it);
+
+ res = func(inst, ctx);
+ if(res != RES_OK) goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
/*******************************************************************************
* Local functions
******************************************************************************/
diff --git a/src/ssol_scene_c.h b/src/ssol_scene_c.h
@@ -22,7 +22,7 @@
struct ssol_instance;
- /* Define the htable_instance data structure */
+/* Define the htable_instance data structure */
#define HTABLE_NAME instance
#define HTABLE_KEY unsigned /* S3D object instance identifier */
#define HTABLE_DATA struct ssol_instance*