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:
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;