star-2d

Contour structuring for efficient 2D geometric queries
git clone git://git.meso-star.fr/star-2d.git
Log | Files | Refs | README | LICENSE

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:
Mcmake/CMakeLists.txt | 1+
Msrc/s2d_device.c | 17+++++++++++++++++
Msrc/s2d_device_c.h | 10++++++++++
Msrc/s2d_scene.c | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/test_s2d_scene.c | 1-
Asrc/test_s2d_trace_ray.c | 160+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_s2d_utils.h | 8++++----
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]);