commit 19795ca5e55ceeb47974b199c54e851943844713
parent a61ec8fbab4c568c4345370a6e53a2eda1c79c4b
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 9 Sep 2015 09:17:41 +0200
Begin the refactoring of the shape and scene build
Diffstat:
7 files changed, 317 insertions(+), 194 deletions(-)
diff --git a/src/s3d_geometry.c b/src/s3d_geometry.c
@@ -0,0 +1,108 @@
+/* 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. */
+
+#include "s3d_geometry.h"
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static void
+geometry_release(ref_T* ref)
+{
+ struct geometry* geom;
+ struct s3d_device* dev;
+
+ geom = CONTAINER_OF(ref, struct geometry, ref);
+ dev = geom->dev;
+ switch(geom->type) {
+ case GEOM_MESH:
+ if(geom->data.mesh) mesh_ref_put(geom->data.mesh);
+ break;
+ case GEOM_INSTANCE:
+ if(geom->data.instance) instance_ref_put(geom->data.instance);
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ MEM_RM(dev->allocator, geom);
+ S3D(device_ref_put(dev));
+}
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+res_T
+geometry_create
+ (struct s3d_device* dev,
+ struct geometry** out_geom)
+{
+ struct geometry* geom = NULL;
+ ASSERT(dev && out_geom);
+
+ geom = MEM_CALLOC(dev->allocator, 1, sizeof(struct geometry));
+ if(!geom) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+
+ geom->name = S3D_INVALID_ID;
+ geom->irtc = RTC_INVALID_GEOMETRY_ID;
+ geom->flip_surface = 0;
+ geom->is_enabled = 1;
+ geom->type = GEOM_NONE;
+ geom->data.mesh = NULL;
+
+exit:
+ *out_geom = geom;
+ return res;
+error:
+ if(geom) {
+ geometry_ref_put(geom);
+ geom = NULL;
+ }
+ goto exit;
+}
+
+void
+geometry_ref_get(struct geometry* geom)
+{
+ ASSERT(geom);
+ ref_get(&geom->ref);
+}
+
+void
+geometry_ref_put(struct geometry* geom)
+{
+ ASSERT(geom);
+ ref_put(&geom->ref, release);
+}
+
+
diff --git a/src/s3d_geometry.h b/src/s3d_geometry.h
@@ -35,19 +35,42 @@
#include "s3d_backend.h"
+enum geometry_type {
+ GEOM_MESH,
+ GEOM_INSTANCE,
+ GEOM_TYPES_COUNT__,
+ GEOM_NONE = SHAPE_TYPES_COUNT__
+};
+
/* Backend geometry */
struct geometry {
- unsigned irtc; /* Embree geometry identifier */
- char is_enabled;
+ unsigned name; /* Client side identifier */
+ unsigned irtc; /* Embree identifier */
+ char flip_surface; /* Is the geometry surface flipped? */
+ char is_enabled; /* Is the geometry enabled? */
+
+ enum geometry_type type;
+ union {
+ struct instance* instance;
+ struct mesh* mesh;
+ } data;
+
+ struct s3d_device* dev;
+ ref_T ref;
};
-static FINLINE void
-geometry_init(struct geometry* geom)
-{
- ASSERT(geom);
- geom->irtc = RTC_INVALID_GEOMETRY_ID;
- geom->is_enabled = 1;
-}
+extern LOCAL_SYM res_T
+geometry_create
+ (struct s3d_device* dev,
+ struct geometry** geom);
+
+extern LOCAL_SYM res_T
+geometry_ref_get
+ (struct geometry* geometry);
+
+extern LOCAL_SYM res_T
+geometry_ref_put
+ (struct geometry* geometry);
#endif /* S3D_GEOMETRY_H */
diff --git a/src/s3d_mesh.h b/src/s3d_mesh.h
@@ -61,15 +61,8 @@ struct mesh { /* Triangular mesh */
struct index_buffer* indices;
struct vertex_buffer* attribs[S3D_ATTRIBS_COUNT__];
enum s3d_type attribs_type[S3D_ATTRIBS_COUNT__];
-
int resize_mask; /* Combination of buffer_type */
int update_mask; /* Combination of buffer_type */
-
- struct geometry geom;
- char flip_surface;
-
- unsigned id; /* Unique identifier of a mesh */
-
struct s3d_device* dev;
ref_T ref;
};
diff --git a/src/s3d_scene.c b/src/s3d_scene.c
@@ -68,50 +68,50 @@ scene_geometry_flush_enable_state
}
static res_T
-scene_build_register_mesh(struct s3d_scene* scn, struct mesh* mesh)
+scene_build_register_mesh(struct s3d_scene* scn, struct geometry* geom)
{
- ASSERT(scn && mesh);
+ ASSERT(scn && geom && geom->type == GEOM_MESH);
/* Create the Embree geometry if it is not valid */
- 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->geom.irtc == RTC_INVALID_GEOMETRY_ID)
+ if(geom->irtc == RTC_INVALID_GEOMETRY_ID) {
+ geom->irtc = rtcNewTriangleMesh(scn->rtc_scn, RTC_GEOMETRY_DYNAMIC,
+ mesh_get_ntris(geom->data.mesh), mesh_get_nverts(geom->data.mesh));
+ if(geom->irtc == RTC_INVALID_GEOMETRY_ID)
return RES_UNKNOWN_ERR;
scn->is_rtc_scn_outdated = 1;
}
- if(mesh->geom.irtc >= darray_mesh_size_get(&scn->meshes)) {
- res_T res = darray_mesh_resize(&scn->meshes, mesh->geom.irtc + 1);
+ if(geom->irtc >= darray_mesh_size_get(&scn->meshes)) {
+ res_T res = darray_mesh_resize(&scn->meshes, geom->irtc + 1);
if(res != RES_OK) {
- rtcDeleteGeometry(scn->rtc_scn, mesh->geom.irtc);
- mesh->geom.irtc = RTC_INVALID_GEOMETRY_ID;
+ rtcDeleteGeometry(scn->rtc_scn, geom->irtc);
+ geom->irtc = RTC_INVALID_GEOMETRY_ID;
return res;
}
}
- mesh_ref_get(mesh);
- darray_mesh_data_get(&scn->meshes)[mesh->geom.irtc] = mesh;
+ geometry_ref_get(geom);
+ darray_mesh_data_get(&scn->meshes)[geom->irtc] = geom;
return RES_OK;
}
static res_T
-scene_build_register_instance(struct s3d_scene* scn, struct instance* inst)
+scene_build_register_instance(struct s3d_scene* scn, struct geometry* geom)
{
- ASSERT(scn && inst && inst->scene);
+ ASSERT(scn && geom && inst->scene);
/* The instance should not contain instances */
ASSERT(!darray_inst_size_get(&inst->scene->instances));
- 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)
+ if(geom->irtc == RTC_INVALID_GEOMETRY_ID) {
+ geom->irtc = rtcNewInstance(scn->rtc_scn, geom->data.instance->scene->rtc_scn);
+ if(geom.irtc == RTC_INVALID_GEOMETRY_ID)
return RES_UNKNOWN_ERR;
scn->is_rtc_scn_outdated = 1;
}
- if(inst->geom.irtc >= darray_inst_size_get(&scn->instances)) {
- res_T res = darray_inst_resize(&scn->instances, inst->geom.irtc + 1);
+ if(geom->irtc >= darray_inst_size_get(&scn->instances)) {
+ res_T res = darray_inst_resize(&scn->instances, geom->irtc + 1);
if(res != RES_OK) {
- rtcDeleteGeometry(scn->rtc_scn, inst->geom.irtc);
- inst->geom.irtc = RTC_INVALID_GEOMETRY_ID;
+ rtcDeleteGeometry(scn->rtc_scn, geom->irtc);
+ geom->irtc = RTC_INVALID_GEOMETRY_ID;
return res;
}
}
@@ -152,88 +152,91 @@ scene_setup_shape_mesh
(struct s3d_scene* scn,
struct s3d_shape* shape)
{
- struct mesh** pmesh = NULL;
- struct mesh* mesh = NULL;
+ struct geometry** pgeom = NULL;
+ struct geometry* geom = NULL;
size_t iattr;
char upd_pos, upd_ids;
res_T res = RES_OK;
ASSERT(shape && shape->type == SHAPE_MESH);
- /* Retrieve the cached shape mesh */
- pmesh = htable_mesh_find(&scn->cached_meshes, &shape);
- if(pmesh) {
- mesh = *pmesh;
+ /* Retrieve the cached geometry */
+ pgeom = htable_geom_find(&scn->cached_geoms, &shape);
+ if(pgeom) {
+ geom = *pgeom;
} else {
- res = mesh_create(scn->dev, &mesh);
+ res = geometry_create(scn->dev, &geom);
+ if(res != RES_OK) goto error;
+ res = mesh_create(scn->dev, &geom->data.mesh);
if(res != RES_OK) goto error;
- res = htable_mesh_set(&scn->cached_meshes, &shape, &mesh);
+ geom->type = GEOM_MESH;
+ res = htable_geom_set(&scn->cached_geoms, &shape, &geom);
if(res != RES_OK) goto error;
- mesh->id = shape->name.index;
+ geom->name = shape->name.index;
}
- /* Discard the shape mesh that is not geometrically valid */
+ /* Discard the geometry that is not geometrically valid */
if(!shape->data.mesh->indices || !shape->data.mesh->attribs[S3D_POSITION]) {
- if(mesh->geom.irtc != RTC_INVALID_GEOMETRY_ID) {
- rtcDeleteGeometry(scn->rtc_scn, mesh->geom.irtc);
- mesh->geom.irtc = RTC_INVALID_GEOMETRY_ID;
+ if(geom->irtc != RTC_INVALID_GEOMETRY_ID) {
+ rtcDeleteGeometry(scn->rtc_scn, geom->irtc);
+ geom->irtc = RTC_INVALID_GEOMETRY_ID;
scn->is_rtc_scn_outdated = 1;
}
- mesh_clear(mesh);
+ mesh_clear(geom->mesh);
goto exit;
}
/* Define which Embree geometry buffer must be updated */
- upd_ids = mesh->indices != shape->data.mesh->indices
+ upd_ids = geom->data.mesh->indices != shape->data.mesh->indices
|| ((shape->data.mesh->update_mask & INDEX_BUFFER) != 0);
- upd_pos = mesh->attribs[S3D_POSITION] != shape->data.mesh->attribs[S3D_POSITION]
+ upd_pos = geom->data.mesh->attribs[S3D_POSITION] != shape->data.mesh->attribs[S3D_POSITION]
|| ((shape->data.mesh->update_mask == VERTEX_BUFFER) != 0);
/* Get a reference onto the shape mesh indices */
- if(mesh->indices != shape->data.mesh->indices) {
- if(mesh->indices) {
- index_buffer_ref_put(mesh->indices);
- mesh->indices = NULL;
+ if(geom->data.mesh->indices != shape->data.mesh->indices) {
+ if(geom->data.mesh->indices) {
+ index_buffer_ref_put(geom->data.mesh->indices);
+ geom->data.mesh->indices = NULL;
}
ASSERT(shape->data.mesh->indices);
index_buffer_ref_get(shape->data.mesh->indices);
- mesh->indices = shape->data.mesh->indices;
+ geom->data.mesh->indices = shape->data.mesh->indices;
}
/* Get the reference onto the shape mesh attribs */
FOR_EACH(iattr, 0, S3D_ATTRIBS_COUNT__) {
- if(mesh->attribs[iattr] == shape->data.mesh->attribs[iattr])
+ if(geom->data.mesh->attribs[iattr] == shape->data.mesh->attribs[iattr])
continue;
- if(mesh->attribs[iattr]) {
- vertex_buffer_ref_put(mesh->attribs[iattr]);
- mesh->attribs[iattr] = NULL;
+ if(geom->data.mesh->attribs[iattr]) {
+ vertex_buffer_ref_put(geom->data.mesh->attribs[iattr]);
+ geom->data.mesh->attribs[iattr] = NULL;
}
if(!shape->data.mesh->attribs[iattr])
continue;
vertex_buffer_ref_get(shape->data.mesh->attribs[iattr]);
- mesh->attribs[iattr] = shape->data.mesh->attribs[iattr];
- mesh->attribs_type[iattr] = shape->data.mesh->attribs_type[iattr];
+ geom->data.mesh->attribs[iattr] = shape->data.mesh->attribs[iattr];
+ geom->data.mesh->attribs_type[iattr] = shape->data.mesh->attribs_type[iattr];
}
/* The shape mesh was resize => the Embree geometry is no more valid */
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;
+ rtcDeleteGeometry(scn->rtc_scn, geom->data.mesh->geom.irtc);
+ geom->data.mesh->geom.irtc = RTC_INVALID_GEOMETRY_ID;
scn->is_rtc_scn_outdated = 1;
}
/* Update the cached mesh states */
- mesh->flip_surface = shape->data.mesh->flip_surface;
+ geom->data.mesh->flip_surface = shape->data.mesh->flip_surface;
- res = scene_build_register_mesh(scn, mesh);
+ res = scene_build_register_mesh(scn, geom);
if(res != RES_OK) goto error;
if(upd_pos) { /* Update the Embree vertex buffer if necessary */
- rtcSetBuffer(scn->rtc_scn, mesh->geom.irtc, RTC_VERTEX_BUFFER,
- mesh_get_pos(mesh), 0, sizeof(float[3]));
- rtcUpdateBuffer(scn->rtc_scn, mesh->geom.irtc, RTC_VERTEX_BUFFER);
+ rtcSetBuffer(scn->rtc_scn, geom->irtc, RTC_VERTEX_BUFFER,
+ mesh_get_pos(geom->data.mesh), 0, sizeof(float[3]));
+ rtcUpdateBuffer(scn->rtc_scn, geom->irtc, RTC_VERTEX_BUFFER);
scn->is_rtc_scn_outdated = 1;
}
if(upd_ids) { /* Update the Embree index buffer if necessary */
@@ -258,33 +261,36 @@ error:
static res_T
scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape)
{
- struct instance** pinst = NULL;
- struct instance* inst = NULL;
+ struct geometry** pgeom = NULL;
+ struct geometry* geom = NULL;
res_T res = RES_OK;
- ASSERT(scn && shape && shape->type == SHAPE_INSTANCE);
+ ASSERT(scn && shape && shape->type == GEOM_INSTANCE);
/* Recursuvely update the scene */
res = scene_build(shape->data.instance->scene, BUILD_INDIRECT);
if(res != RES_OK) goto error;
- pinst = htable_inst_find(&scn->cached_instances, &shape);
- /* Create the scene instance of the shape if necessary */
- if(pinst) {
- inst = *pinst;
+ pgeom = htable_inst_find(&scn->cached_geoms, &shape);
+ /* Create the scene instance of the geometry if necessary */
+ if(pgeom) {
+ geom = *pgeom;
} else {
- res = instance_create(shape->data.instance->scene, &inst);
+ res = geometry_create(scn->dev, &geom);
+ if(res != RES_OK) goto error;
+ geom->type = GEOM_INSTANCE;
+ res = instance_create(shape->data.instance->scene, &geom->data.instance);
if(res != RES_OK) goto error;
- res = htable_inst_set(&scn->cached_instances, &shape, &inst);
+ res = htable_inst_set(&scn->cached_geoms, &shape, &geom);
if(res != RES_OK) goto error;
- inst->id = shape->name.index;
+ geom->id = shape->name.index;
}
/* Update the cached instance states */
- 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);
- inst->flip_surface = shape->data.instance->flip_surface;
+ ASSERT(geom->data.inst->scene == shape->data.instance->scene);
+ f33_set(geom->data.inst->transform, shape->data.instance->transform);
+ f3_set(geom->data.instance->transform + 9, shape->data.instance->transform + 9);
+ geom->data.instance->flip_surface = shape->flip_surface;
- /* The instance cannot contain instances */
+ /* TODO The instance cannot contain instances */
if(darray_inst_size_get(&inst->scene->instances)) {
res = RES_BAD_ARG;
goto error;
@@ -295,7 +301,7 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape)
if(res != RES_OK) goto error;
/* Update the Embree instance transformation */
- if(shape->data.instance->update_transform) {
+ if(geom->data.instance->update_transform) {
rtcSetTransform
(scn->rtc_scn,
inst->geom.irtc,
@@ -305,7 +311,7 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape)
}
scene_geometry_flush_enable_state
- (scn, &inst->geom, &shape->data.instance->geom);
+ (scn, geom, &shape->data.instance->geom);
shape->data.instance->update_transform = 0; /* Flush instance state */
exit:
@@ -369,6 +375,50 @@ scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
}
static res_T
+scene_compute_shape_cdf(struct s3d_scene* scn)
+{
+ struct list_node* node;
+ ASSERT(scn);
+
+ LIST_FOR_EACH(node, &scn->shapes) {
+
+ const size_t ntris = mesh_get_ntris(mesh);
+ const uint32_t* ids = mesh_get_ids(mesh);
+ const float* verts = mesh_get_pos(mesh);
+ size_t itri;
+ float area;
+
+ ASSERT(shape->type == SHAPE_MESH);
+
+ area = 0.f;
+ FOR_EACH(itri, 0, ntris) {
+ int i;
+ const float* positions[3];
+ float edges[2][3], normal[3];
+ float triangle_area;
+
+ FOR_EACH(i, 0, 3) { /* Fetch vertex positions */
+ const uint32_t id = ids[itri * 3 + i];
+ ASSERT(id < mesh_get_nverts(shape->data.mesh));
+ positions[i] = verts + id * 3/*#coords*/;
+ }
+
+ /* Compute triangle area. Note that actually, we compute the double of
+ * the triangle area since it saves computation times whithout affecting
+ * the sampling result */
+ f3_sub(edges[0], positions[1], positions[0]);
+ f3_sub(edges[1], positions[2], positions[0]);
+ f3_cross(normal, edges[0], edges[1]);
+ triangle_area = f3_len(normal);
+
+ /* Store the CDF value of the triangle `itri' */
+ area += triangle_area;
+ darray_float_push_back(&triangles_cdf, &area);
+ }
+ }
+}
+
+static res_T
scene_build(struct s3d_scene* scn, const enum build_type type)
{
struct list_node* node;
@@ -383,9 +433,9 @@ scene_build(struct s3d_scene* scn, const enum build_type type)
LIST_FOR_EACH(node, &scn->shapes) {
struct s3d_shape* shape = CONTAINER_OF
(node, struct s3d_shape, scene_attachment);
- switch(shape->type) {
- case SHAPE_INSTANCE: res = scene_setup_shape_instance(scn, shape); break;
- case SHAPE_MESH: res = scene_setup_shape_mesh(scn, shape); break;
+ switch(shape->geom.type) {
+ case SHAPE_INSTANCE: res = scene_setup_instance(scn, &shape->geom); break;
+ case SHAPE_MESH: res = scene_setup_mesh(scn, &shape->geom); break;
default: FATAL("Unreachable code\n"); break;
}
if(res != RES_OK)
@@ -443,8 +493,7 @@ s3d_scene_create(struct s3d_device* dev, struct s3d_scene** out_scn)
goto error;
}
list_init(&scn->shapes);
- htable_mesh_init(dev->allocator, &scn->cached_meshes);
- htable_inst_init(dev->allocator, &scn->cached_instances);
+ htable_geom_init(dev->allocator, &scn->cached_geoms);
darray_mesh_init(dev->allocator, &scn->meshes);
darray_inst_init(dev->allocator, &scn->instances);
ref_init(&scn->ref);
@@ -498,12 +547,13 @@ s3d_scene_instantiate(struct s3d_scene* scn, struct s3d_shape** out_shape)
res = RES_BAD_ARG;
goto error;
}
+
res = shape_create(scn->dev, &shape);
if(res != RES_OK)
goto error;
- shape->type = SHAPE_INSTANCE;
- res = instance_create(scn, &shape->data.instance);
+ shape->geom.type = GEOM_MESH_INSTANCE;
+ res = instance_create(scn, &shape->geom.data.instance);
if(res != RES_OK)
goto error;
diff --git a/src/s3d_scene_c.h b/src/s3d_scene_c.h
@@ -41,46 +41,28 @@
#include <rsys/ref_count.h>
/*
- * The mesh/instance pointers must be initialized to NULL in order to define
+ * The geometry pointers must be initialized to NULL in order to define
* which pointers are valid or not
*/
static FINLINE void
-mesh_ptr_init__(struct mem_allocator* alloc, struct mesh** mesh)
+geom_ptr_init__(struct mem_allocator* alloc, struct geometry** geom)
{
- (void)alloc; *mesh = NULL;
+ (void)alloc; *geom = NULL;
}
-static FINLINE void
-instance_ptr_init__(struct mem_allocator* alloc, struct instance** inst)
-{
- (void)alloc; *inst = NULL;
-}
-
-/* Generate the darray_mesh dynamic array */
-#define DARRAY_NAME mesh
-#define DARRAY_DATA struct mesh*
-#define DARRAY_FUNCTOR_INIT mesh_ptr_init__
-#include <rsys/dynamic_array.h>
-
-/* Generate the darray_inst dynamic array */
-#define DARRAY_NAME inst
-#define DARRAY_DATA struct instance*
-#define DARRAY_FUNCTOR_INIT instance_ptr_init__
+/* Generate the darray_geom dynamic array */
+#define DARRAY_NAME geom
+#define DARRAY_DATA struct geometry*
+#define DARRAY_FUNCTOR_INIT geom_ptr_init__
#include <rsys/dynamic_array.h>
/* Generate the htable_mesh hash table */
-#define HTABLE_NAME mesh
-#define HTABLE_DATA struct mesh*
-#define HTABLE_KEY struct s3d_shape*
-#include <rsys/hash_table.h>
-
-/* Generate the htable_instance hash table */
-#define HTABLE_NAME inst
-#define HTABLE_DATA struct instance*
+#define HTABLE_NAME geom
+#define HTABLE_DATA struct geometry*
#define HTABLE_KEY struct s3d_shape*
#include <rsys/hash_table.h>
-enum build_type {
+enum sync_type {
BUILD_NONE, /* The scene is not built */
BUILD_DIRECT, /* The scene is directly build */
BUILD_INDIRECT /* The scene is build as an instance */
@@ -88,12 +70,11 @@ enum build_type {
struct s3d_scene {
struct list_node shapes; /* List of attached shapes */
- struct htable_mesh cached_meshes; /* Cached shape meshes */
- struct htable_inst cached_instances; /* Cached shape instances */
+ struct htable_mesh cached_geoms; /* Cached shape geometries */
/* Active geometry. Indexed by the Embree identifier */
- struct darray_mesh meshes;
- struct darray_inst instances;
+ struct darray_geom meshes;
+ struct darray_geom instances;
RTCScene rtc_scn;
char is_rtc_scn_outdated;
diff --git a/src/s3d_shape.c b/src/s3d_shape.c
@@ -42,25 +42,6 @@
* Helper functions
******************************************************************************/
static void
-shape_release_data(struct s3d_shape* shape)
-{
- ASSERT(shape);
- switch(shape->type) {
- case SHAPE_MESH:
- if(shape->data.mesh)
- mesh_ref_put(shape->data.mesh);
- break;
- case SHAPE_NONE: /* Do nothing */ 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;
-}
-
-static void
shape_release(ref_T* ref)
{
struct s3d_shape* shape;
@@ -71,8 +52,16 @@ shape_release(ref_T* ref)
/* The shape should not be attached */
ASSERT(is_list_empty(&shape->scene_attachment));
- flist_name_del(&dev->names, shape->name);
- shape_release_data(shape);
+ if(shape->type != GEOM_NONE) {
+ switch(shape->type) {
+ case GEOM_MESH:
+ if(shape->data.mesh) mesh_ref_put(shape->data.mesh);
+ break;
+ case GEOM_INSTANCE:
+ if(shape->data.instance) instance_ref_put(shape->data.instance);
+ break;
+ }
+ }
MEM_RM(dev->allocator, shape);
S3D(device_ref_put(dev));
}
@@ -100,7 +89,8 @@ shape_create(struct s3d_device* dev, struct s3d_shape** out_shape)
S3D(device_ref_get(dev));
shape->dev = dev;
ref_init(&shape->ref);
- shape->name = flist_name_add(&dev->names);
+ shape->fid = flist_name_add(&dev->names);
+ shape->type = GEOM_NONE;
exit:
if(out_shape) *out_shape = shape;
@@ -133,11 +123,11 @@ s3d_shape_create_mesh
if(res != RES_OK)
goto error;
+ shape->type = GEOM_MESH;
res = mesh_create(dev, &shape->data.mesh);
if(res != RES_OK)
goto error;
- shape->type = SHAPE_MESH;
exit:
if(out_shape)
*out_shape = shape;
@@ -178,11 +168,7 @@ res_T
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->geom.is_enabled = enable; break;
- case SHAPE_INSTANCE: shape->data.instance->geom.is_enabled = enable; break;
- default: FATAL("Unreachable code\n"); break;
- }
+ shape->is_enabled = enable;
return RES_OK;
}
@@ -190,23 +176,14 @@ res_T
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->geom.is_enabled;
- break;
- case SHAPE_INSTANCE:
- *is_enabled = shape->data.instance->geom.is_enabled;
- break;
- default: FATAL("Unreachable code\n"); break;
- }
+ *is_enabled = shape->is_enabled;
return RES_OK;
}
res_T
s3d_shape_is_attached(struct s3d_shape* shape, char* is_attached)
{
- if(!shape || !is_attached)
- return RES_BAD_ARG;
+ if(!shape || !is_attached) return RES_BAD_ARG;
*is_attached = !is_list_empty(&shape->scene_attachment);
return RES_OK;
}
@@ -214,26 +191,20 @@ s3d_shape_is_attached(struct s3d_shape* shape, char* is_attached)
res_T
s3d_shape_flip_surface(struct s3d_shape* shape)
{
- if(!shape)
- return RES_BAD_ARG;
- switch(shape->type) {
- case SHAPE_MESH: shape->data.mesh->flip_surface ^= 1; break;
- case SHAPE_INSTANCE: shape->data.instance->flip_surface ^= 1; break;
- default: FATAL("Unreachable code\n"); break;
- }
+ if(!shape) return RES_BAD_ARG;
+ shape->flip_surface ^= 1;
return RES_OK;
}
res_T
s3d_shape_primitives_count(struct s3d_shape* shape, size_t* nprims)
{
- if(!shape || !nprims)
- return RES_BAD_ARG;
+ if(!shape || !nprims) return RES_BAD_ARG;
switch(shape->type) {
- case SHAPE_MESH:
+ case GEOM_MESH:
*nprims = mesh_get_ntris(shape->data.mesh);
break;
- case SHAPE_INSTANCE:
+ case GEOM_INSTANCE:
*nprims = instance_get_ntris(shape->data.instance);
break;
default: FATAL("Unreachable code\n"); break;
@@ -247,10 +218,10 @@ s3d_shape_compute_area(struct s3d_shape* shape, float* area)
if(!shape || !area)
return RES_BAD_ARG;
switch(shape->type) {
- case SHAPE_MESH:
+ case GEOM_MESH:
*area = mesh_compute_area(shape->data.mesh);
break;
- case SHAPE_INSTANCE:
+ case GEOM_INSTANCE:
*area = instance_compute_area(shape->data.instance);
break;
default: FATAL("Unreachable code\n"); break;
@@ -264,10 +235,10 @@ s3d_shape_compute_volume(struct s3d_shape* shape, float* volume)
if(!shape || !volume)
return RES_BAD_ARG;
switch(shape->type) {
- case SHAPE_MESH:
+ case GEOM_MESH:
*volume = mesh_compute_volume(shape->data.mesh, 0);
break;
- case SHAPE_INSTANCE:
+ case GEOM_INSTANCE:
*volume = instance_compute_volume(shape->data.instance);
break;
default: FATAL("Unreachable code \n"); break;
@@ -280,7 +251,7 @@ s3d_instance_set_position
(struct s3d_shape* shape, const float position[3])
{
float axis[3];
- if(!shape || shape->type != SHAPE_INSTANCE || !position)
+ if(!shape || shape->type != GEOM_INSTANCE || !position)
return RES_BAD_ARG;
shape->data.instance->transform[9] =
f3_dot(f33_row(axis, shape->data.instance->transform, 0), position);
@@ -298,7 +269,7 @@ s3d_instance_translate
const enum s3d_transform_space space,
const float translation[3])
{
- if(!shape || shape->type != SHAPE_INSTANCE || !translation)
+ if(!shape || shape->type != GEOM_INSTANCE || !translation)
return RES_BAD_ARG;
if(space == S3D_LOCAL_TRANSFORM) {
float vec[3];
@@ -329,8 +300,9 @@ s3d_mesh_setup_indexed_vertices
struct s3d_vertex_data attribs[],
void* data)
{
- if(!shape || shape->type != SHAPE_MESH)
+ if(!shape || shape->type != GEOM_MESH)
return RES_BAD_ARG;
return mesh_setup_indexed_vertices
(shape->data.mesh, ntris, get_indices, nverts, attribs, data);
}
+
diff --git a/src/s3d_shape_c.h b/src/s3d_shape_c.h
@@ -44,20 +44,16 @@
#include <limits.h>
-enum shape_type {
- SHAPE_MESH,
- SHAPE_INSTANCE,
- SHAPE_TYPES_COUNT__,
- SHAPE_NONE = SHAPE_TYPES_COUNT__
-};
-
struct s3d_shape {
struct list_node scene_attachment;
- enum shape_type type;
- struct fid name;
+ struct fid id;
+
+ char flip_surface;
+ char is_enabled;
+ enum geometry_type type;
union {
- struct instance* instance;
+ struct instance* instance;
struct mesh* mesh;
} data;