commit 1014b516425347daf33c0e11aecc262336e076e6
parent 19795ca5e55ceeb47974b199c54e851943844713
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 9 Sep 2015 10:27:10 +0200
First functionnal version of s3d_<shape|scene> refactoring
The sampler API is not implemented yet
Diffstat:
11 files changed, 173 insertions(+), 249 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -63,6 +63,7 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(S3D_FILES_SRC
s3d_device.c
+ s3d_geometry.c
s3d_instance.c
s3d_mesh.c
s3d_primitive.c
@@ -75,8 +76,8 @@ set(S3D_FILES_INC
s3d_backend.h
s3d_buffer.h
s3d_device_c.h
- s3d_instance.h
s3d_geometry.h
+ s3d_instance.h
s3d_mesh.h
s3d_shape_c.h)
set(S3D_FILES_DOC COPYING.fr COPYING.en README.md)
@@ -128,7 +129,7 @@ if(NOT NO_TEST)
endfunction(new_test)
new_test(test_s3d_device)
- new_test(test_s3d_sampler)
+ # new_test(test_s3d_sampler)
new_test(test_s3d_scene)
new_test(test_s3d_shape)
new_test(test_s3d_trace_ray)
diff --git a/src/s3d_geometry.c b/src/s3d_geometry.c
@@ -30,7 +30,12 @@
* 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_device_c.h"
#include "s3d_geometry.h"
+#include "s3d_instance.h"
+#include "s3d_mesh.h"
+
+#include <rsys/mem_allocator.h>
/*******************************************************************************
* Helper functions
@@ -65,14 +70,18 @@ geometry_create
struct geometry** out_geom)
{
struct geometry* geom = NULL;
+ res_T res = RES_OK;
ASSERT(dev && out_geom);
- geom = MEM_CALLOC(dev->allocator, 1, sizeof(struct geometry));
+ geom = (struct geometry*)MEM_CALLOC
+ (dev->allocator, 1, sizeof(struct geometry));
if(!geom) {
res = RES_MEM_ERR;
goto error;
}
-
+ ref_init(&geom->ref);
+ S3D(device_ref_get(dev));
+ geom->dev = dev;
geom->name = S3D_INVALID_ID;
geom->irtc = RTC_INVALID_GEOMETRY_ID;
geom->flip_surface = 0;
@@ -102,7 +111,7 @@ void
geometry_ref_put(struct geometry* geom)
{
ASSERT(geom);
- ref_put(&geom->ref, release);
+ ref_put(&geom->ref, geometry_release);
}
diff --git a/src/s3d_geometry.h b/src/s3d_geometry.h
@@ -34,12 +34,13 @@
#define S3D_GEOMETRY_H
#include "s3d_backend.h"
+#include <rsys/ref_count.h>
enum geometry_type {
GEOM_MESH,
GEOM_INSTANCE,
GEOM_TYPES_COUNT__,
- GEOM_NONE = SHAPE_TYPES_COUNT__
+ GEOM_NONE = GEOM_TYPES_COUNT__
};
/* Backend geometry */
@@ -64,11 +65,11 @@ geometry_create
(struct s3d_device* dev,
struct geometry** geom);
-extern LOCAL_SYM res_T
+extern LOCAL_SYM void
geometry_ref_get
(struct geometry* geometry);
-extern LOCAL_SYM res_T
+extern LOCAL_SYM void
geometry_ref_put
(struct geometry* geometry);
diff --git a/src/s3d_instance.c b/src/s3d_instance.c
@@ -50,7 +50,6 @@ instance_release(ref_T* ref)
ASSERT(ref);
inst = CONTAINER_OF(ref, struct instance, ref);
scn = inst->scene;
- ASSERT(inst->geom.irtc == RTC_INVALID_GEOMETRY_ID);
MEM_RM(scn->dev->allocator, inst);
S3D(scene_ref_put(scn));
}
@@ -76,7 +75,6 @@ instance_create
f33_set_identity(inst->transform); /* rotation */
f3_splat(inst->transform + 9, 0.f); /* Translation */
inst->update_transform = 0;
- geometry_init(&inst->geom);
ref_init(&inst->ref);
S3D(scene_ref_get(scn));
inst->scene = scn;
@@ -114,10 +112,10 @@ instance_get_ntris(struct instance* inst)
struct s3d_shape* shape = CONTAINER_OF
(node, struct s3d_shape, scene_attachment);
switch(shape->type) {
- case SHAPE_INSTANCE:
+ case GEOM_INSTANCE:
ntris += instance_get_ntris(shape->data.instance);
break;
- case SHAPE_MESH:
+ case GEOM_MESH:
ntris += mesh_get_ntris(shape->data.mesh);
break;
default: FATAL("Unreachable code\n"); break;
@@ -133,18 +131,15 @@ instance_compute_area(struct instance* inst)
float area = 0.f;
ASSERT(inst);
- if(!inst->geom.is_enabled)
- return 0.f;
-
/* TODO take into account the scale factor of the instance */
LIST_FOR_EACH(node, &inst->scene->shapes) {
struct s3d_shape* shape = CONTAINER_OF
(node, struct s3d_shape, scene_attachment);
switch(shape->type) {
- case SHAPE_INSTANCE:
+ case GEOM_INSTANCE:
area += instance_compute_area(shape->data.instance);
break;
- case SHAPE_MESH:
+ case GEOM_MESH:
area += mesh_compute_area(shape->data.mesh);
break;
default: FATAL("Unreachable code\n"); break;
@@ -154,25 +149,23 @@ instance_compute_area(struct instance* inst)
}
float
-instance_compute_volume(struct instance* inst)
+instance_compute_volume(struct instance* inst, const char flip_surface)
{
struct list_node* node;
float volume = 0.f;
ASSERT(inst);
-
- if(!inst->geom.is_enabled)
- return 0.f;
/* TODO take into account the scale factor of the instance */
LIST_FOR_EACH(node, &inst->scene->shapes) {
struct s3d_shape* shape = CONTAINER_OF
(node, struct s3d_shape, scene_attachment);
+ const char flip = flip_surface ^ shape->flip_surface;
switch(shape->type) {
- case SHAPE_INSTANCE:
- volume += instance_compute_volume(shape->data.instance);
+ case GEOM_INSTANCE:
+ volume += instance_compute_volume(shape->data.instance, flip);
break;
- case SHAPE_MESH:
- volume += mesh_compute_volume(shape->data.mesh, inst->flip_surface);
+ case GEOM_MESH:
+ volume += mesh_compute_volume(shape->data.mesh, flip);
break;
default: FATAL("Unreachable code\n"); break;
}
diff --git a/src/s3d_instance.h b/src/s3d_instance.h
@@ -39,12 +39,6 @@
struct instance {
float transform[12]; /* local to world 3x4 column major matrix */
char update_transform;
- char flip_surface;
-
- struct geometry geom;
-
- unsigned id; /* Unique identifier of an instance */
-
struct s3d_scene* scene;
ref_T ref;
};
@@ -72,7 +66,8 @@ instance_compute_area
extern LOCAL_SYM float
instance_compute_volume
- (struct instance* inst);
+ (struct instance* inst,
+ const char flip_surface); /* Flip the instance surfaces or not */
#endif /* S3D_INSTANCE_H */
diff --git a/src/s3d_mesh.c b/src/s3d_mesh.c
@@ -217,7 +217,6 @@ mesh_release(ref_T* ref)
mesh = CONTAINER_OF(ref, struct mesh, ref);
mesh_clear(mesh);
dev = mesh->dev;
- ASSERT(mesh->geom.irtc == RTC_INVALID_GEOMETRY_ID);
MEM_RM(dev->allocator, mesh);
S3D(device_ref_put(dev));
}
@@ -237,7 +236,6 @@ mesh_create(struct s3d_device* dev, struct mesh** out_mesh)
res = RES_MEM_ERR;
goto error;
}
- geometry_init(&mesh->geom);
ref_init(&mesh->ref);
S3D(device_ref_get(dev));
mesh->dev = dev;
@@ -342,8 +340,7 @@ mesh_compute_area(struct mesh* mesh)
ASSERT(mesh);
ntris = mesh_get_ntris(mesh);
- if(!ntris || !mesh->geom.is_enabled)
- return 0.f;
+ if(!ntris) return 0.f;
ids = mesh_get_ids(mesh);
pos = mesh_get_pos(mesh);
@@ -368,16 +365,13 @@ mesh_compute_volume(struct mesh* mesh, const char flip_surface)
const float* pos;
size_t itri, ntris;
double volume = 0.0;
- char flip;
ASSERT(mesh);
ntris = mesh_get_ntris(mesh);
- if(!ntris || !mesh->geom.is_enabled)
- return 0.f;
+ if(!ntris) return 0.f;
ids = mesh_get_ids(mesh);
pos = mesh_get_pos(mesh);
- flip = mesh->flip_surface ^ flip_surface;
/* Build a tetrahedron whose face is the mesh triangle and its appex is the
* origin. Then compute the volume of the tetrahedron and add or sub it from
@@ -392,7 +386,7 @@ mesh_compute_volume(struct mesh* mesh, const char flip_surface)
/* Front face is CW by default */
f3_sub(E0, v2, v0);
f3_sub(E1, v1, v0);
- if(flip) {
+ if(flip_surface) {
f3_cross(N, E1, E0);
} else {
f3_cross(N, E0, E1);
diff --git a/src/s3d_primitive.c b/src/s3d_primitive.c
@@ -48,7 +48,7 @@ s3d_primitive_get_attrib
struct s3d_attrib* attrib)
{
const uint32_t* ids;
- struct mesh* mesh = NULL;
+ struct geometry* geom_mesh = NULL;
const float* transform = NULL;
char flip_surface = 0;
float w;
@@ -63,33 +63,32 @@ s3d_primitive_get_attrib
return RES_BAD_ARG;
if(prim->inst__ == NULL) {
- mesh = (struct mesh*)prim->mesh__;
- flip_surface = mesh->flip_surface;
+ geom_mesh = (struct geometry*)prim->mesh__;
+ flip_surface = geom_mesh->flip_surface;
} else {
- const struct instance* inst = (const struct instance*)prim->inst__;
- ASSERT(prim->inst_id == inst->id);
- mesh = (struct mesh*)prim->mesh__;
- transform = inst->transform;
- if(!mesh) {
- res = RES_BAD_ARG;
- goto error;
- }
- flip_surface = inst->flip_surface ^ mesh->flip_surface;
+ const struct geometry* geom_inst = (const struct geometry*)prim->inst__;
+ ASSERT(geom_inst->type == GEOM_INSTANCE);
+ ASSERT(prim->inst_id == geom_inst->name);
+ geom_mesh = (struct geometry*)prim->mesh__;
+ transform = geom_inst->data.instance->transform;
+ ASSERT(geom_mesh);
+ flip_surface = geom_inst->flip_surface ^ geom_mesh->flip_surface;
}
- ASSERT(prim->geom_id == mesh->id);
+ ASSERT(prim->geom_id == geom_mesh->name);
+ ASSERT(geom_mesh->type == GEOM_MESH);
/* The mesh haven't the required mesh attrib */
- if(usage != S3D_GEOMETRY_NORMAL && !mesh->attribs[usage]) {
+ if(usage != S3D_GEOMETRY_NORMAL && !geom_mesh->data.mesh->attribs[usage]) {
res = RES_BAD_ARG;
goto error;
}
/* Out of bound primitive index */
- if(prim->prim_id >= mesh_get_ntris(mesh)) {
+ if(prim->prim_id >= mesh_get_ntris(geom_mesh->data.mesh)) {
res = RES_BAD_ARG;
goto error;
}
- ids = mesh_get_ids(mesh) + prim->prim_id * 3/*#ids per triangle*/;
+ ids = mesh_get_ids(geom_mesh->data.mesh) + prim->prim_id * 3/*#triangle ids*/;
attrib->usage = usage;
if(usage == S3D_POSITION || usage == S3D_GEOMETRY_NORMAL) {
@@ -97,7 +96,7 @@ s3d_primitive_get_attrib
const float* pos;
attrib->type = S3D_FLOAT3;
/* Fetch data */
- pos = mesh_get_pos(mesh);
+ pos = mesh_get_pos(geom_mesh->data.mesh);
v0 = pos + ids[0] * 3;
v1 = pos + ids[1] * 3;
v2 = pos + ids[2] * 3;
@@ -131,10 +130,10 @@ s3d_primitive_get_attrib
const float* attr;
const float* v0, *v1, *v2;
unsigned i, dim;
- attrib->type = mesh->attribs_type[usage];
+ attrib->type = geom_mesh->data.mesh->attribs_type[usage];
/* Fetch attrib data */
dim = s3d_type_get_dimension(attrib->type);
- attr = mesh_get_attr(mesh, usage);
+ attr = mesh_get_attr(geom_mesh->data.mesh, usage);
v0 = attr + ids[0] * dim;
v1 = attr + ids[1] * dim;
v2 = attr + ids[2] * dim;
diff --git a/src/s3d_sampler.c b/src/s3d_sampler.c
@@ -42,6 +42,7 @@
#include <algorithm>
/* The sampler is used to compute uniform random variates of a shape */
+#if 0
struct s3d_sampler {
struct s3d_shape* shape; /* The shape to sample */
@@ -578,4 +579,4 @@ exit:
error:
goto exit;
}
-
+#endif
diff --git a/src/s3d_scene.c b/src/s3d_scene.c
@@ -51,18 +51,18 @@ scene_build
static INLINE void
scene_geometry_flush_enable_state
(struct s3d_scene* scn,
- struct geometry* cache, /* Cached value */
- const struct geometry* curr) /* New value */
+ struct geometry* geom, /* Cached geometry */
+ const struct s3d_shape* shape) /* New shape */
{
- ASSERT(scn && cache && curr);
- if(cache->is_enabled == curr->is_enabled)
+ ASSERT(scn && geom && shape);
+ if(geom->is_enabled == shape->is_enabled)
return;
- cache->is_enabled = curr->is_enabled;
- if(curr->is_enabled) {
- rtcEnable(scn->rtc_scn, cache->irtc);
+ geom->is_enabled = shape->is_enabled;
+ if(geom->is_enabled) {
+ rtcEnable(scn->rtc_scn, geom->irtc);
} else {
- rtcDisable(scn->rtc_scn, cache->irtc);
+ rtcDisable(scn->rtc_scn, geom->irtc);
}
scn->is_rtc_scn_outdated = 1;
}
@@ -80,8 +80,8 @@ scene_build_register_mesh(struct s3d_scene* scn, struct geometry* geom)
scn->is_rtc_scn_outdated = 1;
}
- if(geom->irtc >= darray_mesh_size_get(&scn->meshes)) {
- res_T res = darray_mesh_resize(&scn->meshes, geom->irtc + 1);
+ if(geom->irtc >= darray_geom_size_get(&scn->embree2geoms)) {
+ res_T res = darray_geom_resize(&scn->embree2geoms, geom->irtc + 1);
if(res != RES_OK) {
rtcDeleteGeometry(scn->rtc_scn, geom->irtc);
geom->irtc = RTC_INVALID_GEOMETRY_ID;
@@ -89,61 +89,57 @@ scene_build_register_mesh(struct s3d_scene* scn, struct geometry* geom)
}
}
geometry_ref_get(geom);
- darray_mesh_data_get(&scn->meshes)[geom->irtc] = geom;
+ darray_geom_data_get(&scn->embree2geoms)[geom->irtc] = geom;
return RES_OK;
}
static res_T
scene_build_register_instance(struct s3d_scene* scn, struct geometry* geom)
{
- ASSERT(scn && geom && inst->scene);
- /* The instance should not contain instances */
- ASSERT(!darray_inst_size_get(&inst->scene->instances));
+ ASSERT(scn && geom && geom->data.instance->scene && geom->type==GEOM_INSTANCE);
+ /* The instance should not contain instances, i.e. one instancing level is
+ * supported */
+ ASSERT(geom->data.instance->scene->instances_count == 0);
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)
+ if(geom->irtc == RTC_INVALID_GEOMETRY_ID)
return RES_UNKNOWN_ERR;
scn->is_rtc_scn_outdated = 1;
}
- if(geom->irtc >= darray_inst_size_get(&scn->instances)) {
- res_T res = darray_inst_resize(&scn->instances, geom->irtc + 1);
+ if(geom->irtc >= darray_geom_size_get(&scn->embree2geoms)) {
+ res_T res = darray_geom_resize(&scn->embree2geoms, geom->irtc + 1);
if(res != RES_OK) {
rtcDeleteGeometry(scn->rtc_scn, geom->irtc);
geom->irtc = RTC_INVALID_GEOMETRY_ID;
return res;
}
}
- instance_ref_get(inst);
- darray_inst_data_get(&scn->instances)[inst->geom.irtc] = inst;
+ geometry_ref_get(geom);
+ darray_geom_data_get(&scn->embree2geoms)[geom->irtc] = geom;
return RES_OK;
}
static void
scene_build_clear(struct s3d_scene* scn)
{
- struct mesh** meshes;
- struct instance** instances;
- size_t nmeshes;
- size_t ninstances;
+ struct geometry** geoms;
+ size_t ngeoms;
size_t i;
ASSERT(scn);
- nmeshes = darray_mesh_size_get(&scn->meshes);
- meshes = darray_mesh_data_get(&scn->meshes);
- FOR_EACH(i, 0, nmeshes) if(meshes[i]) mesh_ref_put(meshes[i]);
- darray_mesh_clear(&scn->meshes);
-
- ninstances = darray_inst_size_get(&scn->instances);
- instances = darray_inst_data_get(&scn->instances);
- FOR_EACH(i, 0, ninstances) {
- if(instances[i]) {
- scene_build_clear(instances[i]->scene);
- instance_ref_put(instances[i]);
- }
+ ngeoms = darray_geom_size_get(&scn->embree2geoms);
+ geoms = darray_geom_data_get(&scn->embree2geoms);
+ FOR_EACH(i, 0, ngeoms) {
+ if(!geoms[i]) continue;
+
+ if(geoms[i]->type == GEOM_INSTANCE)
+ scene_build_clear(geoms[i]->data.instance->scene);
+
+ geometry_ref_put(geoms[i]);
}
- darray_inst_clear(&scn->instances);
+ darray_geom_clear(&scn->embree2geoms);
scn->build_type = BUILD_NONE;
}
@@ -158,7 +154,7 @@ scene_setup_shape_mesh
char upd_pos, upd_ids;
res_T res = RES_OK;
- ASSERT(shape && shape->type == SHAPE_MESH);
+ ASSERT(shape && shape->type == GEOM_MESH);
/* Retrieve the cached geometry */
pgeom = htable_geom_find(&scn->cached_geoms, &shape);
@@ -172,7 +168,7 @@ scene_setup_shape_mesh
geom->type = GEOM_MESH;
res = htable_geom_set(&scn->cached_geoms, &shape, &geom);
if(res != RES_OK) goto error;
- geom->name = shape->name.index;
+ geom->name = shape->id.index;
}
/* Discard the geometry that is not geometrically valid */
@@ -182,7 +178,7 @@ scene_setup_shape_mesh
geom->irtc = RTC_INVALID_GEOMETRY_ID;
scn->is_rtc_scn_outdated = 1;
}
- mesh_clear(geom->mesh);
+ mesh_clear(geom->data.mesh);
goto exit;
}
@@ -221,14 +217,14 @@ scene_setup_shape_mesh
}
/* 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, geom->data.mesh->geom.irtc);
- geom->data.mesh->geom.irtc = RTC_INVALID_GEOMETRY_ID;
+ if(shape->data.mesh->resize_mask && geom->irtc != RTC_INVALID_GEOMETRY_ID) {
+ rtcDeleteGeometry(scn->rtc_scn, geom->irtc);
+ geom->irtc = RTC_INVALID_GEOMETRY_ID;
scn->is_rtc_scn_outdated = 1;
}
/* Update the cached mesh states */
- geom->data.mesh->flip_surface = shape->data.mesh->flip_surface;
+ geom->flip_surface = shape->flip_surface;
res = scene_build_register_mesh(scn, geom);
if(res != RES_OK) goto error;
@@ -240,13 +236,13 @@ scene_setup_shape_mesh
scn->is_rtc_scn_outdated = 1;
}
if(upd_ids) { /* Update the Embree index buffer if necessary */
- rtcSetBuffer(scn->rtc_scn, mesh->geom.irtc, RTC_INDEX_BUFFER,
- mesh_get_ids(mesh), 0, sizeof(uint32_t[3]));
- rtcUpdateBuffer(scn->rtc_scn, mesh->geom.irtc, RTC_INDEX_BUFFER);
+ rtcSetBuffer(scn->rtc_scn, geom->irtc, RTC_INDEX_BUFFER,
+ mesh_get_ids(geom->data.mesh), 0, sizeof(uint32_t[3]));
+ rtcUpdateBuffer(scn->rtc_scn, geom->irtc, RTC_INDEX_BUFFER);
scn->is_rtc_scn_outdated = 1;
}
- scene_geometry_flush_enable_state(scn, &mesh->geom, &shape->data.mesh->geom);
+ scene_geometry_flush_enable_state(scn, geom, shape);
/* Flush the shape mesh states */
shape->data.mesh->resize_mask = 0;
@@ -270,7 +266,7 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape)
res = scene_build(shape->data.instance->scene, BUILD_INDIRECT);
if(res != RES_OK) goto error;
- pgeom = htable_inst_find(&scn->cached_geoms, &shape);
+ pgeom = htable_geom_find(&scn->cached_geoms, &shape);
/* Create the scene instance of the geometry if necessary */
if(pgeom) {
geom = *pgeom;
@@ -280,38 +276,38 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape)
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_geoms, &shape, &geom);
+ res = htable_geom_set(&scn->cached_geoms, &shape, &geom);
if(res != RES_OK) goto error;
- geom->id = shape->name.index;
+ geom->name = shape->id.index;
}
/* Update the cached instance states */
- ASSERT(geom->data.inst->scene == shape->data.instance->scene);
- f33_set(geom->data.inst->transform, shape->data.instance->transform);
+ ASSERT(geom->data.instance->scene == shape->data.instance->scene);
+ f33_set(geom->data.instance->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;
+ geom->flip_surface = shape->flip_surface;
- /* TODO The instance cannot contain instances */
- if(darray_inst_size_get(&inst->scene->instances)) {
+ /* The instance cannot contain instances, i.e. one instancing level is
+ * supported */
+ if(geom->data.instance->scene->instances_count != 0) {
res = RES_BAD_ARG;
goto error;
}
/* Create the Embree instance */
- res = scene_build_register_instance(scn, inst);
+ res = scene_build_register_instance(scn, geom);
if(res != RES_OK) goto error;
/* Update the Embree instance transformation */
- if(geom->data.instance->update_transform) {
+ if(shape->data.instance->update_transform) {
rtcSetTransform
(scn->rtc_scn,
- inst->geom.irtc,
+ geom->irtc,
RTC_MATRIX_COLUMN_MAJOR,
- inst->transform);
+ geom->data.instance->transform);
scn->is_rtc_scn_outdated = 1;
}
- scene_geometry_flush_enable_state
- (scn, geom, &shape->data.instance->geom);
+ scene_geometry_flush_enable_state(scn, geom, shape);
shape->data.instance->update_transform = 0; /* Flush instance state */
exit:
@@ -321,100 +317,29 @@ error:
}
static void
-scene_detach_shape_mesh(struct s3d_scene* scn, struct s3d_shape* shape)
+scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
{
- struct mesh** pmesh;
+ struct geometry** pgeom;
ASSERT(scn && shape && !is_list_empty(&shape->scene_attachment));
- ASSERT(shape->type == SHAPE_MESH);
-
- pmesh = htable_mesh_find(&scn->cached_meshes, &shape);
- if(pmesh) { /* Remove the cached shape mesh */
- struct mesh* mesh = *pmesh;
- 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_ref_put(mesh);
- htable_mesh_erase(&scn->cached_meshes, &shape);
- }
- list_del(&shape->scene_attachment);
- S3D(shape_ref_put(shape));
-}
+ ASSERT(shape->type == GEOM_MESH || shape->type == GEOM_INSTANCE);
-static void
-scene_detach_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape)
-{
- struct instance** pinst;
- ASSERT(scn && shape && !is_list_empty(&shape->scene_attachment));
- ASSERT(shape->type == SHAPE_INSTANCE);
-
- pinst = htable_inst_find(&scn->cached_instances, &shape);
- if(pinst) { /* Remove the cached shape instance */
- struct instance* inst = *pinst;
- if(inst->geom.irtc != RTC_INVALID_GEOMETRY_ID) {
- rtcDeleteGeometry(scn->rtc_scn, inst->geom.irtc);
- inst->geom.irtc = RTC_INVALID_GEOMETRY_ID;
+ pgeom = htable_geom_find(&scn->cached_geoms, &shape);
+ if(pgeom) { /* Remove the cached shape mesh */
+ struct geometry* geom = *pgeom;
+ 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;
}
- instance_ref_put(inst);
- htable_inst_erase(&scn->cached_instances, &shape);
+ geometry_ref_put(geom);
+ htable_geom_erase(&scn->cached_geoms, &shape);
}
list_del(&shape->scene_attachment);
S3D(shape_ref_put(shape));
-}
-static void
-scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
-{
- ASSERT(scn && shape);
- switch(shape->type) {
- case SHAPE_INSTANCE: scene_detach_shape_instance(scn, shape); break;
- case SHAPE_MESH: scene_detach_shape_mesh(scn, shape); break;
- default: FATAL("Unreachable code\n"); break;
- }
-}
-
-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);
- }
+ if(shape->type == GEOM_INSTANCE) {
+ ASSERT(scn->instances_count != 0);
+ --scn->instances_count;
}
}
@@ -433,9 +358,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->geom.type) {
- case SHAPE_INSTANCE: res = scene_setup_instance(scn, &shape->geom); break;
- case SHAPE_MESH: res = scene_setup_mesh(scn, &shape->geom); break;
+ switch(shape->type) {
+ case GEOM_INSTANCE: res = scene_setup_shape_instance(scn, shape); break;
+ case GEOM_MESH: res = scene_setup_shape_mesh(scn, shape); break;
default: FATAL("Unreachable code\n"); break;
}
if(res != RES_OK)
@@ -465,10 +390,8 @@ scene_release(ref_T* ref)
dev = scn->dev;
scene_build_clear(scn);
if(scn->rtc_scn) rtcDeleteScene(scn->rtc_scn);
- htable_mesh_release(&scn->cached_meshes);
- htable_inst_release(&scn->cached_instances);
- darray_mesh_release(&scn->meshes);
- darray_inst_release(&scn->instances);
+ htable_geom_release(&scn->cached_geoms);
+ darray_geom_release(&scn->embree2geoms);
MEM_RM(dev->allocator, scn);
S3D(device_ref_put(dev));
}
@@ -494,8 +417,7 @@ s3d_scene_create(struct s3d_device* dev, struct s3d_scene** out_scn)
}
list_init(&scn->shapes);
htable_geom_init(dev->allocator, &scn->cached_geoms);
- darray_mesh_init(dev->allocator, &scn->meshes);
- darray_inst_init(dev->allocator, &scn->instances);
+ darray_geom_init(dev->allocator, &scn->embree2geoms);
ref_init(&scn->ref);
S3D(device_ref_get(dev));
scn->dev = dev;
@@ -552,8 +474,8 @@ s3d_scene_instantiate(struct s3d_scene* scn, struct s3d_shape** out_shape)
if(res != RES_OK)
goto error;
- shape->geom.type = GEOM_MESH_INSTANCE;
- res = instance_create(scn, &shape->geom.data.instance);
+ shape->type = GEOM_INSTANCE;
+ res = instance_create(scn, &shape->data.instance);
if(res != RES_OK)
goto error;
@@ -579,6 +501,7 @@ s3d_scene_attach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
list_add_tail(&scn->shapes, &shape->scene_attachment);
S3D(shape_ref_get(shape));
+ scn->instances_count += shape->type == GEOM_INSTANCE;
return RES_OK;
}
@@ -591,7 +514,7 @@ s3d_scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
if(!(S3D(shape_is_attached(shape, &is_attached)), is_attached))
return RES_BAD_ARG;
#ifndef NDEBUG
- {
+ { /* Check the the shape is attached to `scn' */
struct list_node* node;
char is_found = 0;
LIST_FOR_EACH(node, &scn->shapes) {
@@ -703,29 +626,33 @@ s3d_scene_trace_ray
hit->uv[0] = w;
if((unsigned)ray.instID == RTC_INVALID_GEOMETRY_ID) {
- ASSERT((unsigned)ray.geomID < darray_mesh_size_get(&scn->meshes));
- hit->prim.mesh__ = darray_mesh_data_get(&scn->meshes)[ray.geomID];
+ ASSERT((unsigned)ray.geomID < darray_geom_size_get(&scn->embree2geoms));
+ hit->prim.mesh__ = darray_geom_data_get(&scn->embree2geoms)[ray.geomID];
hit->prim.inst__ = NULL;
hit->prim.prim_id = ray.primID;
- hit->prim.geom_id = ((struct mesh*)hit->prim.mesh__)->id;
+ hit->prim.geom_id = ((struct geometry*)hit->prim.mesh__)->name;
hit->prim.inst_id = S3D_INVALID_ID;
} else { /* The hit shape is instantiated */
/* Retrieve the hit instance */
- struct instance* instance;
- ASSERT((unsigned)ray.instID < darray_inst_size_get(&scn->instances));
- instance = darray_inst_data_get(&scn->instances)[ray.instID];
- hit->prim.mesh__ = scene_get_mesh(instance->scene, ray.geomID);
- hit->prim.inst__ = instance;
+ struct geometry* geom_inst;
+ ASSERT((unsigned)ray.instID < darray_geom_size_get(&scn->embree2geoms));
+ geom_inst = darray_geom_data_get(&scn->embree2geoms)[ray.instID];
+ hit->prim.mesh__ = scene_get_mesh(geom_inst->data.instance->scene, ray.geomID);
+ hit->prim.inst__ = geom_inst;
hit->prim.prim_id = ray.primID;
- hit->prim.geom_id = ((struct mesh*)hit->prim.mesh__)->id;
- hit->prim.inst_id = instance->id;
- flip_surface = instance->flip_surface;
+ hit->prim.geom_id = ((struct geometry*)hit->prim.mesh__)->name;
+ hit->prim.inst_id = geom_inst->name;
+ flip_surface = geom_inst->flip_surface;
+ ASSERT(hit->prim.inst__);
+ ASSERT(((struct geometry*)hit->prim.inst__)->type == GEOM_INSTANCE);
}
ASSERT(hit->prim.mesh__);
- flip_surface ^= ((struct mesh*)hit->prim.mesh__)->flip_surface;
- if(flip_surface)
- f3_minus(hit->normal, hit->normal);
+ ASSERT(((struct geometry*)hit->prim.mesh__)->type == GEOM_MESH);
+
+ /* Flip geometric normal with respect to the flip surface flag */
+ flip_surface ^= ((struct geometry*)hit->prim.mesh__)->flip_surface;
+ if(flip_surface) f3_minus(hit->normal, hit->normal);
}
return RES_OK;
}
diff --git a/src/s3d_scene_c.h b/src/s3d_scene_c.h
@@ -62,7 +62,7 @@ geom_ptr_init__(struct mem_allocator* alloc, struct geometry** geom)
#define HTABLE_KEY struct s3d_shape*
#include <rsys/hash_table.h>
-enum sync_type {
+enum build_type {
BUILD_NONE, /* The scene is not built */
BUILD_DIRECT, /* The scene is directly build */
BUILD_INDIRECT /* The scene is build as an instance */
@@ -70,11 +70,10 @@ enum sync_type {
struct s3d_scene {
struct list_node shapes; /* List of attached shapes */
- struct htable_mesh cached_geoms; /* Cached shape geometries */
+ struct htable_geom cached_geoms; /* Cached shape geometries */
+ struct darray_geom embree2geoms; /* Shape geometries index by embree id */
- /* Active geometry. Indexed by the Embree identifier */
- struct darray_geom meshes;
- struct darray_geom instances;
+ size_t instances_count; /* # instances int the scene */
RTCScene rtc_scn;
char is_rtc_scn_outdated;
@@ -85,15 +84,15 @@ struct s3d_scene {
ref_T ref;
};
-static FINLINE struct mesh*
+static FINLINE struct geometry*
scene_get_mesh(struct s3d_scene* scn, const unsigned igeom)
{
- struct mesh* mesh;
+ struct geometry* geom;
ASSERT(scn && igeom != RTC_INVALID_GEOMETRY_ID);
- ASSERT(igeom < darray_mesh_size_get(&scn->meshes));
- mesh = darray_mesh_data_get(&scn->meshes)[igeom];
- ASSERT(mesh);
- return mesh;
+ ASSERT(igeom < darray_geom_size_get(&scn->embree2geoms));
+ geom = darray_geom_data_get(&scn->embree2geoms)[igeom];
+ ASSERT(geom);
+ return geom;
}
#endif /* S3D_SCENE_C_H */
diff --git a/src/s3d_shape.c b/src/s3d_shape.c
@@ -60,6 +60,7 @@ shape_release(ref_T* ref)
case GEOM_INSTANCE:
if(shape->data.instance) instance_ref_put(shape->data.instance);
break;
+ default: FATAL("Unreachable code \n"); break;
}
}
MEM_RM(dev->allocator, shape);
@@ -89,8 +90,10 @@ shape_create(struct s3d_device* dev, struct s3d_shape** out_shape)
S3D(device_ref_get(dev));
shape->dev = dev;
ref_init(&shape->ref);
- shape->fid = flist_name_add(&dev->names);
+ shape->id = flist_name_add(&dev->names);
shape->type = GEOM_NONE;
+ shape->is_enabled = 1;
+ shape->flip_surface = 0;
exit:
if(out_shape) *out_shape = shape;
@@ -160,7 +163,7 @@ res_T
s3d_shape_get_id(struct s3d_shape* shape, unsigned* id)
{
if(!shape || !id) return RES_BAD_ARG;
- *id = shape->name.index;
+ *id = shape->id.index;
return RES_OK;
}
@@ -236,10 +239,12 @@ s3d_shape_compute_volume(struct s3d_shape* shape, float* volume)
return RES_BAD_ARG;
switch(shape->type) {
case GEOM_MESH:
- *volume = mesh_compute_volume(shape->data.mesh, 0);
+ *volume = mesh_compute_volume
+ (shape->data.mesh, shape->flip_surface);
break;
case GEOM_INSTANCE:
- *volume = instance_compute_volume(shape->data.instance);
+ *volume = instance_compute_volume
+ (shape->data.instance, shape->flip_surface);
break;
default: FATAL("Unreachable code \n"); break;
}