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 e72f4b9c0e670b0b9e5bdae9dc11528098534245
parent fdc9717a405a6ebd3fe8835fbca53f040d675743
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 26 Mar 2015 15:45:31 +0100

Ref count the internal instance representation

Diffstat:
Msrc/s3d_instance.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/s3d_instance.h | 15++++++++++++---
Msrc/s3d_scene.c | 59+++++++++++++++++++++++++++++------------------------------
Msrc/s3d_shape.c | 33++++++++++++++++++---------------
Msrc/s3d_shape_c.h | 2+-
5 files changed, 113 insertions(+), 57 deletions(-)

diff --git a/src/s3d_instance.c b/src/s3d_instance.c @@ -32,29 +32,74 @@ #include "s3d.h" #include "s3d_backend.h" +#include "s3d_device_c.h" #include "s3d_instance.h" +#include "s3d_scene_c.h" #include <rsys/float33.h> +/******************************************************************************* + * Helper functions + ******************************************************************************/ void -instance_init(struct instance* inst) +instance_release(ref_T* ref) { - ASSERT(inst); - inst->scene = NULL; + struct instance* inst; + struct s3d_scene* scn; + ASSERT(ref); + inst = CONTAINER_OF(ref, struct instance, ref); + scn = inst->scene; + MEM_FREE(scn->dev->allocator, inst); + S3D(scene_ref_put(scn)); +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +instance_create + (struct s3d_scene* scn, + struct instance** out_inst) +{ + struct instance* inst = NULL; + res_T res = RES_OK; + ASSERT(scn && out_inst); + + inst = (struct instance*) + MEM_CALLOC(scn->dev->allocator, 1, sizeof(struct instance)); + if(!inst) { + res = RES_MEM_ERR; + goto error; + } f33_set_identity(inst->transform); /* rotation */ f3_splat(inst->transform + 9, 0.f); /* Translation */ inst->update_transform = 0; inst->rtc_geom = RTC_INVALID_GEOMETRY_ID; + ref_init(&inst->ref); + S3D(scene_ref_get(scn)); + inst->scene = scn; +exit: + *out_inst = inst; + return res; +error: + if(inst) { + instance_ref_put(inst); + inst = NULL; + } + goto exit; } void -instance_clear(struct instance* inst) +instance_ref_get(struct instance* inst) { ASSERT(inst); - if(inst->scene) { - S3D(scene_ref_put(inst->scene)); - inst->scene = NULL; - } + ref_get(&inst->ref); } +void +instance_ref_put(struct instance* inst) +{ + ASSERT(inst); + ref_put(&inst->ref, instance_release); +} diff --git a/src/s3d_instance.h b/src/s3d_instance.h @@ -33,19 +33,28 @@ #ifndef S3D_INSTANCE_H #define S3D_INSTANCE_H +#include <rsys/ref_count.h> + struct instance { - struct s3d_scene* scene; float transform[12]; /* local to world 3x4 column major matrix */ char update_transform; unsigned rtc_geom; + + struct s3d_scene* scene; + ref_T ref; }; +extern LOCAL_SYM res_T +instance_create + (struct s3d_scene* scene, + struct instance** inst); + extern LOCAL_SYM void -instance_init +instance_ref_get (struct instance* inst); extern LOCAL_SYM void -instance_clear +instance_ref_put (struct instance* inst); #endif /* S3D_INSTANCE_H */ diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -226,7 +226,7 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) ASSERT(scn && shape && shape->type == SHAPE_INSTANCE); /* Recursuvely update the scene */ - res = s3d_scene_build(shape->data.instance.scene); + res = s3d_scene_build(shape->data.instance->scene); if(res != RES_OK) goto error; pinst = htable_inst_find(&scn->instances, &shape); @@ -234,25 +234,15 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) if(pinst) { inst = *pinst; } else { - inst = (struct instance*) - MEM_ALLOC(scn->dev->allocator, sizeof(struct instance)); - if(!inst) { - res = RES_MEM_ERR; - goto error; - } - instance_init(inst); + res = instance_create(shape->data.instance->scene, &inst); + if(res != RES_OK) goto error; res = htable_inst_set(&scn->instances, &shape, &inst); if(res != RES_OK) goto error; - /* It is not necessary to get a reference onto the instantiated scene since - * the scene get a reference onto its shape. Anyway it is actually more - * consistent */ - S3D(scene_ref_get(shape->data.instance.scene)); - inst->scene = shape->data.instance.scene; } - ASSERT(inst->scene == shape->data.instance.scene); - f33_set(inst->transform, shape->data.instance.transform); - f3_set(inst->transform + 9, shape->data.instance.transform + 9); + ASSERT(inst->scene == shape->data.instance->scene); + f33_set(inst->transform, shape->data.instance->transform); + f3_set(inst->transform + 9, shape->data.instance->transform + 9); /* The instance cannot contain instances */ if(darray_geom2inst_size_get(&inst->scene->geom2inst)) { @@ -267,7 +257,7 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) } /* Update the Embree instance transformation */ - if(shape->data.instance.update_transform) { + if(shape->data.instance->update_transform) { rtcSetTransform (scn->rtc_scn, inst->rtc_geom, @@ -276,7 +266,7 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) scn->is_rtc_scn_outdated = 1; } - shape->data.instance.update_transform = 0; /* Flush instance state */ + shape->data.instance->update_transform = 0; /* Flush instance state */ exit: return res; @@ -316,8 +306,7 @@ scene_detach_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) struct instance* inst = *pinst; if(inst->rtc_geom != RTC_INVALID_GEOMETRY_ID) scene_delete_instance_rtc_geometry(scn, inst); - instance_clear(inst); - MEM_FREE(scn->dev->allocator, inst); + instance_ref_put(inst); htable_inst_erase(&scn->instances, &shape); } list_del(&shape->scene_attachment); @@ -420,22 +409,32 @@ s3d_scene_ref_put(struct s3d_scene* scn) res_T s3d_scene_instantiate(struct s3d_scene* scn, struct s3d_shape** out_shape) { - struct s3d_shape* shape; + struct s3d_shape* shape = NULL; res_T res = RES_OK; - if(!scn || !out_shape) - return RES_BAD_ARG; - + if(!scn || !out_shape) { + res = RES_BAD_ARG; + goto error; + } res = shape_create(scn->dev, &shape); if(res != RES_OK) - return res; + goto error; shape->type = SHAPE_INSTANCE; - instance_init(&shape->data.instance); - S3D(scene_ref_get(scn)); - shape->data.instance.scene = scn; - *out_shape = shape; - return RES_OK; + res = instance_create(scn, &shape->data.instance); + if(res != RES_OK) + goto error; + +exit: + if(out_shape) + *out_shape = shape; + return res; +error: + if(shape) { + S3D(shape_ref_put(shape)); + shape = NULL; + } + goto exit; } res_T diff --git a/src/s3d_shape.c b/src/s3d_shape.c @@ -48,7 +48,10 @@ shape_release_data(struct s3d_shape* shape) switch(shape->type) { case SHAPE_MESH: mesh_clear(&shape->data.mesh); break; case SHAPE_NONE: /* Do nothing */ break; - case SHAPE_INSTANCE: instance_clear(&shape->data.instance); break; + case SHAPE_INSTANCE: + if(shape->data.instance) + instance_ref_put(shape->data.instance); + break; default: FATAL("Unreachable code\n"); break; } shape->type = SHAPE_NONE; @@ -175,13 +178,13 @@ s3d_instance_set_position float axis[3]; if(!shape || shape->type != SHAPE_INSTANCE || !position) return RES_BAD_ARG; - shape->data.instance.transform[9] = - f3_dot(f33_row(axis, shape->data.instance.transform, 0), position); - shape->data.instance.transform[10] = - f3_dot(f33_row(axis, shape->data.instance.transform, 1), position); - shape->data.instance.transform[11] = - f3_dot(f33_row(axis, shape->data.instance.transform, 2), position); - shape->data.instance.update_transform = 1; + shape->data.instance->transform[9] = + f3_dot(f33_row(axis, shape->data.instance->transform, 0), position); + shape->data.instance->transform[10] = + f3_dot(f33_row(axis, shape->data.instance->transform, 1), position); + shape->data.instance->transform[11] = + f3_dot(f33_row(axis, shape->data.instance->transform, 2), position); + shape->data.instance->update_transform = 1; return RES_OK; } @@ -195,18 +198,18 @@ s3d_instance_translate return RES_BAD_ARG; if(space == S3D_LOCAL_TRANSFORM) { float vec[3]; - f33_mulf3(vec, shape->data.instance.transform, translation); + f33_mulf3(vec, shape->data.instance->transform, translation); f3_add - (shape->data.instance.transform + 9, - shape->data.instance.transform + 9, + (shape->data.instance->transform + 9, + shape->data.instance->transform + 9, vec); - shape->data.instance.update_transform = 1; + shape->data.instance->update_transform = 1; } else if(space == S3D_WORLD_TRANSFORM) { f3_add - (shape->data.instance.transform + 9, - shape->data.instance.transform + 9, + (shape->data.instance->transform + 9, + shape->data.instance->transform + 9, translation); - shape->data.instance.update_transform = 1; + shape->data.instance->update_transform = 1; } else { return RES_BAD_ARG; } diff --git a/src/s3d_shape_c.h b/src/s3d_shape_c.h @@ -56,7 +56,7 @@ struct s3d_shape { enum shape_type type; union { - struct instance instance; + struct instance* instance; struct mesh mesh; } data;