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 d80f604129e3d8a1daa6f464edd63d9084428103
parent a066df19fd96fa4ded0f8096813380abfd665c09
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 10 Mar 2015 16:20:27 +0100

Implement and test the s3d_shape_setup_trimesh function

Diffstat:
Mcmake/CMakeLists.txt | 6++++--
Msrc/s3d.h | 8++++++--
Msrc/s3d_shape.c | 88++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/s3d_shape_c.h | 9+++++++++
Asrc/test_s3d_cbox.h | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_s3d_shape.c | 18++++++++++++++++++
6 files changed, 264 insertions(+), 5 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -60,7 +60,7 @@ set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(S3D_FILES_SRC s3d_device.c s3d_scene.c s3d_shape.c) -set(S3D_FILES_INC s3d.h) +set(S3D_FILES_INC s3d.h s3d_device_c.h s3d_shape_c.h) # Prepend each file in the `S3D_FILES_<SRC|INC>' list by `S3D_SOURCE_DIR' rcmake_prepend_path(S3D_FILES_SRC ${S3D_SOURCE_DIR}) @@ -81,7 +81,9 @@ rcmake_setup_devel(s3d s3d ${VERSION} se/s3d_version.h) ################################################################################ if(NOT NO_TEST) function(new_test _name) - add_executable(${_name} ${S3D_SOURCE_DIR}/${_name}.c) + add_executable(${_name} + ${S3D_SOURCE_DIR}/${_name}.c + ${S3D_SOURCE_DIR}/test_s3d_utils.h) target_link_libraries(${_name} s3d RSys) set(_libraries ${ARGN}) foreach(_lib ${_libraries}) diff --git a/src/s3d.h b/src/s3d.h @@ -80,13 +80,17 @@ struct s3d_trimesh_desc { (const unsigned itri, unsigned ids[3], void*); void (*get_position) /* Get the 3D position of the vertex `ivert' */ (const unsigned ivert, float position[3], void*); - void (*get_normal) /* Get the world space normal of the vertex `ivert' */ + void (*get_normal) /* Get the world space normal of `ivert'. May be NULL */ (const unsigned ivert, float normal[3], void*); - void (*get_uv) /* Get the parametric coordinates of the vertex `ivert' */ + void (*get_uv) /* Get the parametric coordinates of `ivert'. May be NULL */ (const unsigned ivert, float uv[2], void*); void* data;/* Pointer to user data; last argument of the previous callbacks */ }; +static const struct s3d_trimesh_desc S3D_TRIMESH_DESC_NULL = { + NULL, NULL, NULL, NULL, NULL, NULL +}; + /* Intersection point */ struct s3d_hit { struct s3d_shape* shape; /* Hit shape */ diff --git a/src/s3d_shape.c b/src/s3d_shape.c @@ -49,6 +49,10 @@ shape_release(ref_T* ref) dev = shape->dev; /* The shape should not be attached */ ASSERT(is_list_empty(&shape->scene_attachment)); + darray_u32_release(&shape->indices); + darray_float_release(&shape->positions); + darray_float_release(&shape->normals); + darray_float_release(&shape->uvs); MEM_FREE(dev->allocator, shape); S3D(device_ref_put(dev)); } @@ -74,9 +78,13 @@ s3d_shape_create(struct s3d_device* dev, struct s3d_shape** out_shape) } list_init(&shape->scene_attachment); shape->type = SHAPE_NONE; + darray_u32_init(dev->allocator, &shape->indices); + darray_float_init(dev->allocator, &shape->positions); + darray_float_init(dev->allocator, &shape->normals); + darray_float_init(dev->allocator, &shape->uvs); S3D(device_ref_get(dev)); - ref_init(&shape->ref); shape->dev = dev; + ref_init(&shape->ref); exit: if(out_shape) *out_shape = shape; @@ -116,3 +124,81 @@ s3d_shape_detach(struct s3d_shape* shape) return RES_OK; } +res_T +s3d_shape_setup_trimesh + (struct s3d_shape* shape, + const struct s3d_trimesh_desc* desc) +{ + uint32_t* indices; + float* positions = NULL; + float* normals = NULL; + float* uvs = NULL; + unsigned itri, ntris, nverts, nids; + size_t i; + res_T res = RES_OK; + if(!shape || !desc) { + res = RES_BAD_ARG; + goto error; + } + if(!desc->get_tricount || !desc->get_indices || !desc->get_position) { + res = RES_BAD_ARG; + goto error; + } + + ntris = desc->get_tricount(desc->data); + nids = ntris * 3; + res = darray_u32_resize(&shape->indices, nids); + if(res != RES_OK) goto error; + indices = darray_u32_data_get(&shape->indices); + + /* Get the mesh indices */ + nverts = 0; + FOR_EACH(itri, 0, ntris) { + uint32_t* ids = indices + itri*3; + STATIC_ASSERT(sizeof(unsigned) == sizeof(uint32_t), Unexpected_Type); + desc->get_indices(itri, ids, desc->data); + FOR_EACH(i, 0, 3) + if(ids[i] >= nverts) nverts = ids[i]; + } + ++nverts; /* Transform nverts from last vertex id to vertices count */ + + /* Allocate the vertex data */ + res = darray_float_resize(&shape->positions, nverts*3); + if(res != RES_OK) goto error; + positions = darray_float_data_get(&shape->positions); + if(desc->get_normal) { + res = darray_float_resize(&shape->normals, nverts*3); + if(res != RES_OK) goto error; + normals = darray_float_data_get(&shape->normals); + } + if(desc->get_uv) { + res = darray_float_resize(&shape->uvs, nverts*2); + if(res != RES_OK) goto error; + uvs = darray_float_data_get(&shape->uvs); + } + + /* Setup the vertex data */ + memset(positions, 0xFF, sizeof(float[3])*nverts); + FOR_EACH(i, 0, nids) { + union { float f; uint32_t i; } ucast; + const unsigned ivert = indices[i]; + const unsigned iposition = ivert * 3; + const unsigned inormal = iposition; + const unsigned iuv = indices[i] * 2; + + ucast.f = positions[iposition]; + if(ucast.i != 0xFFFFFFFF) /* The vertex was already setuped */ + continue; + + desc->get_position(ivert, positions + iposition, desc->data); + if(normals) desc->get_normal(ivert, normals + inormal, desc->data); + if(uvs) desc->get_uv(ivert, uvs + iuv, desc->data); + } + shape->type = SHAPE_TRIMESH; + +exit: + return res; +error: + goto exit; +} + diff --git a/src/s3d_shape_c.h b/src/s3d_shape_c.h @@ -33,6 +33,8 @@ #ifndef S3D_SHAPE_C_H #define S3D_SHAPE_C_H +#include <rsys/dynamic_array_u32.h> +#include <rsys/dynamic_array_float.h> #include <rsys/list.h> #include <rsys/ref_count.h> @@ -46,6 +48,13 @@ enum shape_type { struct s3d_shape { struct list_node scene_attachment; enum shape_type type; + unsigned igeom; /* Embree geometry id */ + + darray_u32 indices; + darray_float positions; /* list of 3 floats */ + darray_float normals; /* list of 3 floats */ + darray_float uvs; /* list of 2 floats */ + struct s3d_device* dev; ref_T ref; }; diff --git a/src/test_s3d_cbox.h b/src/test_s3d_cbox.h @@ -0,0 +1,140 @@ +/* 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. */ + +#ifndef TEST_S3D_CBOX_H +#define TEST_S3D_CBOX_H + +#include <rsys/rsys.h> +#include <stdint.h> + +static const float cbox_verts[] = { + /* Box */ + 552.f, 0.f, 0.f, + 0.f, 0.f, 0.f, + 0.f, 559.f, 0.f, + 552.f, 559.f, 0.f, + 552.f, 0.f, 548.f, + 0.f, 0.f, 548.f, + 0.f, 559.f, 548.f, + 552.f, 559.f, 548.f, + /* Short block */ + 130.f, 65.f, 0.f, + 82.f, 225.f, 0.f, + 240.f, 272.f, 0.f, + 290.f, 114.f, 0.f, + 130.f, 65.f, 165.f, + 82.f, 225.f, 165.f, + 240.f, 272.f, 165.f, + 290.f, 114.f, 165.f, + /* Tall block */ + 423.0f, 247.0f, 0.f, + 265.0f, 296.0f, 0.f, + 314.0f, 456.0f, 0.f, + 472.0f, 406.0f, 0.f, + 423.0f, 247.0f, 330.f, + 265.0f, 296.0f, 330.f, + 314.0f, 456.0f, 330.f, + 472.0f, 406.0f, 330.f +}; +const size_t cbox_nverts = sizeof(cbox_verts) / (sizeof(float[3])); + +const uint32_t cbox_ids[] = { + /* Box */ + 0, 1, 2, 2, 3, 0, + 4, 5, 6, 6, 7, 4, + 1, 2, 6, 6, 5, 1, + 0, 3, 7, 7, 4, 0, + 2, 3, 7, 7, 6, 2, + /* Short block */ + 12, 13, 14, 14, 15, 12, + 9, 10, 14, 14, 13, 9, + 8, 11, 15, 15, 12, 8, + 10, 11, 15, 15, 14, 10, + 8, 9, 13, 13, 12, 8, + /* Tall block */ + 20, 21, 22, 22, 23, 20, + 17, 18, 22, 22, 21, 17, + 16, 19, 23, 23, 20, 16, + 18, 19, 23, 23, 22, 18, + 16, 17, 21, 21, 20, 16 +}; +const size_t cbox_nids = sizeof(cbox_ids)/sizeof(uint32_t); + +static unsigned +cbox_get_ntris(void* data) +{ + (void)data; + CHECK(cbox_nids % 3, 0); + return (unsigned)(cbox_nids / 3); +} + +static void +cbox_get_ids(const unsigned itri, unsigned ids[3], void* data) +{ + const unsigned id = itri * 3; + (void)data; + CHECK(itri < cbox_get_ntris(data), 1); + CHECK(id + 2 < cbox_nids, 1); + ids[0] = cbox_ids[id + 0]; + ids[1] = cbox_ids[id + 1]; + ids[2] = cbox_ids[id + 2]; +} + +static void +cbox_get_position(const unsigned ivert, float position[3], void* data) +{ + (void)data; + CHECK(ivert < cbox_nverts, 1); + position[0] = cbox_verts[ivert*3 + 0]; + position[1] = cbox_verts[ivert*3 + 1]; + position[2] = cbox_verts[ivert*3 + 2]; +} + +static void +cbox_get_normal(const unsigned ivert, float normal[3], void* data) +{ + (void)ivert, (void)data; + normal[0] = 1.f; + normal[1] = 0.f; + normal[2] = 0.f; +} + +static void +cbox_get_uv(const unsigned ivert, float uv[2], void* data) +{ + (void)ivert, (void)data; + uv[0] = -1.f; + uv[1] = 1.f; +} + +#endif /* TEST_S3D_CBOX_H */ + diff --git a/src/test_s3d_shape.c b/src/test_s3d_shape.c @@ -31,6 +31,7 @@ * 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 @@ -39,6 +40,7 @@ main(int argc, char** argv) struct mem_allocator allocator; struct s3d_device* dev; struct s3d_shape* shape; + struct s3d_trimesh_desc trimesh = S3D_TRIMESH_DESC_NULL; (void)argc, (void)argv; mem_init_proxy_allocator(&allocator, &mem_default_allocator); @@ -53,6 +55,22 @@ main(int argc, char** argv) CHECK(s3d_shape_detach(NULL), RES_BAD_ARG); CHECK(s3d_shape_detach(shape), RES_OK); + CHECK(s3d_shape_setup_trimesh(NULL, NULL), RES_BAD_ARG); + CHECK(s3d_shape_setup_trimesh(shape, NULL), RES_BAD_ARG); + CHECK(s3d_shape_setup_trimesh(NULL, &trimesh), RES_BAD_ARG); + CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_BAD_ARG); + trimesh.get_tricount = cbox_get_ntris; + CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_BAD_ARG); + trimesh.get_indices = cbox_get_ids; + CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_BAD_ARG); + trimesh.get_position = cbox_get_position; + CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_OK); + CHECK(s3d_shape_setup_trimesh(NULL, &trimesh), RES_BAD_ARG); + trimesh.get_normal = cbox_get_normal; + CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_OK); + trimesh.get_uv = cbox_get_uv; + CHECK(s3d_shape_setup_trimesh(shape, &trimesh), RES_OK); + CHECK(s3d_shape_ref_get(NULL), RES_BAD_ARG); CHECK(s3d_shape_ref_get(shape), RES_OK); CHECK(s3d_shape_ref_put(NULL), RES_BAD_ARG);