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:
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);