commit 9f0d3be7042c3d74306d64e9d1581e3bc607dee7
parent 1014b516425347daf33c0e11aecc262336e076e6
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 9 Sep 2015 11:43:30 +0200
Replace <begin|end>_trace by <begin|end>_session
Diffstat:
5 files changed, 112 insertions(+), 114 deletions(-)
diff --git a/src/s3d.h b/src/s3d.h
@@ -155,6 +155,12 @@ static const struct s3d_hit S3D_HIT_NULL =
FLT_MAX
};
+enum s3d_session_flag {
+ S3D_SESSION_NONE = 0,
+ S3D_SESSION_TRACE = BIT(0),
+ S3D_SESSION_SAMPLE = BIT(1)
+};
+
/* Helper macro that defines whether or not the hit is valid, i.e. the ray
* intersects a shape or not */
#define S3D_HIT_NONE(Hit) ((Hit)->distance >= FLT_MAX)
@@ -243,26 +249,25 @@ s3d_scene_clear
(struct s3d_scene* scn);
/* Synchronize the scene geometry with the geometry of its attached shapes. If
- * a s3d_scene_begin_trace is already active on `scn' or one of its attached
+ * a s3d_scene_begin_session is already active on `scn' or one of its attached
* instance a RES_BAD_OP error is returned. On success neither another begin
- * trace nor a clear or shape_detach can be invoked on `scn' and its attached
- * instances until s3d_scene_end_trace is called. A s3d_scene_trace_ray
- * operation can be invoked on `scn' only between a s3d_scene_begin_trace and
- * s3d_scene_end_trace call. */
+ * session nor a clear or shape_detach can be invoked on `scn' and its attached
+ * instances until s3d_scene_end_session is called. A s3d_scene_trace_ray
+ * operation can be invoked on if a S3D_SESSION_TRACE session is active on scn*/
S3D_API res_T
-s3d_scene_begin_trace
- (struct s3d_scene* scn);
+s3d_scene_begin_session
+ (struct s3d_scene* scn,
+ const int session_mask); /* Combination of s3d_session_flag */
-/* End the trace operation on the `scn' */
+/* End the session on the `scn' */
S3D_API res_T
-s3d_scene_end_trace
+s3d_scene_end_session
(struct s3d_scene* scn);
-/* Define if the begin scene is currently invoked on `scn' */
S3D_API res_T
-s3d_scene_is_traceable
+s3d_scene_get_session_mask
(struct s3d_scene* scn,
- char* is_traceable);
+ int* mask);
/* Trace a ray into the `scn' and return the closest intersection. The ray is
* defined by `origin' + t*`direction' = 0 with t in [`range[0]', `range[1]').
diff --git a/src/s3d_scene.c b/src/s3d_scene.c
@@ -40,13 +40,16 @@
#include <rsys/mem_allocator.h>
#include <rsys/mutex.h>
+/* Flag used to define session of enabled on instantiated scene */
+#define S3D_SESSION_INSTANCE (BIT(sizeof(int)*8 - 1))
+
/*******************************************************************************
* Helper functions
******************************************************************************/
static res_T
-scene_build
+scene_sync
(struct s3d_scene* scn,
- const enum build_type type);
+ const int mask);/* combination of s3d_session_flag & S3D_SESSION_INSTANCE */
static INLINE void
scene_geometry_flush_enable_state
@@ -68,43 +71,26 @@ scene_geometry_flush_enable_state
}
static res_T
-scene_build_register_mesh(struct s3d_scene* scn, struct geometry* geom)
+scene_register_embree_geometry(struct s3d_scene* scn, struct geometry* geom)
{
- ASSERT(scn && geom && geom->type == GEOM_MESH);
+ ASSERT(scn && geom && (geom->type==GEOM_MESH || geom->type==GEOM_INSTANCE));
+
/* Create the Embree geometry if it is not valid */
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(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;
+ switch(geom->type) {
+ case GEOM_MESH:
+ geom->irtc = rtcNewTriangleMesh(scn->rtc_scn, RTC_GEOMETRY_DYNAMIC,
+ mesh_get_ntris(geom->data.mesh), mesh_get_nverts(geom->data.mesh));
+ break;
+ case GEOM_INSTANCE:
+ geom->irtc = rtcNewInstance
+ (scn->rtc_scn, geom->data.instance->scene->rtc_scn);
+ break;
+ default: FATAL("Unreachable code\n"); break;
}
- }
- geometry_ref_get(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 && 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)
return RES_UNKNOWN_ERR;
+
scn->is_rtc_scn_outdated = 1;
}
@@ -122,7 +108,7 @@ scene_build_register_instance(struct s3d_scene* scn, struct geometry* geom)
}
static void
-scene_build_clear(struct s3d_scene* scn)
+scene_session_clear(struct s3d_scene* scn)
{
struct geometry** geoms;
size_t ngeoms;
@@ -135,18 +121,19 @@ scene_build_clear(struct s3d_scene* scn)
if(!geoms[i]) continue;
if(geoms[i]->type == GEOM_INSTANCE)
- scene_build_clear(geoms[i]->data.instance->scene);
+ scene_session_clear(geoms[i]->data.instance->scene);
geometry_ref_put(geoms[i]);
}
darray_geom_clear(&scn->embree2geoms);
- scn->build_type = BUILD_NONE;
+ scn->session_mask = S3D_SESSION_NONE;
}
static res_T
-scene_setup_shape_mesh
+scene_register_mesh
(struct s3d_scene* scn,
- struct s3d_shape* shape)
+ struct s3d_shape* shape,
+ const int session_mask)
{
struct geometry** pgeom = NULL;
struct geometry* geom = NULL;
@@ -226,7 +213,7 @@ scene_setup_shape_mesh
/* Update the cached mesh states */
geom->flip_surface = shape->flip_surface;
- res = scene_build_register_mesh(scn, geom);
+ res = scene_register_embree_geometry(scn, geom);
if(res != RES_OK) goto error;
if(upd_pos) { /* Update the Embree vertex buffer if necessary */
@@ -255,7 +242,10 @@ error:
}
static res_T
-scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape)
+scene_register_instance
+ (struct s3d_scene* scn,
+ struct s3d_shape* shape,
+ const int session_mask)
{
struct geometry** pgeom = NULL;
struct geometry* geom = NULL;
@@ -263,7 +253,8 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape)
ASSERT(scn && shape && shape->type == GEOM_INSTANCE);
/* Recursuvely update the scene */
- res = scene_build(shape->data.instance->scene, BUILD_INDIRECT);
+ res = scene_sync(shape->data.instance->scene,
+ session_mask|S3D_SESSION_INSTANCE);
if(res != RES_OK) goto error;
pgeom = htable_geom_find(&scn->cached_geoms, &shape);
@@ -294,7 +285,7 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape)
}
/* Create the Embree instance */
- res = scene_build_register_instance(scn, geom);
+ res = scene_register_embree_geometry(scn, geom);
if(res != RES_OK) goto error;
/* Update the Embree instance transformation */
@@ -344,13 +335,13 @@ scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
}
static res_T
-scene_build(struct s3d_scene* scn, const enum build_type type)
+scene_sync(struct s3d_scene* scn, const int session_mask)
{
struct list_node* node;
res_T res = RES_OK;
- ASSERT(scn && (type == BUILD_DIRECT || type == BUILD_INDIRECT));
+ ASSERT(scn);
- if(scn->build_type != BUILD_NONE) {
+ if(scn->session_mask != S3D_SESSION_NONE) {
res = RES_BAD_OP;
goto error;
}
@@ -359,8 +350,12 @@ scene_build(struct s3d_scene* scn, const enum build_type type)
struct s3d_shape* shape = CONTAINER_OF
(node, struct s3d_shape, scene_attachment);
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;
+ case GEOM_INSTANCE:
+ res = scene_register_instance(scn, shape, session_mask);
+ break;
+ case GEOM_MESH:
+ res = scene_register_mesh(scn, shape, session_mask);
+ break;
default: FATAL("Unreachable code\n"); break;
}
if(res != RES_OK)
@@ -370,8 +365,7 @@ scene_build(struct s3d_scene* scn, const enum build_type type)
rtcCommit(scn->rtc_scn);
scn->is_rtc_scn_outdated = 0;
}
-
- scn->build_type = type;
+ scn->session_mask = session_mask;
exit:
return res;
@@ -388,7 +382,7 @@ scene_release(ref_T* ref)
scn = CONTAINER_OF(ref, struct s3d_scene, ref);
S3D(scene_clear(scn));
dev = scn->dev;
- scene_build_clear(scn);
+ scene_session_clear(scn);
if(scn->rtc_scn) rtcDeleteScene(scn->rtc_scn);
htable_geom_release(&scn->cached_geoms);
darray_geom_release(&scn->embree2geoms);
@@ -421,7 +415,7 @@ s3d_scene_create(struct s3d_device* dev, struct s3d_scene** out_scn)
ref_init(&scn->ref);
S3D(device_ref_get(dev));
scn->dev = dev;
- scn->build_type = BUILD_NONE;
+ scn->session_mask = S3D_SESSION_NONE;
scn->rtc_scn = rtcNewScene
(RTC_SCENE_DYNAMIC | RTC_SCENE_INCOHERENT | RTC_SCENE_ROBUST,
RTC_INTERSECT1 | RTC_INTERSECT4);
@@ -510,7 +504,7 @@ s3d_scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
{
char is_attached;
if(!scn || !shape) return RES_BAD_ARG;
- if(scn->build_type != BUILD_NONE) return RES_BAD_OP;
+ if(scn->session_mask != S3D_SESSION_NONE) return RES_BAD_OP;
if(!(S3D(shape_is_attached(shape, &is_attached)), is_attached))
return RES_BAD_ARG;
#ifndef NDEBUG
@@ -533,7 +527,7 @@ s3d_scene_clear(struct s3d_scene* scn)
{
struct list_node* node, *tmp;
if(!scn) return RES_BAD_ARG;
- if(scn->build_type != BUILD_NONE) return RES_BAD_OP;
+ if(scn->session_mask != S3D_SESSION_NONE) return RES_BAD_OP;
LIST_FOR_EACH_SAFE(node, tmp, &scn->shapes) {
struct s3d_shape* shape = CONTAINER_OF
(node, struct s3d_shape, scene_attachment);
@@ -543,29 +537,32 @@ s3d_scene_clear(struct s3d_scene* scn)
}
res_T
-s3d_scene_begin_trace(struct s3d_scene* scn)
+s3d_scene_begin_session(struct s3d_scene* scn, const int session_mask)
{
- if(!scn) return RES_BAD_ARG;
- return scene_build(scn, BUILD_DIRECT);
+ if(!scn)
+ return RES_BAD_ARG;
+ if(!(session_mask&S3D_SESSION_TRACE) && !(session_mask&S3D_SESSION_SAMPLE))
+ return RES_BAD_ARG;
+ return scene_sync(scn, session_mask);
}
res_T
-s3d_scene_end_trace(struct s3d_scene* scn)
+s3d_scene_end_session(struct s3d_scene* scn)
{
if(!scn)
return RES_BAD_ARG;
- if(scn->build_type != BUILD_DIRECT)
+ if(scn->session_mask & S3D_SESSION_INSTANCE || !scn->session_mask)
return RES_BAD_OP;
- scene_build_clear(scn);
+ scene_session_clear(scn);
return RES_OK;
}
res_T
-s3d_scene_is_traceable(struct s3d_scene* scn, char* is_traceable)
+s3d_scene_get_session_mask(struct s3d_scene* scn, int* session_mask)
{
- if(!scn || !is_traceable)
+ if(!scn || !session_mask)
return RES_BAD_ARG;
- *is_traceable = scn->build_type != BUILD_NONE;
+ *session_mask = scn->session_mask & (~S3D_SESSION_INSTANCE);
return RES_OK;
}
@@ -582,7 +579,7 @@ s3d_scene_trace_ray
return RES_BAD_ARG;
if(!f3_is_normalized(dir))
return RES_BAD_ARG;
- if(scn->build_type == BUILD_NONE)
+ if(scn->session_mask == S3D_SESSION_NONE)
return RES_BAD_OP;
if(range[0] > range[1]) {
*hit = S3D_HIT_NULL;
diff --git a/src/s3d_scene_c.h b/src/s3d_scene_c.h
@@ -62,23 +62,17 @@ geom_ptr_init__(struct mem_allocator* alloc, struct geometry** geom)
#define HTABLE_KEY struct s3d_shape*
#include <rsys/hash_table.h>
-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 */
-};
-
struct s3d_scene {
struct list_node shapes; /* List of attached shapes */
struct htable_geom cached_geoms; /* Cached shape geometries */
struct darray_geom embree2geoms; /* Shape geometries index by embree id */
- size_t instances_count; /* # instances int the scene */
+ size_t instances_count; /* # instances in the scene */
- RTCScene rtc_scn;
- char is_rtc_scn_outdated;
+ RTCScene rtc_scn; /* Embree scene */
+ char is_rtc_scn_outdated; /* Must the embree scene rebuild */
- enum build_type build_type;
+ int session_mask; /* Combination of enum s3d_session_flag */
struct s3d_device* dev;
ref_T ref;
diff --git a/src/test_s3d_scene.c b/src/test_s3d_scene.c
@@ -43,7 +43,7 @@ main(int argc, char** argv)
const size_t nshapes = sizeof(shapes)/sizeof(struct s3d_shape*);
size_t i;
unsigned id;
- char b;
+ int mask;
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
@@ -90,29 +90,31 @@ main(int argc, char** argv)
CHECK(s3d_scene_clear(scn), RES_OK);
CHECK(s3d_scene_instantiate(scn, shapes + 2), RES_OK);
- CHECK(s3d_scene_is_traceable(NULL, NULL), RES_BAD_ARG);
- CHECK(s3d_scene_is_traceable(scn, NULL), RES_BAD_ARG);
- CHECK(s3d_scene_is_traceable(NULL, &b), RES_BAD_ARG);
- CHECK(s3d_scene_is_traceable(scn, &b), RES_OK);
- CHECK(b, 0);
+ CHECK(s3d_scene_get_session_mask(NULL, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_get_session_mask(scn, NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_get_session_mask(NULL, &mask), RES_BAD_ARG);
+ CHECK(s3d_scene_get_session_mask(scn, &mask), RES_OK);
+ CHECK(mask, S3D_SESSION_NONE);
CHECK(s3d_scene_attach_shape(scn, shapes[0]), RES_OK);
- CHECK(s3d_scene_begin_trace(NULL), RES_BAD_ARG);
- CHECK(s3d_scene_begin_trace(scn), RES_OK);
- CHECK(s3d_scene_begin_trace(scn), RES_BAD_OP);
+ CHECK(s3d_scene_begin_session(NULL, 0), RES_BAD_ARG);
+ CHECK(s3d_scene_begin_session(scn, 0), RES_BAD_ARG);
+ CHECK(s3d_scene_begin_session(scn, S3D_SESSION_TRACE), RES_OK);
+ CHECK(s3d_scene_begin_session(scn, S3D_SESSION_TRACE), RES_BAD_OP);
- CHECK(s3d_scene_is_traceable(scn, &b), RES_OK);
- CHECK(b, 1);
+ CHECK(s3d_scene_get_session_mask(scn, &mask), RES_OK);
+ CHECK(mask & S3D_SESSION_TRACE, S3D_SESSION_TRACE);
+ CHECK(mask & S3D_SESSION_SAMPLE, 0);
CHECK(s3d_scene_clear(scn), RES_BAD_OP);
CHECK(s3d_scene_detach_shape(scn, shapes[0]), RES_BAD_OP);
- CHECK(s3d_scene_end_trace(NULL), RES_BAD_ARG);
- CHECK(s3d_scene_end_trace(scn), RES_OK);
- CHECK(s3d_scene_end_trace(scn), RES_BAD_OP);
+ CHECK(s3d_scene_end_session(NULL), RES_BAD_ARG);
+ CHECK(s3d_scene_end_session(scn), RES_OK);
+ CHECK(s3d_scene_end_session(scn), RES_BAD_OP);
- CHECK(s3d_scene_is_traceable(scn, &b), RES_OK);
- CHECK(b, 0);
+ CHECK(s3d_scene_get_session_mask(scn, &mask), RES_OK);
+ CHECK(mask, 0);
CHECK(s3d_scene_detach_shape(scn, shapes[0]), RES_OK);
diff --git a/src/test_s3d_trace_ray.c b/src/test_s3d_trace_ray.c
@@ -133,7 +133,7 @@ main(int argc, char** argv)
CHECK(s3d_scene_attach_shape(scn, walls), RES_OK);
CHECK(s3d_shape_ref_put(walls), RES_OK);
- CHECK(s3d_scene_begin_trace(scn), RES_OK);
+ CHECK(s3d_scene_begin_session(scn, S3D_SESSION_TRACE), RES_OK);
CHECK(s3d_scene_trace_ray(NULL, NULL, NULL, NULL, NULL), RES_BAD_ARG);
CHECK(s3d_scene_trace_ray(scn, NULL, NULL, NULL, NULL), RES_BAD_ARG);
CHECK(s3d_scene_trace_ray(NULL, org, NULL, NULL, NULL), RES_BAD_ARG);
@@ -169,7 +169,7 @@ main(int argc, char** argv)
CHECK(s3d_scene_trace_ray(scn, org, dir, range, &hit), RES_OK);
f3(dir, 1.f, 1.f, 1.f);
CHECK(s3d_scene_trace_ray(scn, org, dir, range, &hit), RES_BAD_ARG);
- CHECK(s3d_scene_end_trace(scn), RES_OK);
+ CHECK(s3d_scene_end_session(scn), RES_OK);
f3(dir, 0.f, 1.f, 0.f);
CHECK(s3d_scene_trace_ray(scn, org, dir, range, &hit), RES_BAD_OP);
@@ -237,27 +237,27 @@ main(int argc, char** argv)
CHECK(s3d_shape_enable(inst, 0), RES_OK);
- CHECK(s3d_scene_begin_trace(scn), RES_OK);
- CHECK(s3d_scene_begin_trace(scn2), RES_BAD_OP);
- CHECK(s3d_scene_end_trace(scn), RES_OK);
- CHECK(s3d_scene_begin_trace(scn2), RES_OK);
- CHECK(s3d_scene_begin_trace(scn), RES_BAD_OP);
- CHECK(s3d_scene_end_trace(scn), RES_BAD_OP);
+ CHECK(s3d_scene_begin_session(scn, S3D_SESSION_TRACE), RES_OK);
+ CHECK(s3d_scene_begin_session(scn2, S3D_SESSION_TRACE), RES_BAD_OP);
+ CHECK(s3d_scene_end_session(scn), RES_OK);
+ CHECK(s3d_scene_begin_session(scn2, S3D_SESSION_TRACE), RES_OK);
+ CHECK(s3d_scene_begin_session(scn, S3D_SESSION_TRACE), RES_BAD_OP);
+ CHECK(s3d_scene_end_session(scn), RES_BAD_OP);
CHECK(s3d_scene_clear(scn2), RES_BAD_OP);
CHECK(s3d_scene_clear(scn), RES_BAD_OP);
- CHECK(s3d_scene_end_trace(scn2), RES_OK);
+ CHECK(s3d_scene_end_session(scn2), RES_OK);
CHECK(s3d_shape_enable(inst, 1), RES_OK);
- CHECK(s3d_scene_begin_trace(scn2), RES_OK);
- CHECK(s3d_scene_end_trace(scn2), RES_OK);
+ CHECK(s3d_scene_begin_session(scn2, S3D_SESSION_TRACE), RES_OK);
+ CHECK(s3d_scene_end_session(scn2), RES_OK);
CHECK(s3d_scene_clear(scn), RES_OK);
CHECK(s3d_scene_attach_shape(scn, walls), RES_OK);
CHECK(s3d_scene_attach_shape(scn, short_block), RES_OK);
CHECK(s3d_scene_attach_shape(scn, tall_block), RES_OK);
- CHECK(s3d_scene_begin_trace(scn2), RES_OK);
+ CHECK(s3d_scene_begin_session(scn2, S3D_SESSION_TRACE), RES_OK);
camera_init(&cam);
FOR_EACH(iy, 0, IMG_HEIGHT) {
@@ -325,7 +325,7 @@ main(int argc, char** argv)
}
}
}
- CHECK(s3d_scene_end_trace(scn2), RES_OK);
+ CHECK(s3d_scene_end_session(scn2), RES_OK);
if(argc > 1) {
CHECK(image_ppm_write(argv[1], IMG_WIDTH, IMG_HEIGHT, 3, img), RES_OK);