commit 282807c38404b499d4c4d0ad1c1a974542d1ee31
parent 5e60e840f66b6842d6579775b64518555765f1c4
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 24 Jun 2016 15:16:21 +0200
Implement and test the s2d_scene_trace_ray function
Diffstat:
7 files changed, 289 insertions(+), 46 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -128,6 +128,7 @@ if(NOT NO_TEST)
new_test(test_s2d_device)
new_test(test_s2d_scene)
new_test(test_s2d_shape)
+ new_test(test_s2d_trace_ray)
endif(NOT NO_TEST)
################################################################################
diff --git a/src/s2d_device.c b/src/s2d_device.c
@@ -105,3 +105,20 @@ s2d_device_ref_put(struct s2d_device* dev)
return RES_OK;
}
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+void
+log_error(struct s2d_device* dev, const char* msg, ...)
+{
+ va_list vargs_list;
+ ASSERT(dev && msg);
+ if(dev->verbose) {
+ res_T res; (void)res;
+ va_start(vargs_list, msg);
+ res = logger_vprint(dev->logger, LOG_ERROR, msg, vargs_list);
+ ASSERT(res == RES_OK);
+ va_end(vargs_list);
+ }
+}
+
diff --git a/src/s2d_device_c.h b/src/s2d_device_c.h
@@ -50,5 +50,15 @@ struct s2d_device {
ref_T ref;
};
+extern LOCAL_SYM void
+log_error
+ (struct s2d_device* dev,
+ const char* msg,
+ ...)
+#ifdef COMPILER_GCC
+ __attribute((format(printf, 2, 3)))
+#endif
+;
+
#endif /* S2D_DEVICE_C_H */
diff --git a/src/s2d_scene.c b/src/s2d_scene.c
@@ -35,6 +35,7 @@
#include <rsys/logger.h>
#include <rsys/float2.h>
+#include <rsys/float3.h>
#include <rsys/mem_allocator.h>
struct ray_extended : public RTCRay {
@@ -48,8 +49,30 @@ struct ray_extended : public RTCRay {
static INLINE void
hit_setup(struct s2d_scene* scn, const RTCRay* ray, struct s2d_hit* hit)
{
- (void)scn, (void)ray, (void)hit;
- /* TODO */
+ struct geometry* geom;
+
+ if((unsigned)ray->geomID == RTC_INVALID_GEOMETRY_ID) { /* No hit */
+ *hit = S2D_HIT_NULL;
+ return;
+ }
+ ASSERT(eq_epsf(ray->Ng[2], 0.f, 1.e-6f));
+ ASSERT((unsigned)ray->instID == RTC_INVALID_GEOMETRY_ID);
+ ASSERT((unsigned)ray->geomID < darray_geom_size_get(&scn->embree2geoms));
+
+ geom = darray_geom_data_get(&scn->embree2geoms)[ray->geomID];
+ ASSERT(geom);
+
+ hit->prim.mesh__ = geom;
+ hit->prim.prim_id = ray->primID;
+ hit->prim.geom_id = geom->name;
+ hit->prim.scene_prim_id = 0/* TODO */;
+ hit->normal[0] = ray->Ng[0];
+ hit->normal[1] = ray->Ng[1];
+ hit->distance = ray->tfar;
+ hit->u = ray->u; /* TODO Check that the hit "u" matches to the edge "u" */
+
+ if(geom->flip_contour)
+ f2_minus(hit->normal, hit->normal);
}
static void
@@ -184,10 +207,10 @@ scene_geometry_flush_indices(struct s2d_scene* scn, struct geometry* geom)
size_t id = i*2/*#ids per segment*/;
size_t rtc_id = i*4/*#ids per quad*/;
- rtc_ids[rtc_id + 0] = ids[id + 0] * 2/*#rtc vertices per line vertex*/ + 0;
- rtc_ids[rtc_id + 1] = ids[id + 0] * 2/*#rtc vertices per line vertex*/ + 1;
- rtc_ids[rtc_id + 2] = ids[id + 1] * 2/*#rtc vertices per line vertex*/ + 1;
- rtc_ids[rtc_id + 3] = ids[id + 1] * 2/*#rtc vertices per line vertex*/ + 0;
+ rtc_ids[rtc_id + 0] = ids[id + 0] * 2/*#rtc vertices per line vertex*/ + 1;
+ rtc_ids[rtc_id + 1] = ids[id + 0] * 2/*#rtc vertices per line vertex*/ + 0;
+ rtc_ids[rtc_id + 2] = ids[id + 1] * 2/*#rtc vertices per line vertex*/ + 0;
+ rtc_ids[rtc_id + 3] = ids[id + 1] * 2/*#rtc vertices per line vertex*/ + 1;
}
rtcUnmapBuffer(scn->rtc_scn, geom->irtc, RTC_INDEX_BUFFER);
}
@@ -325,11 +348,9 @@ scene_detach_shape
struct geometry* geom = *pgeom;
if(scn->session_mask != 0) {
- if(scn->dev->verbose) {
- logger_print(scn->dev->logger, LOG_ERROR,
- "%s: Cannot detach a shape currently in used in a scene session.\n",
- caller_name);
- }
+ log_error(scn->dev,
+ "%s: Cannot detach a shape currently in used in a scene session.\n",
+ caller_name);
return RES_BAD_OP;
}
if(geom->irtc != RTC_INVALID_GEOMETRY_ID) {
@@ -382,11 +403,9 @@ scene_sync
ASSERT(scn);
if(scn->session_mask != 0) {
- if(scn->dev->verbose) {
- logger_print(scn->dev->logger, LOG_ERROR,
- "%s: Invalid operation. The scene cannot be synced several times.\n",
- caller_name);
- }
+ log_error(scn->dev,
+ "%s: Invalid operation. The scene cannot be synced several times.\n",
+ caller_name);
res = RES_BAD_OP;
goto error;
}
@@ -508,11 +527,9 @@ s2d_scene_attach_shape(struct s2d_scene* scn, struct s2d_shape* shape)
if(!scn || !shape)
return RES_BAD_ARG;
if(!is_list_empty(&shape->scene_attachment)) {
- if(scn->dev->verbose) {
- logger_print(scn->dev->logger, LOG_ERROR,
- "%s: Cannot attach a shape that is already attached to a scene.\n",
- __FUNCTION__);
- }
+ log_error(scn->dev,
+ "%s: Cannot attach a shape that is already attached to a scene.\n",
+ __FUNCTION__);
return RES_BAD_ARG;
}
list_add_tail(&scn->shapes, &shape->scene_attachment);
@@ -529,11 +546,9 @@ s2d_scene_detach_shape(struct s2d_scene* scn, struct s2d_shape* shape)
if(!scn || !shape) return RES_BAD_ARG;
if(!(S2D(shape_is_attached(shape, &is_attached)), is_attached)) {
- if(scn->dev->verbose) {
- logger_print(scn->dev->logger, LOG_ERROR,
- "%s: The shape to detach is not attached to any scene.\n",
- __FUNCTION__);
- }
+ log_error(scn->dev,
+ "%s: The shape to detach is not attached to any scene.\n",
+ __FUNCTION__);
return RES_BAD_ARG;
}
#ifndef NDEBUG
@@ -561,11 +576,9 @@ s2d_scene_clear(struct s2d_scene* scn)
struct list_node* node, *tmp;
if(!scn) return RES_BAD_ARG;
if(scn->session_mask != 0) {
- if(scn->dev->verbose) {
- logger_print(scn->dev->logger, LOG_ERROR,
- "%s: Invalid operation. A session is active onto the scene.\n",
- __FUNCTION__);
- }
+ log_error(scn->dev,
+ "%s: Invalid operation. A session is active onto the scene.\n",
+ __FUNCTION__);
return RES_BAD_OP;
}
LIST_FOR_EACH_SAFE(node, tmp, &scn->shapes) {
@@ -584,11 +597,9 @@ s2d_scene_begin_session(struct s2d_scene* scn, const int session_mask)
if(!(session_mask & S2D_TRACE)
&& !(session_mask & S2D_SAMPLE)
&& !(session_mask & S2D_GET_PRIMITIVE)) {
- if(scn->dev->verbose) {
- logger_print(scn->dev->logger, LOG_ERROR,
- "%s: Invalid session mask. No valid session is defined.\n",
- __FUNCTION__);
- }
+ log_error(scn->dev,
+ "%s: Invalid session mask. No valid session is defined.\n",
+ __FUNCTION__);
return RES_BAD_ARG;
}
return scene_sync(scn, session_mask, __FUNCTION__);
@@ -600,11 +611,9 @@ s2d_scene_end_session(struct s2d_scene* scn)
if(!scn)
return RES_BAD_ARG;
if(!scn->session_mask) {
- if(scn->dev->verbose) {
- logger_print(scn->dev->logger, LOG_ERROR,
- "%s: Cannot end session. No session is currently active onto the scene.\n",
- __FUNCTION__);
- }
+ log_error(scn->dev,
+ "%s: Cannot end session. No session is currently active onto the scene.\n",
+ __FUNCTION__);
return RES_BAD_ARG;
}
scene_session_clear(scn);
@@ -620,3 +629,50 @@ s2d_scene_get_session_mask(struct s2d_scene* scn, int* session_mask)
return RES_OK;
}
+res_T
+s2d_scene_trace_ray
+ (struct s2d_scene* scn,
+ const float org[2],
+ const float dir[2],
+ const float range[2],
+ void* ray_data,
+ struct s2d_hit* hit)
+{
+ struct ray_extended ray_ex;
+
+ if(!scn || !org || !dir || !range || !hit)
+ return RES_BAD_ARG;
+ if(!f2_is_normalized(dir)) {
+ log_error(scn->dev,
+ "%s: The ray direction should be normalized.\n", __FUNCTION__);
+ return RES_BAD_ARG;
+ }
+ if((scn->session_mask & S2D_TRACE) == 0) {
+ log_error(scn->dev,
+ "%s: A S2D_TRACE session should be active onto the submitted scene.\n",
+ __FUNCTION__);
+ return RES_BAD_OP;
+ }
+ if(range[0] > range[1]) { /* Degenerated range <=> disabled ray */
+ *hit = S2D_HIT_NULL;
+ return RES_OK;
+ }
+
+ f3(ray_ex.org, org[0], org[1], 0.f);
+ f3(ray_ex.dir, dir[0], dir[1], 0.f);
+ ray_ex.tnear = range[0];
+ ray_ex.tfar = range[1];
+ ray_ex.geomID = RTC_INVALID_GEOMETRY_ID;
+ ray_ex.primID = RTC_INVALID_GEOMETRY_ID;
+ ray_ex.instID = RTC_INVALID_GEOMETRY_ID;
+ ray_ex.mask = 0xFFFFFFFF;
+ ray_ex.time = 0.f;
+ ray_ex.scene = scn;
+ ray_ex.data = ray_data;
+
+ rtcIntersect(scn->rtc_scn, ray_ex);
+ hit_setup(scn, &ray_ex, hit);
+
+ return RES_OK;
+}
+
diff --git a/src/test_s2d_scene.c b/src/test_s2d_scene.c
@@ -97,7 +97,6 @@ main(int argc, char** argv)
CHECK(s2d_scene_get_session_mask(scn, &mask), RES_OK);
CHECK(mask, 0);
-
attrib.type = S2D_FLOAT2;
attrib.usage = S2D_POSITION;
attrib.get = box_get_position;
diff --git a/src/test_s2d_trace_ray.c b/src/test_s2d_trace_ray.c
@@ -0,0 +1,160 @@
+/* Copyright (C) |Meso|Star> 2016 (contact@meso-star.com)
+ *
+ * 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 "s2d.h"
+#include "test_s2d_utils.h"
+
+#include <rsys/float2.h>
+
+int
+main(int argc, char** argv)
+{
+ struct s2d_device* dev;
+ struct s2d_shape* shape;
+ struct s2d_scene* scn;
+ struct s2d_vertex_data vdata;
+ struct s2d_hit hit;
+ struct mem_allocator allocator;
+ float org[2], dir[3], range[2];
+ float N[3] = {0.f, 0.f, 0.f};
+ (void)argc, (void)argv;
+
+ mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+
+ CHECK(s2d_device_create(NULL, &allocator, 1, &dev), RES_OK);
+ CHECK(s2d_shape_create_line_segments(dev, &shape), RES_OK);
+ CHECK(s2d_scene_create(dev, &scn), RES_OK);
+
+ vdata.type = S2D_FLOAT2;
+ vdata.usage = S2D_POSITION;
+ vdata.get = box_get_position;
+ CHECK(s2d_line_segments_setup_indexed_vertices
+ (shape, box_nsegs, box_get_ids, box_nverts, &vdata, 1, (void*)&box_desc),
+ RES_OK);
+
+ CHECK(s2d_scene_attach_shape(scn, shape), RES_OK);
+
+ f2(org, 0.f, 0.f);
+ f2(dir, 0.f, -1.f);
+ f2(range, 0, FLT_MAX);
+
+ CHECK(s2d_scene_begin_session(scn, S2D_TRACE), RES_OK);
+
+ CHECK(s2d_scene_trace_ray(NULL, NULL, NULL, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, NULL, NULL, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, org, NULL, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, org, NULL, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, NULL, dir, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, NULL, dir, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, org, dir, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, org, dir, NULL, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, NULL, NULL, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, NULL, NULL, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, org, NULL, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, org, NULL, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, NULL, dir, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, NULL, dir, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, org, dir, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, org, dir, range, NULL, NULL), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, NULL, NULL, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, NULL, NULL, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, org, NULL, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, org, NULL, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, NULL, dir, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, NULL, dir, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, org, dir, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, org, dir, NULL, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, NULL, NULL, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, NULL, NULL, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, org, NULL, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, org, NULL, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, NULL, dir, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(scn, NULL, dir, range, NULL, &hit), RES_BAD_ARG);
+ CHECK(s2d_scene_trace_ray(NULL, org, dir, range, NULL, &hit), RES_BAD_ARG);
+
+ f2(dir, 0.f, -1.f);
+ CHECK(s2d_scene_trace_ray(scn, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S2D_HIT_NONE(&hit), 0);
+ CHECK(hit.prim.prim_id, 0);
+ f2_normalize(N, hit.normal);
+ CHECK(f2_eq_eps(N, f2(dir, 0.f, 1.f), 1.e-6f), 1);
+ CHECK(eq_epsf(hit.u, 0.5f, 1.e-6f), 1);
+ CHECK(eq_epsf(hit.distance, 1.0f, 1.e-6f), 1);
+
+ f2(dir, -1.f, 0.f);
+ CHECK(s2d_scene_trace_ray(scn, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S2D_HIT_NONE(&hit), 0);
+ CHECK(hit.prim.prim_id, 1);
+ f2_normalize(N, hit.normal);
+ CHECK(f2_eq_eps(N, f2(dir, 1.f, 0.f), 1.e-6f), 1);
+ CHECK(eq_epsf(hit.u, 0.5f, 1.e-6f), 1);
+ CHECK(eq_epsf(hit.distance, 1.0f, 1.e-6f), 1);
+
+ f2(dir, 0.f, 1.f);
+ CHECK(s2d_scene_trace_ray(scn, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S2D_HIT_NONE(&hit), 0);
+ CHECK(hit.prim.prim_id, 2);
+ f2_normalize(N, hit.normal);
+ CHECK(f2_eq_eps(N, f2(dir, 0.f, -1.f), 1.e-6f), 1);
+ CHECK(eq_epsf(hit.u, 0.5f, 1.e-6f), 1);
+ CHECK(eq_epsf(hit.distance, 1.0f, 1.e-6f), 1);
+
+ f2(dir, 1.f, 0.f);
+ CHECK(s2d_scene_trace_ray(scn, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S2D_HIT_NONE(&hit), 0);
+ CHECK(hit.prim.prim_id, 3);
+ f2_normalize(N, hit.normal);
+ CHECK(f2_eq_eps(N, f2(dir, -1.f, 0.f), 1.e-6f), 1);
+ CHECK(eq_epsf(hit.u, 0.5f, 1.e-6f), 1);
+ CHECK(eq_epsf(hit.distance, 1.0f, 1.e-6f), 1);
+
+ f2(range, 1.f, -1.f);
+ CHECK(s2d_scene_trace_ray(scn, org, dir, range, NULL, &hit), RES_OK);
+ CHECK(S2D_HIT_NONE(&hit), 1);
+
+ f2(dir, 1.f, 1.f);
+ f2(range, 0.f, FLT_MAX);
+ CHECK(s2d_scene_trace_ray(scn, org, dir, range, NULL, &hit), RES_BAD_ARG);
+
+ CHECK(s2d_scene_end_session(scn), RES_OK);
+
+ f2(dir, 1.f, 0.f);
+ f2(range, 0.f, FLT_MAX);
+ CHECK(s2d_scene_trace_ray(scn, org, dir, range, NULL, &hit), RES_BAD_OP);
+
+ CHECK(s2d_device_ref_put(dev), RES_OK);
+ CHECK(s2d_shape_ref_put(shape), RES_OK);
+ CHECK(s2d_scene_ref_put(scn), RES_OK);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHECK(mem_allocated_size(), 0);
+
+ return 0;
+}
+
diff --git a/src/test_s2d_utils.h b/src/test_s2d_utils.h
@@ -41,10 +41,10 @@ struct box_desc {
* Box geometry
******************************************************************************/
static const float box_verts[] = {
- 552.f, 0.f,
- 0.f, 0.f,
- 0.f, 559.f,
- 552.f, 559.f
+ 1.f, -1.f,
+ -1.f, -1.f,
+ -1.f, 1.f,
+ 1.f, 1.f
};
const unsigned box_nverts = sizeof(box_verts)/sizeof(float[2]);