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 25dc3f8917156a7ce84106c89d5b410cac3f5005
parent 1219563e93d695ab07744ae34880dba33bef8999
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 20 Mar 2015 10:15:48 +0100

Add the support of instantiated scenes into another scene

Diffstat:
Msrc/s3d_scene.c | 146++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/s3d_scene_c.h | 2+-
Msrc/s3d_shape.c | 38+++++++++++++++++++++++++-------------
Msrc/s3d_shape_c.h | 9+++++++--
4 files changed, 133 insertions(+), 62 deletions(-)

diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -36,6 +36,7 @@ #include "s3d_shape_c.h" #include <rsys/float3.h> +#include <rsys/float33.h> #include <rsys/mem_allocator.h> #include <rsys/mutex.h> @@ -54,6 +55,90 @@ delete_rtc_geometry(struct s3d_scene* scn, struct s3d_shape* shape) } static res_T +shape_mesh_setup(struct s3d_scene* scn, struct s3d_shape* shape) +{ + uint32_t* ids; + float* pos; + size_t ntris, nverts; + res_T res; + ASSERT(scn && shape && shape->type == SHAPE_MESH); + + ids = darray_u32_data_get(&shape->data.mesh.indices); + pos = darray_float_data_get(&shape->data.mesh.attribs[S3D_POSITION]); + ntris = darray_u32_size_get(&shape->data.mesh.indices)/3; + nverts = darray_float_size_get(&shape->data.mesh.attribs[S3D_POSITION])/3; + + mutex_rw_rlock(shape->lock); /* Prevent concurrent shape update */ + + /* The Embree geometry is no more valid */ + if(shape->data.mesh.resize_mask + && shape->rtc_geom != RTC_INVALID_GEOMETRY_ID) { + rtcDeleteGeometry(scn->rtc_scn, shape->rtc_geom); + shape->rtc_geom = RTC_INVALID_GEOMETRY_ID; + shape->data.mesh.resize_mask = 0; + } + if(shape->rtc_geom != RTC_INVALID_GEOMETRY_ID) { + /* Update the Embree geometry if required */ + if(shape->data.mesh.update_mask & MESH_INDEX_BUFFER) + rtcUpdateBuffer(scn->rtc_scn, shape->rtc_geom, RTC_INDEX_BUFFER); + if(shape->data.mesh.update_mask & MESH_VERTEX_BUFFER) + rtcUpdateBuffer(scn->rtc_scn, shape->rtc_geom, RTC_VERTEX_BUFFER); + shape->data.mesh.update_mask = 0; + } else { + /* Setup a new Embree geometry */ + shape->rtc_geom = rtcNewTriangleMesh + (scn->rtc_scn, RTC_GEOMETRY_STATIC, ntris, nverts); + rtcSetBuffer(scn->rtc_scn, shape->rtc_geom, RTC_INDEX_BUFFER, ids, 0, + sizeof(uint32_t[3])); + rtcSetBuffer(scn->rtc_scn, shape->rtc_geom, RTC_VERTEX_BUFFER, pos, 0, + sizeof(float[3])); + + /* Map the Embree geometry to its shape */ + if(shape->rtc_geom >= darray_geom2shape_size_get(&scn->geom2shape)) { + res = darray_geom2shape_resize(&scn->geom2shape, shape->rtc_geom+1); + if(res != RES_OK) { + mutex_rw_unlock(shape->lock); + return res; + } + } + darray_geom2shape_data_get(&scn->geom2shape)[shape->rtc_geom] = shape; + } + mutex_rw_unlock(shape->lock); + + return RES_OK; +} + +static res_T +scene_setup(struct s3d_scene* scn); + +static res_T +shape_instance_setup(struct s3d_scene* scn, struct s3d_shape* shape) +{ + res_T res; + ASSERT(scn && shape && shape->type == SHAPE_INSTANCE); + + /* Recursuvely update the scene */ + res = scene_setup(shape->data.instance.scene); + if(res != RES_OK) return res; + + mutex_rw_rlock(shape->lock); + + if(shape->rtc_geom == RTC_INVALID_GEOMETRY_ID) { + shape->rtc_geom = rtcNewInstance + (scn->rtc_scn, shape->data.instance.scene->rtc_scn); + } + if(shape->data.instance.update_transform) { + rtcSetTransform + (scn->rtc_scn, + shape->rtc_geom, + RTC_MATRIX_COLUMN_MAJOR, + shape->data.instance.transform); + } + + mutex_rw_unlock(shape->lock); +} + +res_T scene_setup(struct s3d_scene* scn) { struct list_node* node; @@ -63,51 +148,17 @@ scene_setup(struct s3d_scene* scn) LIST_FOR_EACH(node, &scn->shapes) { struct s3d_shape* shape = CONTAINER_OF (node, struct s3d_shape, scene_attachment); - uint32_t* ids = darray_u32_data_get(&shape->data.mesh.indices); - float* pos = darray_float_data_get(&shape->data.mesh.attribs[S3D_POSITION]); - const size_t ntris = darray_u32_size_get(&shape->data.mesh.indices)/3; - const size_t nverts = darray_float_size_get - (&shape->data.mesh.attribs[S3D_POSITION])/3; - - mutex_rw_rlock(shape->lock); /* Prevent concurrent shape update */ - - if(shape->type != SHAPE_MESH) - FATAL("Unsupported shape type\n"); - - /* The Embree geometry is no more valid */ - if(shape->data.mesh.resize_mask - && shape->rtc_geom != RTC_INVALID_GEOMETRY_ID) { - rtcDeleteGeometry(scn->rtc_scn, shape->rtc_geom); - shape->rtc_geom = RTC_INVALID_GEOMETRY_ID; - shape->data.mesh.resize_mask = 0; + switch(shape->type) { + case SHAPE_INSTANCE: + FATAL("Unsupported shape type\n"); + break; + case SHAPE_MESH: + res = shape_mesh_setup(scn, shape); + break; + default: FATAL("Unreachable code\n"); break; } - - if(shape->rtc_geom != RTC_INVALID_GEOMETRY_ID) { - /* Update the Embree geometry if required */ - if(shape->data.mesh.update_mask & MESH_INDEX_BUFFER) - rtcUpdateBuffer(scn->rtc_scn, shape->rtc_geom, RTC_INDEX_BUFFER); - if(shape->data.mesh.update_mask & MESH_VERTEX_BUFFER) - rtcUpdateBuffer(scn->rtc_scn, shape->rtc_geom, RTC_VERTEX_BUFFER); - shape->data.mesh.update_mask = 0; - } else { - /* Setup a new Embree geometry */ - shape->rtc_geom = rtcNewTriangleMesh - (scn->rtc_scn, RTC_GEOMETRY_STATIC, ntris, nverts); - rtcSetBuffer(scn->rtc_scn, shape->rtc_geom, RTC_INDEX_BUFFER, ids, 0, - sizeof(uint32_t[3])); - rtcSetBuffer(scn->rtc_scn, shape->rtc_geom, RTC_VERTEX_BUFFER, pos, 0, - sizeof(float[3])); - - if(shape->rtc_geom >= darray_geom2shape_size_get(&scn->geom2shape)) { - res = darray_geom2shape_resize(&scn->geom2shape, shape->rtc_geom+1); - if(res != RES_OK) { - mutex_rw_unlock(shape->lock); - goto error; - } - } - darray_geom2shape_data_get(&scn->geom2shape)[shape->rtc_geom] = shape; - } - mutex_rw_unlock(shape->lock); + if(res != RES_OK) + goto error; } exit: @@ -241,7 +292,10 @@ s3d_scene_instantiate(struct s3d_scene* scn, struct s3d_shape** out_shape) shape->type = SHAPE_INSTANCE; S3D(scene_ref_get(scn)); - shape->data.scene = scn; + f33_set_identity(shape->data.instance.transform); /* Rotation */ + f3_splat(shape->data.instance.transform + 9, 0); /* Translation */ + shape->data.instance.scene = scn; + shape->data.instance.update_transform = 0; *out_shape = shape; return RES_OK; } @@ -309,7 +363,7 @@ s3d_scene_build(struct s3d_scene* scn) /* Prevent concurrent ray tracing */ mutex_rw_wlock(scn->lock_rtc); - if(scn->is_outdated) { + if(ATOMIC_GET(&scn->is_outdated)) { res = scene_setup(scn); rtcCommit(scn->rtc_scn); scn->is_outdated = res != RES_OK; diff --git a/src/s3d_scene_c.h b/src/s3d_scene_c.h @@ -47,7 +47,7 @@ struct s3d_scene { struct list_node shapes; /* List of attached shapes */ struct darray_geom2shape geom2shape; RTCScene rtc_scn; - char is_outdated; /* Flag defining if the scene description was updated */ + int is_outdated; /* Flag defining if the scene description was updated */ struct mutex* lock; struct mutex_rw* lock_rtc; diff --git a/src/s3d_shape.c b/src/s3d_shape.c @@ -238,7 +238,7 @@ shape_release_data(struct s3d_shape* shape) switch(shape->type) { case SHAPE_MESH: mesh_release(&shape->data.mesh); break; case SHAPE_NONE: /* Do nothing */ break; - case SHAPE_INSTANCE: S3D(scene_ref_put(shape->data.scene)); break; + case SHAPE_INSTANCE: S3D(scene_ref_put(shape->data.instance.scene)); break; default: FATAL("Unreachable code\n"); break; } shape->type = SHAPE_NONE; @@ -295,7 +295,6 @@ shape_create(struct s3d_device* dev, struct s3d_shape** out_shape) S3D(device_ref_get(dev)); shape->dev = dev; ref_init(&shape->ref); - f33_set_identity(shape->transform); shape->lock = mutex_rw_create(); if(!shape->lock) { res = RES_MEM_ERR; @@ -386,9 +385,15 @@ s3d_shape_instance_set_position if(!shape || shape->type != SHAPE_INSTANCE || !position) return RES_BAD_ARG; mutex_rw_wlock(shape->lock); - shape->transform[9] = -f3_dot(f33_row(axis, shape->transform, 0), position); - shape->transform[10] = -f3_dot(f33_row(axis, shape->transform, 1), position); - shape->transform[11] = -f3_dot(f33_row(axis, shape->transform, 2), position); + 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; + if(shape->scn) + ATOMIC_SET(&shape->scn->is_outdated, 1); mutex_rw_unlock(shape->lock); return RES_OK; } @@ -404,12 +409,22 @@ s3d_shape_instance_translate if(space == S3D_LOCAL_TRANSFORM) { float vec[3]; mutex_rw_wlock(shape->lock); - f33_mulf3(vec, shape->transform, translation); /* Trans in local space */ - f3_add(shape->transform + 9, shape->transform + 9, vec); + f33_mulf3(vec, shape->data.instance.transform, translation); + f3_add + (shape->data.instance.transform + 9, + shape->data.instance.transform + 9, + vec); + shape->data.instance.update_transform = 1; + if(shape->scn) ATOMIC_SET(&shape->scn->is_outdated, 1); mutex_rw_unlock(shape->lock); } else if(space == S3D_WORLD_TRANSFORM) { mutex_rw_wlock(shape->lock); - f3_add(shape->transform + 9, shape->transform + 9, translation); + f3_add + (shape->data.instance.transform + 9, + shape->data.instance.transform + 9, + translation); + shape->data.instance.update_transform = 1; + if(shape->scn) ATOMIC_SET(&shape->scn->is_outdated, 1); mutex_rw_unlock(shape->lock); } else { return RES_BAD_ARG; @@ -489,11 +504,8 @@ s3d_shape_mesh_setup_indexed_vertices } } - if(shape->scn) {/* Notify the shape update */ - mutex_lock(shape->scn->lock); - shape->scn->is_outdated = 1; - mutex_unlock(shape->scn->lock); - } + if(shape->scn) /* Notify the shape update */ + ATOMIC_SET(&shape->scn->is_outdated, 1); exit: mutex_rw_unlock(shape->lock); diff --git a/src/s3d_shape_c.h b/src/s3d_shape_c.h @@ -65,16 +65,21 @@ struct mesh { /* Triangular mesh */ int resize_mask; /* Define which shape buffers were [re]allocateod */ }; +struct instance { + struct s3d_scene* scene; + float transform[12]; /* local to world 3x4 column major matrix */ + int update_transform; /* Define if the transform matrix was updated or not */ +}; + struct s3d_shape { struct list_node scene_attachment; enum shape_type type; unsigned rtc_geom; /* Embree geometry id */ struct s3d_scene* scn; /* The scene on which the shape is attached */ struct mutex_rw* lock; - float transform[12]; /* 3x4 column major transformation */ union { - struct s3d_scene* scene; + struct instance instance; struct mesh mesh; } data;