commit a66e360264907cfed2c33044027efd357ed2ffd9
parent 8e85a6d7b3f8687179c5a63e5c3ffc702db818fe
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 26 Oct 2016 12:02:53 +0200
Fix a major issue in the scene instantiation
Each instance was a copy of the original scene, i.e. no data was
shared between the instances. The main advantages of the instantiation
mechanism was thus cancelled. This commit fixes this issue by sharing the
scene view of the instantiated scene between all instances.
Diffstat:
4 files changed, 60 insertions(+), 32 deletions(-)
diff --git a/src/s3d_instance.h b/src/s3d_instance.h
@@ -40,7 +40,10 @@
struct instance {
float transform[12]; /* local to world 3x4 column major matrix */
struct s3d_scene* scene; /* Instantiated scene */
- struct s3d_scene_view* scnview; /* Current view of the instantiated scene */
+ /* Current view of the instantiated scene. Note that the instance does not
+ * own the scnview; the instance scnview lifetime is managed by the scnview
+ * into which the instance lies */
+ struct s3d_scene_view* scnview;
ref_T ref;
};
diff --git a/src/s3d_scene_view.c b/src/s3d_scene_view.c
@@ -505,7 +505,8 @@ scene_view_register_instance
{
struct geometry** pgeom = NULL;
struct geometry* geom = NULL;
- struct s3d_scene_view* instance_scnview = NULL;
+ struct s3d_scene_view** pview = NULL;
+ struct s3d_scene_view* view = NULL;
unsigned shape_id;
res_T res = RES_OK;
ASSERT(scnview && shape && shape->type == GEOM_INSTANCE);
@@ -517,14 +518,23 @@ scene_view_register_instance
goto error;
}
- /* Recursively create a scnview on the scene to instantiate */
- res = s3d_scene_view_create
- (shape->data.instance->scene, mask, &instance_scnview);
- if(res != RES_OK) goto error;
+ /* Recursively create scnview on the scene to instantiate if necessary */
+ pview = htable_instview_find
+ (&scnview->instviews, &shape->data.instance->scene);
+ if(pview) {
+ view = *pview;
+ } else {
+ res = s3d_scene_view_create
+ (shape->data.instance->scene, mask, &view);
+ if(res != RES_OK) goto error;
+ res = htable_instview_set
+ (&scnview->instviews, &shape->data.instance->scene, &view);
+ if(res != RES_OK) goto error;
+ }
+ /* Create the scene instance of the geometry if necessary */
S3D(shape_get_id(shape, &shape_id));
pgeom = htable_geom_find(&scnview->cached_geoms, &shape_id);
- /* Create the scene instance of the geometry if necessary */
if(pgeom) {
geom = *pgeom;
} else {
@@ -538,7 +548,7 @@ scene_view_register_instance
geom->name = shape->id.index;
}
ASSERT(geom->data.instance->scene == shape->data.instance->scene);
- geom->data.instance->scnview = instance_scnview;
+ geom->data.instance->scnview = view;
/* Update the Embree instance transformation if necessary */
if(!f33_eq(shape->data.instance->transform, geom->data.instance->transform)
@@ -577,8 +587,7 @@ scene_view_compute_cdf(struct s3d_scene_view* scnview)
while(!htable_geom_iterator_eq(&it, &end)) {
const unsigned* shape_id = htable_geom_iterator_key_get(&it);
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
+ struct geometry* geom = *htable_geom_iterator_data_get(&it);
struct fltui fltui;
htable_geom_iterator_next(&it);
@@ -636,8 +645,7 @@ scene_view_compute_nprims_cdf
nprims = 0;
while(!htable_geom_iterator_eq(&it, &end)) {
const unsigned* shape_id = htable_geom_iterator_key_get(&it);
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
+ struct geometry* geom = *htable_geom_iterator_data_get(&it);
struct nprims_cdf cdf;
htable_geom_iterator_next(&it);
@@ -691,8 +699,7 @@ scene_view_compute_scene_aabb(struct s3d_scene_view* scnview)
while(!htable_geom_iterator_eq(&it, &end)) {
struct instance* inst;
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
+ struct geometry* geom = *htable_geom_iterator_data_get(&it);
htable_geom_iterator_next(&it);
@@ -731,8 +738,7 @@ scene_view_compute_volume
volume = 0.f;
while(!htable_geom_iterator_eq(&it, &end)) {
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
+ struct geometry* geom = *htable_geom_iterator_data_get(&it);
const char flip = geom->flip_surface ^ flip_surface;
htable_geom_iterator_next(&it);
@@ -841,6 +847,7 @@ scene_view_create(struct s3d_scene* scn, struct s3d_scene_view** out_scnview)
darray_geom_init(scn->dev->allocator, &scnview->embree2geoms);
darray_fltui_init(scn->dev->allocator, &scnview->cdf);
darray_nprims_cdf_init(scn->dev->allocator, &scnview->nprims_cdf);
+ htable_instview_init(scn->dev->allocator, &scnview->instviews);
darray_uint_init(scn->dev->allocator, &scnview->detached_shapes);
f3_splat(scnview->lower, FLT_MAX);
f3_splat(scnview->upper,-FLT_MAX);
@@ -866,25 +873,31 @@ error:
static void
scene_view_release(ref_T* ref)
{
- struct htable_geom_iterator it, end;
+ struct htable_instview_iterator it_view, end_view;
+ struct htable_geom_iterator it_geom, end_geom;
struct s3d_scene_view* scnview = CONTAINER_OF(ref, struct s3d_scene_view, ref);
size_t i, n;
ASSERT(ref);
/* Release the scnview of the instances */
- htable_geom_begin(&scnview->cached_geoms, &it);
- htable_geom_end(&scnview->cached_geoms, &end);
- while(!htable_geom_iterator_eq(&it, &end)) {
- struct geometry** pgeom = htable_geom_iterator_data_get(&it);
- struct geometry* geom = *pgeom;
- htable_geom_iterator_next(&it);
-
- if(geom->type == GEOM_INSTANCE) {
- if(geom->data.instance->scnview) {
- S3D(scene_view_ref_put(geom->data.instance->scnview));
- geom->data.instance->scnview = NULL;
- }
- }
+ htable_instview_begin(&scnview->instviews, &it_view);
+ htable_instview_end(&scnview->instviews, &end_view);
+ while(!htable_instview_iterator_eq(&it_view, &end_view)) {
+ struct s3d_scene_view* view = *htable_instview_iterator_data_get(&it_view);
+ htable_instview_iterator_next(&it_view);
+ S3D(scene_view_ref_put(view));
+ }
+ htable_instview_clear(&scnview->instviews);
+
+ /* Reset the scnview of the cached instance. Note that this step is actually
+ * not necessary but this reset is "appreciated" in debug */
+ htable_geom_begin(&scnview->cached_geoms, &it_geom);
+ htable_geom_end(&scnview->cached_geoms, &end_geom);
+ while(!htable_geom_iterator_eq(&it_geom, &end_geom)) {
+ struct geometry* geom = *htable_geom_iterator_data_get(&it_geom);
+ htable_geom_iterator_next(&it_geom);
+ if(geom->type != GEOM_INSTANCE) continue;
+ geom->data.instance->scnview = NULL;
}
/* Remove the geometry of the shapes detached while the scnview was active */
@@ -1423,6 +1436,7 @@ scene_view_destroy(struct s3d_scene_view* scnview)
darray_geom_release(&scnview->embree2geoms);
darray_fltui_release(&scnview->cdf);
darray_nprims_cdf_release(&scnview->nprims_cdf);
+ htable_instview_release(&scnview->instviews);
darray_uint_release(&scnview->detached_shapes);
/* Remove the scnview from its pool */
diff --git a/src/s3d_scene_view_c.h b/src/s3d_scene_view_c.h
@@ -79,6 +79,12 @@ struct nprims_cdf { unsigned nprims, ishape; };
#define DARRAY_DATA struct nprims_cdf
#include <rsys/dynamic_array.h>
+/* Generate the htable_instview hash table */
+#define HTABLE_NAME instview
+#define HTABLE_DATA struct s3d_scene_view*
+#define HTABLE_KEY struct s3d_scene*
+#include <rsys/hash_table.h>
+
struct s3d_scene_view {
struct list_node node; /* Attachment point to the scene scene_views pool */
@@ -87,6 +93,9 @@ struct s3d_scene_view {
struct darray_fltui cdf; /* Unormalized CDF */
struct darray_nprims_cdf nprims_cdf;
+ /* Map an instantiated scene to its scene view */
+ struct htable_instview instviews;
+
/* Id of Shapes detached while the scnview is active */
struct darray_uint detached_shapes;
@@ -95,7 +104,7 @@ struct s3d_scene_view {
/* Callback attached to the sig_shape_detach signal of scn */
scene_shape_cb_T on_shape_detach_cb;
- int mask; /* Combinatin of enum s3d_scene_view_flag */
+ int mask; /* Combination of enum s3d_scene_view_flag */
int rtc_scn_update; /* Define if Embree geometries were deleted/added */
RTCScene rtc_scn; /* Embree scene */
diff --git a/src/test_s3d_trace_ray_instance.c b/src/test_s3d_trace_ray_instance.c
@@ -293,7 +293,8 @@ test_cbox(struct s3d_device* dev, const char* filename)
img[ipix+1] = 0;
img[ipix+2] = 0;
} else {
- float normal[3], col[3], dot;
+ float normal[3] = {0.f, 0.f, 0.f};
+ float col[3], dot;
float f = (float)hit.prim.inst_id / (float)(N*N);
f3(col, f, MMAX(0.f, 1.f-f), MMAX(0.f, 1.f-f));
@@ -315,6 +316,7 @@ test_cbox(struct s3d_device* dev, const char* filename)
}
CHECK(s3d_scene_view_ref_put(view), RES_OK);
+ /* Write image */
if(img) {
CHECK(image_ppm_write(filename, img_sz[0], img_sz[1], 3, img), RES_OK);
mem_rm(img);