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 c1939428ea5f4a43ffb5708d6fbed14212a83ffd
parent 06c70c6a82b24504b8c347da0bb8730ef846ebb6
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Tue,  5 Jan 2021 17:43:43 +0100

Add a test on raytrace accuracy

Diffstat:
Mcmake/CMakeLists.txt | 1+
Asrc/test_s2d_raytrace.c | 206+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 207 insertions(+), 0 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -137,6 +137,7 @@ if(NOT NO_TEST) new_test(test_s2d_closest_point) new_test(test_s2d_device) new_test(test_s2d_primitive) + new_test(test_s2d_raytrace) new_test(test_s2d_sample) new_test(test_s2d_shape) new_test(test_s2d_scene) diff --git a/src/test_s2d_raytrace.c b/src/test_s2d_raytrace.c @@ -0,0 +1,206 @@ +/* Copyright (C) 2016-2020 |Meso|Star> (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> +#include <rsys/float3.h> + +/******************************************************************************* + * Single segment test + ******************************************************************************/ +static void +test_single_segment(struct s2d_device* dev) +{ + struct s2d_vertex_data vdata = S2D_VERTEX_DATA_NULL; + struct line_segments_desc desc; + struct s2d_hit hit = S2D_HIT_NULL; + struct s2d_hit hit3 = S2D_HIT_NULL; + struct s2d_scene* scn = NULL; + struct s2d_scene_view* view = NULL; + struct s2d_shape* shape = NULL; + struct s2d_attrib attr; + float vertices[4]; + float v0[2], v1[2]; + float pos[2]; + size_t i, j; + unsigned indices[2] = {0, 1}; + + f2(vertices+0, -0.5f, -0.3f); + f2(vertices+2, -0.4f, 0.2f); + + CHK(s2d_scene_create(dev, &scn) == RES_OK); + CHK(s2d_shape_create_line_segments(dev, &shape) == RES_OK); + CHK(s2d_scene_attach_shape(scn, shape) == RES_OK); + + vdata.usage = S2D_POSITION; + vdata.type = S2D_FLOAT2; + vdata.get = line_segments_get_position; + desc.vertices = vertices; + desc.indices = indices; + CHK(s2d_line_segments_setup_indexed_vertices + (shape, 1, line_segments_get_ids, 2, &vdata, 1, &desc) == RES_OK); + + CHK(s2d_scene_view_create(scn, S2D_TRACE, &view) == RES_OK); + + line_segments_get_position(0, v0, &desc); + line_segments_get_position(1, v1, &desc); + + CHK(s2d_scene_view_ref_put(view) == RES_OK); + CHK(s2d_shape_ref_put(shape) == RES_OK); + CHK(s2d_scene_ref_put(scn) == RES_OK); + + FOR_EACH(i, 0, 100) { + float A[2], B[2], tmp[2]; + const float amplitude = 10000; + const float eps = 1e-6f * amplitude; + /* Randomly generate a segment AB on the X axis */ + A[0] = (rand_canonic() - 0.5f) * amplitude; + do B[0] = (rand_canonic() - 0.5f) * amplitude; + while(fabsf(A[0] - B[0]) < eps); + A[1] = B[1] = 0; + + f2_set(vertices + 0, A); + f2_set(vertices + 2, B); + + CHK(s2d_scene_create(dev, &scn) == RES_OK); + CHK(s2d_shape_create_line_segments(dev, &shape) == RES_OK); + CHK(s2d_scene_attach_shape(scn, shape) == RES_OK); + + vdata.usage = S2D_POSITION; + vdata.type = S2D_FLOAT2; + vdata.get = line_segments_get_position; + desc.vertices = vertices; + desc.indices = indices; + CHK(s2d_line_segments_setup_indexed_vertices + (shape, 1, line_segments_get_ids, 2, &vdata, 1, &desc) == RES_OK); + + CHK(s2d_scene_view_create(scn, S2D_TRACE, &view) == RES_OK); + + FOR_EACH(j, 0, 100) { + float l; + float dir[3], range[2] = { 0, FLT_MAX }; + + /* Randomly generate a pos not on the segment */ + pos[0] = (rand_canonic() - 0.5f) * amplitude; + do pos[1] = (rand_canonic() - 0.5f) * amplitude; + while (fabsf(pos[1]) < 1e-5); + + /* Raytrace towards the X axis (can hit or miss the segment) */ + f3(dir, 0, (pos[1] > 0 ? -1.f : 1.f), rand_canonic() - 0.5f); + CHK(s2d_scene_view_trace_ray(view, pos, dir, range, NULL, &hit) == RES_OK); + l = f3_normalize(dir, dir); + CHK(s2d_scene_view_trace_ray_3d(view, pos, dir, range, NULL, &hit3) == RES_OK); + + /* Check the result */ + if((A[0] > pos[0] && B[0] > pos[0]) || (A[0] < pos[0] && B[0] < pos[0])) { + CHK(S2D_HIT_NONE(&hit)); + CHK(S2D_HIT_NONE(&hit3)); + } else { + float expected[2]; + float d = f2_len(f2_sub(tmp, pos, expected)); + f2(expected, pos[0], 0); + d = f2_len(f2_sub(tmp, pos, expected)); + CHK(!S2D_HIT_NONE(&hit)); + CHK(eq_epsf(hit.distance, d, eps)); + CHK(eq_epsf(hit3.distance, d * l, eps)); + CHK(s2d_primitive_get_attrib(&hit.prim, S2D_POSITION, hit.u, &attr) == RES_OK); + CHK(f2_eq_eps(attr.value, expected, eps)); + CHK(s2d_primitive_get_attrib(&hit3.prim, S2D_POSITION, hit3.u, &attr) == RES_OK); + CHK(f2_eq_eps(attr.value, expected, eps)); + } + } + + CHK(s2d_scene_view_ref_put(view) == RES_OK); + CHK(s2d_shape_ref_put(shape) == RES_OK); + CHK(s2d_scene_ref_put(scn) == RES_OK); + } +} + +/******************************************************************************* + * Miscellaneous test + ******************************************************************************/ +static void +test_api(struct s2d_device* dev) +{ + struct s2d_hit hit = S2D_HIT_NULL; + struct s2d_scene* scn = NULL; + struct s2d_scene_view* view = NULL; + float pos[3] = { 0 }, dir[3] = { 1 }, range[2] = { 0, 1 }; + + CHK(s2d_scene_create(dev, &scn) == RES_OK); + CHK(s2d_scene_view_create(scn, S2D_TRACE, &view) == RES_OK); + + CHK(s2d_scene_view_trace_ray(NULL, pos, dir, range, NULL, &hit) == RES_BAD_ARG); + CHK(s2d_scene_view_trace_ray(view, NULL, dir, range, NULL, &hit) == RES_BAD_ARG); + CHK(s2d_scene_view_trace_ray(view, pos, NULL, range, NULL, &hit) == RES_BAD_ARG); + CHK(s2d_scene_view_trace_ray(view, pos, dir, NULL, NULL, &hit) == RES_BAD_ARG); + CHK(s2d_scene_view_trace_ray(view, pos, dir, range, NULL, NULL) == RES_BAD_ARG); + CHK(s2d_scene_view_trace_ray(view, pos, dir, range, NULL, &hit) == RES_OK); + CHK(S2D_HIT_NONE(&hit)); + + CHK(s2d_scene_view_trace_ray_3d(NULL, pos, dir, range, NULL, &hit) == RES_BAD_ARG); + CHK(s2d_scene_view_trace_ray_3d(view, NULL, dir, range, NULL, &hit) == RES_BAD_ARG); + CHK(s2d_scene_view_trace_ray_3d(view, pos, NULL, range, NULL, &hit) == RES_BAD_ARG); + CHK(s2d_scene_view_trace_ray_3d(view, pos, dir, NULL, NULL, &hit) == RES_BAD_ARG); + CHK(s2d_scene_view_trace_ray_3d(view, pos, dir, range, NULL, NULL) == RES_BAD_ARG); + CHK(s2d_scene_view_trace_ray_3d(view, pos, dir, range, NULL, &hit) == RES_OK); + CHK(S2D_HIT_NONE(&hit)); + + CHK(s2d_scene_view_ref_put(view) == RES_OK); + CHK(s2d_scene_view_create(scn, S2D_SAMPLE, &view) == RES_OK); + CHK(s2d_scene_view_closest_point(view, pos, 1.f, NULL, &hit) == RES_BAD_OP); + + CHK(s2d_scene_view_ref_put(view) == RES_OK); + CHK(s2d_scene_ref_put(scn) == RES_OK); +} + +/******************************************************************************* + * Main function + ******************************************************************************/ +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct s2d_device* dev = NULL; + (void)argc, (void)argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + CHK(s2d_device_create(NULL, &allocator, 1, &dev) == RES_OK); + + test_api(dev); + test_single_segment(dev); + + CHK(s2d_device_ref_put(dev) == RES_OK); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +}