commit e3e536e1a075572a6c01b8262151950cf7be963d
parent 6bbd7d19755a04c283db5bd189b97ba5fff0c09f
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 1 Jul 2016 12:26:00 +0200
Add verbosity to the s3d_scene API
Conditionally print error/warning messages with respect to the
verbosity of the Star-3D device.
Diffstat:
5 files changed, 169 insertions(+), 28 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -44,7 +44,7 @@ set(Embree_DIR ${_current_source_dir}/)
find_package(Embree REQUIRED)
find_package(RCMake 0.2.2 REQUIRED)
-find_package(RSys 0.2.1 REQUIRED)
+find_package(RSys 0.3.1 REQUIRED)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR})
include(rcmake)
include(rcmake_runtime)
diff --git a/src/s3d_device.c b/src/s3d_device.c
@@ -40,6 +40,21 @@
/*******************************************************************************
* Helper functions
******************************************************************************/
+static INLINE void
+log_msg
+ (struct s3d_device* dev,
+ const enum log_type stream,
+ const char* msg,
+ va_list vargs)
+{
+ ASSERT(dev && msg);
+ if(dev->verbose) {
+ res_T res; (void)res;
+ res = logger_vprint(dev->logger, stream, msg, vargs);
+ ASSERT(res == RES_OK);
+ }
+}
+
static void
device_release(ref_T* ref)
{
@@ -110,3 +125,28 @@ s3d_device_ref_put(struct s3d_device* dev)
return RES_OK;
}
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+void
+log_error(struct s3d_device* dev, const char* msg, ...)
+{
+ va_list vargs_list;
+ ASSERT(dev && msg);
+
+ va_start(vargs_list, msg);
+ log_msg(dev, LOG_ERROR, msg, vargs_list);
+ va_end(vargs_list);
+}
+
+void
+log_warning(struct s3d_device* dev, const char* msg, ...)
+{
+ va_list vargs_list;
+ ASSERT(dev && msg);
+
+ va_start(vargs_list, msg);
+ log_msg(dev, LOG_WARNING, msg, vargs_list);
+ va_end(vargs_list);
+}
+
diff --git a/src/s3d_device_c.h b/src/s3d_device_c.h
@@ -54,5 +54,29 @@ struct s3d_device {
ref_T ref;
};
+/* Conditionally log a message on the LOG_ERROR stream of the device logger,
+ * with respect to the device verbose flag */
+extern LOCAL_SYM void
+log_error
+ (struct s3d_device* dev,
+ const char* msg,
+ ...)
+#ifdef COMPILER_GCC
+ __attribute((format(printf, 2, 3)))
+#endif
+;
+
+/* Conditionally log a message on the LOG_WARNING stream of the device logger,
+ * with respect to the device verbose flag */
+extern LOCAL_SYM void
+log_warning
+ (struct s3d_device* dev,
+ const char* msg,
+ ...)
+#ifdef COMPILER_GCC
+ __attribute((format(printf, 2, 3)))
+#endif
+;
+
#endif /* S3D_DEVICE_C_H */
diff --git a/src/s3d_scene.c b/src/s3d_scene.c
@@ -443,7 +443,8 @@ error:
}
static res_T
-scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
+scene_detach_shape
+ (struct s3d_scene* scn, struct s3d_shape* shape, const char* caller_name)
{
struct geometry** pgeom;
ASSERT(scn && shape && !is_list_empty(&shape->scene_attachment));
@@ -452,7 +453,11 @@ scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
pgeom = htable_geom_find(&scn->cached_geoms, &shape);
if(pgeom) { /* Remove the cached shape mesh */
struct geometry* geom = *pgeom;
- if(scn->session_mask != 0) return RES_BAD_OP;
+ if(scn->session_mask != 0) {
+ log_error(scn->dev,
+ "%s: the shape is currently used in a scene session.\n", caller_name);
+ return RES_BAD_OP;
+ }
if(geom->irtc != RTC_INVALID_GEOMETRY_ID) {
rtcDeleteGeometry(scn->rtc_scn, geom->irtc);
@@ -835,10 +840,16 @@ s3d_scene_attach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
{
if(!scn || !shape)
return RES_BAD_ARG;
- if(!is_list_empty(&shape->scene_attachment))
+ if(!is_list_empty(&shape->scene_attachment)) {
+ log_error(scn->dev,
+ "%s: the shape is already attached to a scene.\n", FUNC_NAME);
return RES_BAD_ARG;
- if(shape->type == GEOM_INSTANCE && shape->data.instance->scene == scn)
+ }
+ if(shape->type == GEOM_INSTANCE && shape->data.instance->scene == scn) {
+ log_error(scn->dev,
+ "%s: the instantiated scene cannot be attached to itself.\n", FUNC_NAME);
return RES_BAD_ARG;
+ }
list_add_tail(&scn->shapes, &shape->scene_attachment);
S3D(shape_ref_get(shape));
@@ -853,8 +864,11 @@ s3d_scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
char is_attached;
if(!scn || !shape) return RES_BAD_ARG;
- if(!(S3D(shape_is_attached(shape, &is_attached)), is_attached))
+ if(!(S3D(shape_is_attached(shape, &is_attached)), is_attached)) {
+ log_error(scn->dev,
+ "%s: the shape is not attached to a scene.\n", FUNC_NAME);
return RES_BAD_ARG;
+ }
#ifndef NDEBUG
{ /* Check that the shape is attached to `scn' */
struct list_node* node;
@@ -868,7 +882,7 @@ s3d_scene_detach_shape(struct s3d_scene* scn, struct s3d_shape* shape)
ASSERT(is_found);
}
#endif
- res = scene_detach_shape(scn, shape);
+ res = scene_detach_shape(scn, shape, FUNC_NAME);
if(res != RES_OK) return res;
return RES_OK;
}
@@ -878,11 +892,15 @@ s3d_scene_clear(struct s3d_scene* scn)
{
struct list_node* node, *tmp;
if(!scn) return RES_BAD_ARG;
- if(scn->session_mask != 0) return RES_BAD_OP;
+ if(scn->session_mask != 0) {
+ log_error(scn->dev,
+ "%s: cannot clear a scene with an active session.\n", FUNC_NAME);
+ return RES_BAD_OP;
+ }
LIST_FOR_EACH_SAFE(node, tmp, &scn->shapes) {
struct s3d_shape* shape = CONTAINER_OF
(node, struct s3d_shape, scene_attachment);
- const res_T res = scene_detach_shape(scn, shape);
+ const res_T res = scene_detach_shape(scn, shape, FUNC_NAME);
ASSERT(res == RES_OK); (void)res;
}
return RES_OK;
@@ -895,8 +913,10 @@ s3d_scene_begin_session(struct s3d_scene* scn, const int session_mask)
return RES_BAD_ARG;
if(!(session_mask&S3D_TRACE)
&& !(session_mask&S3D_SAMPLE)
- && !(session_mask&S3D_GET_PRIMITIVE))
+ && !(session_mask&S3D_GET_PRIMITIVE)) {
+ log_error(scn->dev, "%s: no valid session is defined.\n", FUNC_NAME);
return RES_BAD_ARG;
+ }
return scene_sync(scn, session_mask);
}
@@ -905,8 +925,16 @@ s3d_scene_end_session(struct s3d_scene* scn)
{
if(!scn)
return RES_BAD_ARG;
- if(scn->session_mask & S3D_INSTANCE || !scn->session_mask)
+ if(scn->session_mask & S3D_INSTANCE) {
+ log_error(scn->dev,
+ "%s: the scene session was enabled through scene instantiation.\n",
+ FUNC_NAME);
+ return RES_BAD_OP;
+ }
+ if(!scn->session_mask) {
+ log_error(scn->dev, "%s: the scene has no active session.\n", FUNC_NAME);
return RES_BAD_OP;
+ }
scene_session_clear(scn);
return RES_OK;
}
@@ -932,11 +960,18 @@ s3d_scene_trace_ray
struct ray_extended ray_ex;
if(!scn || !org || !dir || !range || !hit)
return RES_BAD_ARG;
- if(!f3_is_normalized(dir))
+ if(!f3_is_normalized(dir)) {
+ log_error(scn->dev,
+ "%s: unnormalized ray direction {%g, %g, %g}.\n",
+ FUNC_NAME, SPLIT3(dir));
return RES_BAD_ARG;
- if((scn->session_mask & S3D_TRACE) == 0)
+ }
+ if((scn->session_mask & S3D_TRACE) == 0) {
+ log_error(scn->dev,
+ "%s: no active S3D_TRACE session on the submitted scene.\n", FUNC_NAME);
return RES_BAD_OP;
- if(range[0] > range[1]) {
+ }
+ if(range[0] > range[1]) { /* Degenerated range <=> disabled ray */
*hit = S3D_HIT_NULL;
return RES_OK;
}
@@ -1020,10 +1055,16 @@ s3d_scene_sample
}
/* Expecting canonic numbers */
if(u < 0.f || u >= 1.f || v < 0.f || v >= 1.f || w < 0.f || w >= 1.f) {
+ log_error(scn->dev,
+ "%s: the submitted numbers are not canonical, i.e. they are not in [0, 1[.\n",
+ FUNC_NAME);
res = RES_BAD_ARG;
goto error;
}
if((scn->session_mask & S3D_SAMPLE) == 0) {
+ log_error(scn->dev,
+ "%s: no active S3D_SAMPLE session on the submitted scene.\n",
+ FUNC_NAME);
res = RES_BAD_OP;
goto error;
}
@@ -1115,11 +1156,17 @@ s3d_scene_get_primitive
goto error;
}
if((scn->session_mask & S3D_GET_PRIMITIVE) == 0) {
+ log_error(scn->dev,
+ "%s: no active S3D_GET_PRIMITIVE session on the submitted scene.\n",
+ FUNC_NAME);
res = RES_BAD_OP;
goto error;
}
S3D(scene_primitives_count(scn, &nprims));
if(iprim >= nprims) {
+ log_error(scn->dev,
+ "%s: the primitive index %u exceeds the number of scene primitives %u.\n",
+ FUNC_NAME, iprim, (unsigned)nprims);
res = RES_BAD_ARG;
goto error;
}
@@ -1194,6 +1241,8 @@ s3d_scene_primitives_count(struct s3d_scene* scn, size_t* prims_count)
goto error;
}
if(!scn->session_mask) {
+ log_error(scn->dev,
+ "%s: no active session on the submitted scene.\n", FUNC_NAME);
res = RES_BAD_OP;
goto error;
}
@@ -1238,15 +1287,18 @@ error:
}
res_T
-s3d_scene_compute_area(struct s3d_scene* scn, float* area)
+s3d_scene_compute_area(struct s3d_scene* scn, float* out_area)
{
+ float area;
res_T res = RES_OK;
- if(!scn || !area) {
+ if(!scn || !out_area) {
res = RES_BAD_ARG;
goto error;
}
if(!scn->session_mask) {
+ log_error(scn->dev,
+ "%s: no active session on the submitted scene.\n", FUNC_NAME);
res = RES_BAD_OP;
goto error;
}
@@ -1257,9 +1309,9 @@ s3d_scene_compute_area(struct s3d_scene* scn, float* area)
* multiplied by 2; the real scene area is thus the CDF upper bound / 2 */
size_t len = darray_fltui_size_get(&scn->cdf);
if(!len) {
- *area = 0.f;
+ area = 0.f;
} else {
- *area = darray_fltui_cdata_get(&scn->cdf)[len - 1].flt * 0.5f;
+ area = darray_fltui_cdata_get(&scn->cdf)[len - 1].flt * 0.5f;
}
} else {
struct list_node* node;
@@ -1268,7 +1320,7 @@ s3d_scene_compute_area(struct s3d_scene* scn, float* area)
struct geometry* geom;
float inst_area;
- *area = 0.f;
+ area = 0.f;
LIST_FOR_EACH(node, &scn->shapes) {
shape = CONTAINER_OF(node, struct s3d_shape, scene_attachment);
pgeom = htable_geom_find(&scn->cached_geoms, &shape);
@@ -1279,12 +1331,12 @@ s3d_scene_compute_area(struct s3d_scene* scn, float* area)
switch(geom->type) {
case GEOM_MESH:
- *area += mesh_compute_area(geom->data.mesh);
+ area += mesh_compute_area(geom->data.mesh);
break;
case GEOM_INSTANCE:
/* TODO take into account the instance scale factor */
S3D(scene_compute_area(geom->data.instance->scene, &inst_area));
- *area += inst_area;
+ area += inst_area;
break;
default: FATAL("Unreachable code\n"); break;
}
@@ -1292,30 +1344,35 @@ s3d_scene_compute_area(struct s3d_scene* scn, float* area)
}
exit:
+ if(out_area) *out_area = area;
return res;
error:
+ area = -1.f;
goto exit;
}
res_T
-s3d_scene_compute_volume(struct s3d_scene* scn, float* volume)
+s3d_scene_compute_volume(struct s3d_scene* scn, float* out_volume)
{
struct list_node* node;
struct s3d_shape* shape;
struct geometry** pgeom;
struct geometry* geom;
+ float volume;
res_T res = RES_OK;
- if(!scn || !volume) {
+ if(!scn || !out_volume) {
res = RES_BAD_ARG;
goto error;
}
if(!scn->session_mask) {
+ log_error(scn->dev,
+ "%s: no active session on the submitted scene.\n", FUNC_NAME);
res = RES_BAD_OP;
goto error;
}
- *volume = 0.f;
+ volume = 0.f;
LIST_FOR_EACH(node, &scn->shapes) {
shape = CONTAINER_OF(node, struct s3d_shape, scene_attachment);
pgeom = htable_geom_find(&scn->cached_geoms, &shape);
@@ -1326,18 +1383,28 @@ s3d_scene_compute_volume(struct s3d_scene* scn, float* volume)
switch(geom->type) {
case GEOM_MESH:
- *volume += mesh_compute_volume(geom->data.mesh, geom->flip_surface);
+ volume += mesh_compute_volume(geom->data.mesh, geom->flip_surface);
break;
case GEOM_INSTANCE:
- *volume += instance_compute_volume(geom->data.instance, geom->flip_surface);
+ volume += instance_compute_volume(geom->data.instance, geom->flip_surface);
break;
default: FATAL("Unreachable code\n"); break;
}
}
+ if(volume < 0.f) {
+ log_warning(scn->dev,
+"%s:\n"
+"\tthe volume is negative. The scene shapes might not represent closed 2D\n"
+"\tmanifold volumes, or their surface normal might not point inward the volume.\n",
+ FUNC_NAME);
+ }
+
exit:
+ if(out_volume) *out_volume = volume;
return res;
error:
+ volume = -1.f;
goto exit;
}
@@ -1345,7 +1412,11 @@ res_T
s3d_scene_get_aabb(struct s3d_scene* scn, float lower[3], float upper[3])
{
if(!scn || !lower || !upper) return RES_BAD_ARG;
- if(!scn->session_mask) return RES_BAD_OP;
+ if(!scn->session_mask) {
+ log_error(scn->dev,
+ "%s: no active session on the submitted scene.\n", FUNC_NAME);
+ return RES_BAD_OP;
+ }
f3_set(lower, scn->lower);
f3_set(upper, scn->upper);
return RES_OK;
diff --git a/src/test_s3d_scene.c b/src/test_s3d_scene.c
@@ -105,7 +105,7 @@ main(int argc, char** argv)
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHECK(s3d_device_create(NULL, &allocator, 0, &dev), RES_OK);
+ CHECK(s3d_device_create(NULL, &allocator, 1, &dev), RES_OK);
FOR_EACH(i, 0, nshapes)
CHECK(s3d_shape_create_mesh(dev, shapes + i), RES_OK);
@@ -323,6 +323,12 @@ main(int argc, char** argv)
CHECK(eq_epsf(volume, 1.f, 1.e-6f), 1);
CHECK(s3d_scene_end_session(scn), RES_OK);
+ CHECK(s3d_shape_flip_surface(shapes[0]), RES_OK);
+ CHECK(s3d_scene_begin_session(scn, S3D_GET_PRIMITIVE), RES_OK);
+ CHECK(s3d_scene_compute_volume(scn, &volume), RES_OK);
+ CHECK(eq_epsf(volume, -1.f, 1.e-6f), 1);
+ CHECK(s3d_scene_end_session(scn), RES_OK);
+
CHECK(s3d_scene_get_device(NULL, NULL), RES_BAD_ARG);
CHECK(s3d_scene_get_device(scn, NULL), RES_BAD_ARG);
CHECK(s3d_scene_get_device(NULL, &dev2), RES_BAD_ARG);