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:
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 */