star-3d

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

commit 743121ccc6c2ae3b15bd5383a2a2ba3fcf89f1ba
parent 12415ae8847a1ae4c8b20795e4be979f10351966
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 17 Apr 2015 14:19:06 +0200

Test the sampler API

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/s3d_sampler.c | 67++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Asrc/test_s3d_sampler.c | 160+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_s3d_trace_ray.c | 1-
4 files changed, 217 insertions(+), 12 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -117,6 +117,7 @@ if(NOT NO_TEST) endfunction(new_test) new_test(test_s3d_device) + new_test(test_s3d_sampler) new_test(test_s3d_scene) new_test(test_s3d_shape) new_test(test_s3d_trace_ray) diff --git a/src/s3d_sampler.c b/src/s3d_sampler.c @@ -169,6 +169,7 @@ sampler_compute_cdf(struct s3d_sampler* sampler) /* Fetched cached meshes */ meshes = darray_mesh_data_get(&sampler->cached_meshes); nmeshes = darray_mesh_size_get(&sampler->cached_meshes); + ASSERT(nmeshes); /* Reserve meshes CDF memory space */ sampler_clear_cdf(sampler); @@ -206,9 +207,11 @@ sampler_compute_cdf(struct s3d_sampler* sampler) * the triangle area since it saves computation times whithout affecting * the sampling result */ f3_sub(edges[0], positions[1], positions[0]); - f3_sub(edges[1], positions[2], positions[2]); + f3_sub(edges[1], positions[2], positions[0]); f3_cross(normal, edges[0], edges[1]); triangle_area = f3_len(normal); + /* TODO take into account the scale instance transformation in the + * computation of the triangle area */ /* Store the CDF value of the triangle `itri' */ area += triangle_area; @@ -218,6 +221,11 @@ sampler_compute_cdf(struct s3d_sampler* sampler) meshes_cdf[imesh] = area; } + if(eq_eps(area, 0, 1.e-6f)) { + res = RES_BAD_ARG; + goto error; + } + /* Normalize the meshes/triangles CDF */ rcp_area = 1.f / area; FOR_EACH(imesh, 0, nmeshes) { @@ -242,6 +250,12 @@ sampler_cache_mesh(struct s3d_sampler* sampler, char* upd_geom) res_T res = RES_OK; ASSERT(sampler && sampler->shape->type == SHAPE_MESH && upd_geom); + if(!sampler->shape->data.mesh->indices + || !sampler->shape->data.mesh->attribs[S3D_POSITION]) { + res = RES_BAD_ARG; + goto error; + } + if(darray_mesh_size_get(&sampler->cached_meshes)) { /* Fetch the cached entry */ mesh = darray_mesh_data_get(&sampler->cached_meshes)[0]; @@ -285,7 +299,12 @@ sampler_cache_instance(struct s3d_sampler* sampler, char* upd_geom) (node, struct s3d_shape, scene_attachment); ASSERT(shape->type == SHAPE_MESH); - if(ishape <= darray_mesh_size_get(&sampler->cached_meshes)) { + /* Discard shapes with no geometry */ + if(!shape->data.mesh->indices + || !shape->data.mesh->attribs[S3D_POSITION]) + continue; + + if(ishape < darray_mesh_size_get(&sampler->cached_meshes)) { /* Fetch the previous cache entry */ mesh = darray_mesh_data_get(&sampler->cached_meshes)[ishape]; } else { @@ -296,7 +315,8 @@ sampler_cache_instance(struct s3d_sampler* sampler, char* upd_geom) if(res != RES_OK) goto error; } /* Cache the instance mesh data */ - *upd_geom = *upd_geom || cache_mesh(mesh, shape->data.mesh); + *upd_geom = cache_mesh(mesh, shape->data.mesh) || *upd_geom; + ++ishape; } nshapes = ishape; @@ -305,6 +325,12 @@ sampler_cache_instance(struct s3d_sampler* sampler, char* upd_geom) mesh_ref_put(darray_mesh_data_get(&sampler->cached_meshes)[ishape]); darray_mesh_resize(&sampler->cached_meshes, nshapes); + if(!nshapes) { + res = RES_BAD_ARG; + goto error; + } + + /* TODO take into account the scale transformation in the upd_geom flag */ *upd_geom = *upd_geom || (nshapes != ishape); exit: @@ -326,10 +352,11 @@ sampler_sync(struct s3d_sampler* sampler) return RES_BAD_OP; switch(sampler->shape->type) { - case SHAPE_MESH: sampler_cache_mesh(sampler, &upd_geom); break; - case SHAPE_INSTANCE: sampler_cache_instance(sampler, &upd_geom); break; + case SHAPE_MESH: res = sampler_cache_mesh(sampler, &upd_geom); break; + case SHAPE_INSTANCE: res = sampler_cache_instance(sampler, &upd_geom); break; default: FATAL("Unreachable code\n"); break; } + if(res != RES_OK) goto error; if(upd_geom) { res = sampler_compute_cdf(sampler); @@ -437,6 +464,7 @@ res_T s3d_sampler_end_sampling(struct s3d_sampler* sampler) { if(!sampler) return RES_BAD_ARG; + if(!sampler->is_sync) return RES_BAD_OP; sampler_clear(sampler); return RES_OK; } @@ -444,7 +472,9 @@ s3d_sampler_end_sampling(struct s3d_sampler* sampler) res_T s3d_sampler_get (struct s3d_sampler* sampler, - const float u, const float v, const float w, + const float u, + const float v, + const float w, struct s3d_primitive* primitive, /* sampled primitive */ float uv[2]) { @@ -461,13 +491,28 @@ s3d_sampler_get goto error; } + /* Expecting canonic numbers */ + if(u < 0.f || u >= 1.f || v < 0.f || v >= 1.f || w < 0.f || w >= 1.f) { + res = RES_BAD_ARG; + goto error; + } + + if(!sampler->is_sync) { + res = RES_BAD_OP; + goto error; + } + /* Find which mesh is sampled */ - cdf_start = darray_float_cdata_get(&sampler->meshes_cdf); - cdf_stop = cdf_start + darray_float_size_get(&sampler->triangles_cdf); - cdf_found = std::lower_bound(cdf_start, cdf_stop, u); - ASSERT(cdf_found != cdf_stop); + if(darray_float_size_get(&sampler->meshes_cdf) == 1) { + imesh = 0; + } else { + cdf_start = darray_float_cdata_get(&sampler->meshes_cdf); + cdf_stop = cdf_start + darray_float_size_get(&sampler->meshes_cdf); + cdf_found = std::lower_bound(cdf_start, cdf_stop, u); + ASSERT(cdf_found != cdf_stop); + imesh = cdf_found - cdf_start; + } - imesh = cdf_found - cdf_start; imesh2tri = darray_size_t_data_get(&sampler->mesh2triangle)[imesh]; mesh = darray_mesh_data_get(&sampler->cached_meshes)[imesh]; diff --git a/src/test_s3d_sampler.c b/src/test_s3d_sampler.c @@ -0,0 +1,160 @@ +/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) + * + * This software is a computer program whose purpose is to describe a + * virtual 3D environment that can be ray-traced and sampled both robustly + * and efficiently. + * + * 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 "s3d.h" +#include "test_s3d_cbox.h" +#include "test_s3d_utils.h" + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct s3d_device* dev; + struct s3d_scene* scn; + struct s3d_shape* cbox; + struct s3d_shape* walls; + struct s3d_shape* short_block; + struct s3d_shape* tall_block; + struct s3d_vertex_data attribs[2]; + struct s3d_sampler* sampler; + struct s3d_primitive prim; + struct cbox_desc desc; + float uv[2]; + unsigned ntris, nverts; + (void)argc, (void)argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + + CHECK(s3d_device_create(NULL, &allocator, &dev), RES_OK); + CHECK(s3d_scene_create(dev, &scn), RES_OK); + CHECK(s3d_scene_instantiate(scn, &cbox), RES_OK); + CHECK(s3d_shape_create_mesh(dev, &walls), RES_OK); + CHECK(s3d_shape_create_mesh(dev, &short_block), RES_OK); + CHECK(s3d_shape_create_mesh(dev, &tall_block), RES_OK); + + CHECK(s3d_sampler_create(NULL, NULL), RES_BAD_ARG); + CHECK(s3d_sampler_create(walls, NULL), RES_BAD_ARG); + CHECK(s3d_sampler_create(NULL, &sampler), RES_BAD_ARG); + CHECK(s3d_sampler_create(walls, &sampler), RES_OK); + + CHECK(s3d_sampler_begin_sampling(NULL), RES_BAD_ARG); + CHECK(s3d_sampler_begin_sampling(sampler), RES_BAD_ARG); + + attribs[0].usage = S3D_POSITION; + attribs[0].type = S3D_FLOAT3; + attribs[0].get = cbox_get_position; + attribs[1] = S3D_VERTEX_DATA_NULL; + + ntris = sizeof(cbox_walls_ids)/sizeof(unsigned[3]); + nverts = sizeof(cbox_walls)/sizeof(float[3]); + desc.vertices = cbox_walls; + desc.indices = cbox_walls_ids; + CHECK(s3d_mesh_setup_indexed_vertices + (walls, ntris, cbox_get_ids, nverts, attribs, &desc), RES_OK); + + CHECK(s3d_sampler_begin_sampling(sampler), RES_OK); + CHECK(s3d_sampler_begin_sampling(sampler), RES_BAD_OP); + + CHECK(s3d_sampler_get(NULL, 0, 0, 0, NULL, NULL), RES_BAD_ARG); + CHECK(s3d_sampler_get(sampler, 0, 0, 0, NULL, NULL), RES_BAD_ARG); + CHECK(s3d_sampler_get(NULL, 0, 0, 0, &prim, NULL), RES_BAD_ARG); + CHECK(s3d_sampler_get(sampler, 0, 0, 0, &prim, NULL), RES_BAD_ARG); + CHECK(s3d_sampler_get(NULL, 0, 0, 0, NULL, uv), RES_BAD_ARG); + CHECK(s3d_sampler_get(sampler, 0, 0, 0, NULL, uv), RES_BAD_ARG); + CHECK(s3d_sampler_get(NULL, 0, 0, 0, &prim, uv), RES_BAD_ARG); + CHECK(s3d_sampler_get(sampler, 0, 0, 0, &prim, uv), RES_OK); + CHECK(s3d_sampler_get(sampler, -1, 0, 0, &prim, uv), RES_BAD_ARG); + CHECK(s3d_sampler_get(sampler, 0, -1, 0, &prim, uv), RES_BAD_ARG); + CHECK(s3d_sampler_get(sampler, 0, 0, -1, &prim, uv), RES_BAD_ARG); + CHECK(s3d_sampler_get(sampler, 1, 0, 0, &prim, uv), RES_BAD_ARG); + CHECK(s3d_sampler_get(sampler, 0, 1, 0, &prim, uv), RES_BAD_ARG); + CHECK(s3d_sampler_get(sampler, 0, 0, 1, &prim, uv), RES_BAD_ARG); + CHECK(s3d_sampler_get(sampler, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK); + + CHECK(s3d_sampler_end_sampling(NULL), RES_BAD_ARG); + CHECK(s3d_sampler_end_sampling(sampler), RES_OK); + CHECK(s3d_sampler_end_sampling(sampler), RES_BAD_OP); + CHECK(s3d_sampler_get(sampler, 0.5f, 0.5f, 0.5f, &prim, uv), RES_BAD_OP); + + CHECK(s3d_sampler_ref_get(NULL), RES_BAD_ARG); + CHECK(s3d_sampler_ref_get(sampler), RES_OK); + CHECK(s3d_sampler_ref_put(NULL), RES_BAD_ARG); + CHECK(s3d_sampler_ref_put(sampler), RES_OK); + CHECK(s3d_sampler_ref_put(sampler), RES_OK); + + ntris = sizeof(cbox_block_ids)/sizeof(unsigned[3]); + nverts = sizeof(cbox_short_block)/sizeof(float[3]); + desc.vertices = cbox_short_block; + desc.indices = cbox_block_ids; + CHECK(s3d_mesh_setup_indexed_vertices + (short_block, ntris, cbox_get_ids, nverts, attribs, &desc), RES_OK); + + CHECK(s3d_sampler_create(cbox, &sampler), RES_OK); + CHECK(s3d_sampler_begin_sampling(sampler), RES_BAD_ARG); + + 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_sampler_begin_sampling(sampler), RES_OK); + CHECK(s3d_sampler_get(sampler, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK); + desc.vertices = cbox_tall_block; + CHECK(s3d_mesh_setup_indexed_vertices + (tall_block, ntris, cbox_get_ids, nverts, attribs, &desc), RES_OK); + CHECK(s3d_sampler_get(sampler, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK); + /* TODO Check that the sample is the same */ + CHECK(s3d_sampler_end_sampling(sampler), RES_OK); + + CHECK(s3d_sampler_begin_sampling(sampler), RES_OK); + CHECK(s3d_sampler_get(sampler, 0.5f, 0.5f, 0.5f, &prim, uv), RES_OK); + /* TODO Check that the sample is *not* the same */ + CHECK(s3d_sampler_end_sampling(sampler), RES_OK); + + CHECK(s3d_sampler_ref_get(NULL), RES_BAD_ARG); + CHECK(s3d_sampler_ref_get(sampler), RES_OK); + CHECK(s3d_sampler_ref_put(NULL), RES_BAD_ARG); + CHECK(s3d_sampler_ref_put(sampler), RES_OK); + CHECK(s3d_sampler_ref_put(sampler), RES_OK); + + CHECK(s3d_device_ref_put(dev), RES_OK); + CHECK(s3d_scene_ref_put(scn), RES_OK); + CHECK(s3d_shape_ref_put(cbox), RES_OK); + CHECK(s3d_shape_ref_put(walls), RES_OK); + CHECK(s3d_shape_ref_put(short_block), RES_OK); + CHECK(s3d_shape_ref_put(tall_block), RES_OK); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +} + diff --git a/src/test_s3d_trace_ray.c b/src/test_s3d_trace_ray.c @@ -99,7 +99,6 @@ main(int argc, char** argv) float org[3] = { 0.f, 0.f, 0.f }; float dir[3] = { 0.f, 1.f, 0.f }; float range[2] = { 0.f, FLT_MAX }; - (void)argc, (void)argv; mem_init_proxy_allocator(&allocator, &mem_default_allocator);