solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

commit a89292751726df9f2e0d27d99ec733f2745d5bc8
parent 39419653b80110af010a33e50455cbce041527cc
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 18 Jul 2016 16:14:39 +0200

Change the attachment of the object instances into a scene

When an object instance is attached to a scene, it is added to a hash
table that maps the Star-3D identifier of the object instance to the
object instance itself. Contrary to the previous linked list this
associative container allows to retrieve the object instance directly
from its Star-3D identifier.

Diffstat:
Msrc/ssol_object_instance.c | 28++++++++--------------------
Msrc/ssol_object_instance_c.h | 18++++++++++--------
Msrc/ssol_scene.c | 167+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/ssol_scene_c.h | 23+++++++++++++----------
4 files changed, 139 insertions(+), 97 deletions(-)

diff --git a/src/ssol_object_instance.c b/src/ssol_object_instance.c @@ -32,13 +32,15 @@ static void object_instance_release(ref_T* ref) { struct ssol_device* dev; - struct ssol_object_instance* instance - = CONTAINER_OF(ref, struct ssol_object_instance, ref); + struct ssol_object_instance* instance; ASSERT(ref); + + instance = CONTAINER_OF(ref, struct ssol_object_instance, ref); dev = instance->dev; ASSERT(dev && dev->allocator); + SSOL(object_ref_put(instance->object)); - if(instance->shape) S3D(shape_ref_put(instance->shape)); + if(instance->s3d_shape) S3D(shape_ref_put(instance->s3d_shape)); str_release(&instance->receiver_name); MEM_RM(dev->allocator, instance); SSOL(device_ref_put(dev)); @@ -71,7 +73,6 @@ ssol_object_instantiate goto error; } - list_init(&instance->scene_attachment); instance->dev = dev; instance->object = object; str_init(dev->allocator, &instance->receiver_name); @@ -80,7 +81,7 @@ ssol_object_instantiate ref_init(&instance->ref); /* Create the Star-3D instance */ - res = s3d_scene_instantiate(object->s3d_scn, &instance->shape); + res = s3d_scene_instantiate(object->s3d_scn, &instance->s3d_shape); if(res != RES_OK) goto error; exit: @@ -147,22 +148,9 @@ res_T ssol_object_instance_is_attached (struct ssol_object_instance* instance, char* is_attached) { - if (!instance || !is_attached) - return RES_BAD_ARG; - *is_attached = !is_list_empty(&instance->scene_attachment); - + if(!instance || !is_attached) return RES_BAD_ARG; + S3D(shape_is_attached(instance->s3d_shape, is_attached)); return RES_OK; } -/******************************************************************************* - * Local functions - ******************************************************************************/ -unsigned -object_instance_get_s3d_id(const struct ssol_object_instance* instance) -{ - unsigned id; - ASSERT(instance); - S3D(shape_get_id(instance->shape, &id)); - return id; -} diff --git a/src/ssol_object_instance_c.h b/src/ssol_object_instance_c.h @@ -20,21 +20,23 @@ #include <rsys/ref_count.h> #include <rsys/str.h> -struct ssol_object_instance { +struct ssol_object_instance +{ struct ssol_object* object; /* Instantiated object */ double transform[12]; /* Object to world 3x4 column major affine transform */ - struct s3d_shape* shape; /* Instantiated Star-3D shape */ - - struct list_node scene_attachment; + struct s3d_shape* s3d_shape; /* Instantiated Star-3D shape */ struct str receiver_name; /* Emptry if not a receiver */ struct ssol_device* dev; ref_T ref; }; -/* Return the Star-3D identifier of the object instance */ -extern LOCAL_SYM unsigned -object_instance_get_s3d_id - (const struct ssol_object_instance* instance); +/* Return the Star-3D shape of the object instance */ +static INLINE struct s3d_shape* +object_instance_get_s3d_shape(const struct ssol_object_instance* instance) +{ + ASSERT(instance); + return instance->s3d_shape; +} #endif /* SSOL_OBJECT_INSTANCE_C_H */ diff --git a/src/ssol_scene.c b/src/ssol_scene.c @@ -19,9 +19,27 @@ #include "ssol_device_c.h" #include "ssol_object_instance_c.h" -#include <rsys/rsys.h> +#include <rsys/hash_table.h> +#include <rsys/list.h> #include <rsys/mem_allocator.h> #include <rsys/ref_count.h> +#include <rsys/rsys.h> + +/* Define the htable_instance data structure */ +#define HTABLE_NAME instance +#define HTABLE_KEY unsigned /* S3D object instance identifier */ +#define HTABLE_DATA struct ssol_object_instance* +#include <rsys/hash_table.h> + +struct ssol_scene +{ + struct htable_instance instances; + struct s3d_scene* s3d_scn; + struct ssol_sun* sun; + + struct ssol_device* dev; + ref_T ref; +}; /******************************************************************************* * Helper functions @@ -35,25 +53,13 @@ scene_release(ref_T* ref) dev = scene->dev; ASSERT(dev && dev->allocator); SSOL(scene_clear(scene)); - if (scene->scene3D) S3D(scene_ref_put(scene->scene3D)); - if (scene->sun) SSOL(sun_ref_put(scene->sun)); + if(scene->s3d_scn) S3D(scene_ref_put(scene->s3d_scn)); + if(scene->sun) SSOL(sun_ref_put(scene->sun)); + htable_instance_release(&scene->instances); MEM_RM(dev->allocator, scene); SSOL(device_ref_put(dev)); } -static void -scene_detach_instance - (struct ssol_scene* scene, - struct ssol_object_instance* instance) -{ - ASSERT(scene && instance && !is_list_empty(&instance->scene_attachment)); - ASSERT(scene->instances_count != 0); - - list_del(&instance->scene_attachment); - --scene->instances_count; - SSOL(object_instance_ref_put(instance)); -} - /******************************************************************************* * Exported ssol_image functions ******************************************************************************/ @@ -74,11 +80,14 @@ ssol_scene_create res = RES_MEM_ERR; goto error; } - list_init(&scene->instances); + htable_instance_init(dev->allocator, &scene->instances); SSOL(device_ref_get(dev)); scene->dev = dev; ref_init(&scene->ref); + res = s3d_scene_create(dev->s3d, &scene->s3d_scn); + if(res != RES_OK) goto error; + exit: if (out_scene) *out_scene = scene; return res; @@ -91,21 +100,17 @@ error: } res_T -ssol_scene_ref_get - (struct ssol_scene* scene) +ssol_scene_ref_get(struct ssol_scene* scene) { - if (!scene) - return RES_BAD_ARG; + if(!scene) return RES_BAD_ARG; ref_get(&scene->ref); return RES_OK; } res_T -ssol_scene_ref_put - (struct ssol_scene* scene) +ssol_scene_ref_put(struct ssol_scene* scene) { - if (!scene) - return RES_BAD_ARG; + if(!scene) return RES_BAD_ARG; ref_put(&scene->ref, scene_release); return RES_OK; } @@ -114,15 +119,26 @@ res_T ssol_scene_attach_object_instance (struct ssol_scene* scene, struct ssol_object_instance* instance) { - if (!scene || !instance) - return RES_BAD_ARG; - if (!is_list_empty(&instance->scene_attachment)) - return RES_BAD_ARG; - - /* Instance is chained into the list of instance of the scene */ - list_add_tail(&scene->instances, &instance->scene_attachment); + struct s3d_shape* shape; + unsigned id; + res_T res; + + if(!scene || !instance) return RES_BAD_ARG; + shape = object_instance_get_s3d_shape(instance); + + /* Try to attach the instantiated s3d shape to s3d scene */ + res = s3d_scene_attach_shape(scene->s3d_scn, shape); + if(res != RES_OK) return res; + + /* Register the instance against the scene */ + S3D(shape_get_id(shape, &id)); + ASSERT(!htable_instance_find(&scene->instances, &id)); + res = htable_instance_set(&scene->instances, &id, &instance); + if(res != RES_OK) { + S3D(scene_detach_shape(scene->s3d_scn, shape)); + return res; + } SSOL(object_instance_ref_get(instance)); - scene->instances_count++; return RES_OK; } @@ -131,40 +147,51 @@ ssol_scene_detach_object_instance (struct ssol_scene* scene, struct ssol_object_instance* instance) { - char is_attached; - if (!scene || !instance) return RES_BAD_ARG; - if (!(SSOL(object_instance_is_attached(instance, &is_attached)), is_attached)) - return RES_BAD_ARG; - -#ifndef NDEBUG - { /* Check that instance is attached to `scene' */ - struct list_node* node; - char is_found = 0; - LIST_FOR_EACH(node, &scene->instances) { - if (node == &instance->scene_attachment) { - is_found = 1; - break; - } - } - ASSERT(is_found); - } -#endif + struct ssol_object_instance** pinst; + struct ssol_object_instance* inst; + struct s3d_shape* shape; + unsigned id; + size_t n; + (void)n, (void)inst; + + if(!scene || !instance) return RES_BAD_ARG; + + /* Retrieve the object instance identifier */ + shape = object_instance_get_s3d_shape(instance); + S3D(shape_get_id(shape, &id)); + + /* Check that the instance is effectively registered into the scene */ + pinst = htable_instance_find(&scene->instances, &id); + if(!pinst) return RES_BAD_ARG; + inst = *pinst; + ASSERT(inst == instance); + + /* Detach the object instance */ + n = htable_instance_erase(&scene->instances, &id); + ASSERT(n == 1); + S3D(scene_detach_shape(scene->s3d_scn, shape)); + SSOL(object_instance_ref_put(instance)); - scene_detach_instance(scene, instance); return RES_OK; } res_T ssol_scene_clear(struct ssol_scene* scene) { - struct list_node* node, *tmp; - if (!scene) return RES_BAD_ARG; - - LIST_FOR_EACH_SAFE(node, tmp, &scene->instances) { - struct ssol_object_instance* instance = CONTAINER_OF - (node, struct ssol_object_instance, scene_attachment); - scene_detach_instance(scene, instance); + struct htable_instance_iterator it, it_end; + if(!scene) return RES_BAD_ARG; + + htable_instance_begin(&scene->instances, &it); + htable_instance_end(&scene->instances, &it_end); + while(!htable_instance_iterator_eq(&it, &it_end)) { + struct ssol_object_instance* inst; + inst = *htable_instance_iterator_data_get(&it); + S3D(scene_detach_shape(scene->s3d_scn, object_instance_get_s3d_shape(inst))); + SSOL(object_instance_ref_put(inst)); + htable_instance_iterator_next(&it); } + htable_instance_clear(&scene->instances); + S3D(scene_clear(scene->s3d_scn)); return RES_OK; } @@ -193,3 +220,25 @@ ssol_scene_detach_sun(struct ssol_scene* scene, struct ssol_sun* sun) return RES_OK; } +/******************************************************************************* + * Local functions + ******************************************************************************/ +struct s3d_scene* +scene_get_s3d_scene(const struct ssol_scene* scn) +{ + ASSERT(scn); + return scn->s3d_scn; +} + +struct ssol_object_instance* +scene_get_object_instance_from_s3d_hit + (struct ssol_scene* scn, + const struct s3d_hit* hit) +{ + struct ssol_object_instance** pinst; + ASSERT(scn && hit); + pinst = htable_instance_find(&scn->instances, &hit->prim.inst_id); + ASSERT(pinst); + return *pinst; +} + diff --git a/src/ssol_scene_c.h b/src/ssol_scene_c.h @@ -16,18 +16,21 @@ #ifndef SSOL_SCENE_C_H #define SSOL_SCENE_C_H -#include <rsys/ref_count.h> -#include <rsys/list.h> +#include <rsys/rsys.h> -struct ssol_scene { - struct list_node instances; /* List of attached instances */ - size_t instances_count; - struct s3d_scene* scene3D; - struct ssol_sun* sun; +struct s3d_hit; +struct s3d_scene; +struct ssol_object_instance; +struct ssol_scene; - struct ssol_device* dev; - ref_T ref; -}; +extern LOCAL_SYM struct s3d_scene* +scene_get_s3d_scene + (const struct ssol_scene* scn); + +extern LOCAL_SYM struct ssol_object_instance* +scene_get_object_instance_from_s3d_hit + (struct ssol_scene* scn, + const struct s3d_hit* hit); #endif /* SSOL_SCENE_C_H */