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 a63dff51e8352dcd954149d0113cda3a1286a215
parent 20bc8f1d138782a48a2dc41f047a293d9d7c6c16
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 27 Mar 2015 15:42:35 +0100

Refactoring of the back-end geometry

Diffstat:
Asrc/s3d_geometry.h | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/s3d_instance.c | 5++---
Msrc/s3d_instance.h | 5++---
Msrc/s3d_mesh.c | 5++---
Msrc/s3d_mesh.h | 4++--
Msrc/s3d_scene.c | 109++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/s3d_shape.c | 12++++++++----
7 files changed, 124 insertions(+), 69 deletions(-)

diff --git a/src/s3d_geometry.h b/src/s3d_geometry.h @@ -0,0 +1,53 @@ +/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) + * + * This software is a computer program whose purpose is to describe a + * virtual 3D environment that can be ray-traced and sampled both robustly + * and efficiently. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. */ + +#ifndef S3D_GEOMETRY_H +#define S3D_GEOMETRY_H + +#include "s3d_backend.h" + +/* Backend geometry */ +struct geometry { + unsigned irtc; /* Embree geometry identifier */ + char is_enabled; +}; + +static FINLINE void +geometry_init(struct geometry* geom) +{ + ASSERT(geom); + geom->irtc = RTC_INVALID_GEOMETRY_ID; + geom->is_enabled = 1; +} + +#endif /* S3D_GEOMETRY_H */ + diff --git a/src/s3d_instance.c b/src/s3d_instance.c @@ -49,7 +49,7 @@ instance_release(ref_T* ref) ASSERT(ref); inst = CONTAINER_OF(ref, struct instance, ref); scn = inst->scene; - ASSERT(inst->rtc_geom == RTC_INVALID_GEOMETRY_ID); + ASSERT(inst->geom.irtc == RTC_INVALID_GEOMETRY_ID); MEM_FREE(scn->dev->allocator, inst); S3D(scene_ref_put(scn)); } @@ -75,8 +75,7 @@ instance_create f33_set_identity(inst->transform); /* rotation */ f3_splat(inst->transform + 9, 0.f); /* Translation */ inst->update_transform = 0; - inst->is_enabled = 1; - inst->rtc_geom = RTC_INVALID_GEOMETRY_ID; + geometry_init(&inst->geom); ref_init(&inst->ref); S3D(scene_ref_get(scn)); inst->scene = scn; diff --git a/src/s3d_instance.h b/src/s3d_instance.h @@ -33,14 +33,13 @@ #ifndef S3D_INSTANCE_H #define S3D_INSTANCE_H +#include "s3d_geometry.h" #include <rsys/ref_count.h> struct instance { float transform[12]; /* local to world 3x4 column major matrix */ char update_transform; - - char is_enabled; - unsigned rtc_geom; + struct geometry geom; struct s3d_scene* scene; ref_T ref; diff --git a/src/s3d_mesh.c b/src/s3d_mesh.c @@ -215,7 +215,7 @@ mesh_release(ref_T* ref) mesh = CONTAINER_OF(ref, struct mesh, ref); mesh_clear(mesh); dev = mesh->dev; - ASSERT(mesh->rtc_geom == RTC_INVALID_GEOMETRY_ID); + ASSERT(mesh->geom.irtc == RTC_INVALID_GEOMETRY_ID); MEM_FREE(dev->allocator, mesh); S3D(device_ref_put(dev)); } @@ -235,8 +235,7 @@ mesh_create(struct s3d_device* dev, struct mesh** out_mesh) res = RES_MEM_ERR; goto error; } - mesh->rtc_geom = RTC_INVALID_GEOMETRY_ID; - mesh->is_enabled = 1; + geometry_init(&mesh->geom); ref_init(&mesh->ref); S3D(device_ref_get(dev)); mesh->dev = dev; diff --git a/src/s3d_mesh.h b/src/s3d_mesh.h @@ -33,6 +33,7 @@ #include "s3d.h" #include "s3d_buffer.h" +#include "s3d_geometry.h" #include <rsys/dynamic_array_u32.h> #include <rsys/dynamic_array_float.h> @@ -64,8 +65,7 @@ struct mesh { /* Triangular mesh */ int resize_mask; /* Combination of buffer_type */ int update_mask; /* Combination of buffer_type */ - char is_enabled; - unsigned rtc_geom; /* Embree geometry */ + struct geometry geom; struct s3d_device* dev; ref_T ref; diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -48,28 +48,47 @@ scene_build (struct s3d_scene* scn, const enum build_type type); +static INLINE void +scene_geometry_flush_enable_state + (struct s3d_scene* scn, + struct geometry* cache, /* Cached value */ + const struct geometry* curr) /* New value */ +{ + ASSERT(scn && cache && curr); + if(cache->is_enabled == curr->is_enabled) + return; + + cache->is_enabled = curr->is_enabled; + if(curr->is_enabled) { + rtcEnable(scn->rtc_scn, cache->irtc); + } else { + rtcDisable(scn->rtc_scn, cache->irtc); + } + scn->is_rtc_scn_outdated = 1; +} + static res_T scene_build_register_mesh(struct s3d_scene* scn, struct mesh* mesh) { ASSERT(scn && mesh); /* Create the Embree geometry if it is not valid */ - if(mesh->rtc_geom == RTC_INVALID_GEOMETRY_ID) { - mesh->rtc_geom = rtcNewTriangleMesh(scn->rtc_scn, RTC_GEOMETRY_DYNAMIC, + if(mesh->geom.irtc == RTC_INVALID_GEOMETRY_ID) { + mesh->geom.irtc = rtcNewTriangleMesh(scn->rtc_scn, RTC_GEOMETRY_DYNAMIC, mesh_get_ntris(mesh), mesh_get_nverts(mesh)); - if(mesh->rtc_geom == RTC_INVALID_GEOMETRY_ID) + if(mesh->geom.irtc == RTC_INVALID_GEOMETRY_ID) return RES_UNKNOWN_ERR; scn->is_rtc_scn_outdated = 1; } - if(mesh->rtc_geom >= darray_geom2mesh_size_get(&scn->geom2mesh)) { - res_T res = darray_geom2mesh_resize(&scn->geom2mesh, mesh->rtc_geom + 1); + if(mesh->geom.irtc >= darray_geom2mesh_size_get(&scn->geom2mesh)) { + res_T res = darray_geom2mesh_resize(&scn->geom2mesh, mesh->geom.irtc + 1); if(res != RES_OK) { - rtcDeleteGeometry(scn->rtc_scn, mesh->rtc_geom); - mesh->rtc_geom = RTC_INVALID_GEOMETRY_ID; + rtcDeleteGeometry(scn->rtc_scn, mesh->geom.irtc); + mesh->geom.irtc = RTC_INVALID_GEOMETRY_ID; return res; } mesh_ref_get(mesh); - darray_geom2mesh_data_get(&scn->geom2mesh)[mesh->rtc_geom] = mesh; + darray_geom2mesh_data_get(&scn->geom2mesh)[mesh->geom.irtc] = mesh; } return RES_OK; } @@ -81,22 +100,22 @@ scene_build_register_instance(struct s3d_scene* scn, struct instance* inst) /* The instance should not contain instances */ ASSERT(!darray_geom2inst_size_get(&inst->scene->geom2inst)); - if(inst->rtc_geom == RTC_INVALID_GEOMETRY_ID) { - inst->rtc_geom = rtcNewInstance(scn->rtc_scn, inst->scene->rtc_scn); - if(inst->rtc_geom == RTC_INVALID_GEOMETRY_ID) + if(inst->geom.irtc == RTC_INVALID_GEOMETRY_ID) { + inst->geom.irtc = rtcNewInstance(scn->rtc_scn, inst->scene->rtc_scn); + if(inst->geom.irtc == RTC_INVALID_GEOMETRY_ID) return RES_UNKNOWN_ERR; scn->is_rtc_scn_outdated = 1; } - if(inst->rtc_geom >= darray_geom2inst_size_get(&scn->geom2inst)) { - res_T res = darray_geom2inst_resize(&scn->geom2inst, inst->rtc_geom + 1); + if(inst->geom.irtc >= darray_geom2inst_size_get(&scn->geom2inst)) { + res_T res = darray_geom2inst_resize(&scn->geom2inst, inst->geom.irtc + 1); if(res != RES_OK) { - rtcDeleteGeometry(scn->rtc_scn, inst->rtc_geom); - inst->rtc_geom = RTC_INVALID_GEOMETRY_ID; + rtcDeleteGeometry(scn->rtc_scn, inst->geom.irtc); + inst->geom.irtc = RTC_INVALID_GEOMETRY_ID; return res; } instance_ref_get(inst); - darray_geom2inst_data_get(&scn->geom2inst)[inst->rtc_geom] = inst; + darray_geom2inst_data_get(&scn->geom2inst)[inst->geom.irtc] = inst; } return RES_OK; } @@ -155,9 +174,9 @@ scene_setup_shape_mesh /* Discard the shape mesh that is not geometrically valid */ if(!shape->data.mesh->indices || !shape->data.mesh->attribs[S3D_POSITION]) { - if(mesh->rtc_geom != RTC_INVALID_GEOMETRY_ID) { - rtcDeleteGeometry(scn->rtc_scn, mesh->rtc_geom); - mesh->rtc_geom = RTC_INVALID_GEOMETRY_ID; + if(mesh->geom.irtc != RTC_INVALID_GEOMETRY_ID) { + rtcDeleteGeometry(scn->rtc_scn, mesh->geom.irtc); + mesh->geom.irtc = RTC_INVALID_GEOMETRY_ID; scn->is_rtc_scn_outdated = 1; } mesh_clear(mesh); @@ -199,9 +218,9 @@ scene_setup_shape_mesh } /* The shape mesh was resize => the Embree geometry is no more valid */ - if(shape->data.mesh->resize_mask && mesh->rtc_geom!=RTC_INVALID_GEOMETRY_ID) { - rtcDeleteGeometry(scn->rtc_scn, mesh->rtc_geom); - mesh->rtc_geom = RTC_INVALID_GEOMETRY_ID; + if(shape->data.mesh->resize_mask && mesh->geom.irtc != RTC_INVALID_GEOMETRY_ID) { + rtcDeleteGeometry(scn->rtc_scn, mesh->geom.irtc); + mesh->geom.irtc = RTC_INVALID_GEOMETRY_ID; scn->is_rtc_scn_outdated = 1; } @@ -209,28 +228,19 @@ scene_setup_shape_mesh if(res != RES_OK) goto error; if(upd_pos) { /* Update the Embree vertex buffer if necessary */ - rtcSetBuffer(scn->rtc_scn, mesh->rtc_geom, RTC_VERTEX_BUFFER, + rtcSetBuffer(scn->rtc_scn, mesh->geom.irtc, RTC_VERTEX_BUFFER, mesh_get_pos(mesh), 0, sizeof(float[3])); - rtcUpdateBuffer(scn->rtc_scn, mesh->rtc_geom, RTC_VERTEX_BUFFER); + rtcUpdateBuffer(scn->rtc_scn, mesh->geom.irtc, RTC_VERTEX_BUFFER); scn->is_rtc_scn_outdated = 1; } if(upd_ids) { /* Update the Embree index buffer if necessary */ - rtcSetBuffer(scn->rtc_scn, mesh->rtc_geom, RTC_INDEX_BUFFER, + rtcSetBuffer(scn->rtc_scn, mesh->geom.irtc, RTC_INDEX_BUFFER, mesh_get_ids(mesh), 0, sizeof(uint32_t[3])); - rtcUpdateBuffer(scn->rtc_scn, mesh->rtc_geom, RTC_INDEX_BUFFER); + rtcUpdateBuffer(scn->rtc_scn, mesh->geom.irtc, RTC_INDEX_BUFFER); scn->is_rtc_scn_outdated = 1; } - /* Setup the is_enabled state */ - if(mesh->is_enabled != shape->data.mesh->is_enabled) { - mesh->is_enabled = shape->data.mesh->is_enabled; - if(shape->data.mesh->is_enabled) { - rtcEnable(scn->rtc_scn, mesh->rtc_geom); - } else { - rtcDisable(scn->rtc_scn, mesh->rtc_geom); - } - scn->is_rtc_scn_outdated = 1; - } + scene_geometry_flush_enable_state(scn, &mesh->geom, &shape->data.mesh->geom); /* Flush the shape mesh states */ shape->data.mesh->resize_mask = 0; @@ -283,23 +293,14 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) if(shape->data.instance->update_transform) { rtcSetTransform (scn->rtc_scn, - inst->rtc_geom, + inst->geom.irtc, RTC_MATRIX_COLUMN_MAJOR, inst->transform); scn->is_rtc_scn_outdated = 1; } - /* Setup the is_enabled state */ - if(inst->is_enabled != shape->data.instance->is_enabled) { - inst->is_enabled = shape->data.instance->is_enabled; - if(shape->data.instance->is_enabled) { - rtcEnable(scn->rtc_scn, inst->rtc_geom); - } else { - rtcDisable(scn->rtc_scn, inst->rtc_geom); - } - scn->is_rtc_scn_outdated = 1; - } - + scene_geometry_flush_enable_state + (scn, &inst->geom, &shape->data.instance->geom); shape->data.instance->update_transform = 0; /* Flush instance state */ exit: @@ -318,9 +319,9 @@ scene_detach_shape_mesh(struct s3d_scene* scn, struct s3d_shape* shape) pmesh = htable_mesh_find(&scn->meshes, &shape); if(pmesh) { /* The shape mesh is cached into the scene */ struct mesh* mesh = *pmesh; - if(mesh->rtc_geom != RTC_INVALID_GEOMETRY_ID) { - rtcDeleteGeometry(scn->rtc_scn, mesh->rtc_geom); - mesh->rtc_geom = RTC_INVALID_GEOMETRY_ID; + if(mesh->geom.irtc != RTC_INVALID_GEOMETRY_ID) { + rtcDeleteGeometry(scn->rtc_scn, mesh->geom.irtc); + mesh->geom.irtc = RTC_INVALID_GEOMETRY_ID; } mesh_ref_put(mesh); htable_mesh_erase(&scn->meshes, &shape); @@ -339,9 +340,9 @@ scene_detach_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) pinst = htable_inst_find(&scn->instances, &shape); if(pinst) { /* The shape instance is cached into the scene */ struct instance* inst = *pinst; - if(inst->rtc_geom != RTC_INVALID_GEOMETRY_ID) { - rtcDeleteGeometry(scn->rtc_scn, inst->rtc_geom); - inst->rtc_geom = RTC_INVALID_GEOMETRY_ID; + if(inst->geom.irtc != RTC_INVALID_GEOMETRY_ID) { + rtcDeleteGeometry(scn->rtc_scn, inst->geom.irtc); + inst->geom.irtc = RTC_INVALID_GEOMETRY_ID; } instance_ref_put(inst); htable_inst_erase(&scn->instances, &shape); diff --git a/src/s3d_shape.c b/src/s3d_shape.c @@ -169,8 +169,8 @@ s3d_shape_enable(struct s3d_shape* shape, const char enable) { if(!shape) return RES_BAD_ARG; switch(shape->type) { - case SHAPE_MESH: shape->data.mesh->is_enabled = enable; break; - case SHAPE_INSTANCE: shape->data.instance->is_enabled = enable; break; + case SHAPE_MESH: shape->data.mesh->geom.is_enabled = enable; break; + case SHAPE_INSTANCE: shape->data.instance->geom.is_enabled = enable; break; default: FATAL("Unreachable code\n"); break; } return RES_OK; @@ -181,8 +181,12 @@ s3d_shape_is_enabled(struct s3d_shape* shape, char* is_enabled) { if(!shape || !is_enabled) return RES_BAD_ARG; switch(shape->type) { - case SHAPE_MESH: *is_enabled = shape->data.mesh->is_enabled; break; - case SHAPE_INSTANCE: *is_enabled = shape->data.instance->is_enabled; break; + case SHAPE_MESH: + *is_enabled = shape->data.mesh->geom.is_enabled; + break; + case SHAPE_INSTANCE: + *is_enabled = shape->data.instance->geom.is_enabled; + break; default: FATAL("Unreachable code\n"); break; } return RES_OK;