star-3dut

Generate meshes of simple geometric shapes
git clone git://git.meso-star.fr/star-3dut.git
Log | Files | Refs | README | LICENSE

commit c24315e59e5f23e7595a83fcd60a476cf32d0448
parent 68b4d54fc6522c13cab48c6d8a91dd1c1e5f4e17
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 25 Nov 2016 12:17:20 +0100

Test the s3dut_<sphere|mesh> API

Diffstat:
Mcmake/CMakeLists.txt | 3++-
Msrc/s3dut.h | 32++++++++++++++++++++++++--------
Msrc/s3dut_mesh.c | 20++++++++++++++++++++
Msrc/s3dut_sphere.c | 54+++++++++++++++++++++++++++---------------------------
Asrc/test_s3dut_sphere.c | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_s3dut_utils.h | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 204 insertions(+), 36 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -73,7 +73,8 @@ if(NOT NO_TEST) target_link_libraries(${_name} s3dut RSys) add_test(${_name} ${_name}) endfunction() - # TODO add tests here + + new_test(test_s3dut_sphere) endif() ################################################################################ diff --git a/src/s3dut.h b/src/s3dut.h @@ -38,18 +38,17 @@ struct mem_allocator; struct s3dut_mesh; +struct s3dut_mesh_data { + const double* positions; + const size_t* indices; + size_t nvertices; /* # vertices */ + size_t nprimitives; /* # primitives */ +}; + /******************************************************************************* * Stard-3DUT API ******************************************************************************/ S3DUT_API res_T -s3dut_create_sphere - (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ - const double radius, - const unsigned nslices, /* # subdivisions around the Z axis */ - const unsigned nstacks, /* # subdivisions along the Z axis */ - struct s3dut_mesh** sphere); - -S3DUT_API res_T s3dut_mesh_ref_get (struct s3dut_mesh* mesh); @@ -57,5 +56,22 @@ S3DUT_API res_T s3dut_mesh_ref_put (struct s3dut_mesh* mesh); +S3DUT_API res_T +s3dut_mesh_get_data + (struct s3dut_mesh* mesh, + struct s3dut_mesh_data* data); + +/* Create a triangulared UV sphere discretized in `nslices' around the Z axis + * and `nstacks' along the Z axis. Face vertices are CCW ordered with respect + * to the sphere center, i.e. they are CW ordered from the outside point of + * view. */ +S3DUT_API res_T +s3dut_create_sphere + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const double radius, /* Sphere radius */ + const unsigned nslices, /* # subdivisions around the Z axis */ + const unsigned nstacks, /* # subdivisions along the Z axis */ + struct s3dut_mesh** sphere); + #endif /* S3DUT_H */ diff --git a/src/s3dut_mesh.c b/src/s3dut_mesh.c @@ -51,6 +51,26 @@ s3dut_mesh_ref_put(struct s3dut_mesh* mesh) return RES_OK; } +res_T +s3dut_mesh_get_data(struct s3dut_mesh* mesh, struct s3dut_mesh_data* data) +{ + size_t ncoords, nids; + if(!mesh || !data) return RES_BAD_ARG; + + data->positions = darray_double_cdata_get(&mesh->coords); + data->indices = darray_size_t_cdata_get(&mesh->ids); + + ncoords = darray_double_size_get(&mesh->coords); + nids = darray_size_t_size_get(&mesh->ids); + ASSERT(ncoords % 3 == 0); /* Only 3D coordinates are supported */ + ASSERT(nids % 3 == 0); /* Only triangular primitives are supported */ + + data->nvertices = ncoords / 3; + data->nprimitives = nids / 3; + + return RES_OK; +} + /******************************************************************************* * Local function ******************************************************************************/ diff --git a/src/s3dut_sphere.c b/src/s3dut_sphere.c @@ -24,8 +24,8 @@ setup_sphere_coords (struct mem_allocator* allocator, struct darray_double* coords, const double radius, - const unsigned nslices, /* # subdivisions around the Z axis */ - const unsigned nstacks) /* # subdivisions along the Z axis */ + const unsigned nthetas, /* # subdivisions around the Z axis */ + const unsigned nphis) /* # subdivisions along the Z axis */ { enum { SIN, COS }; struct darray_double sincos_theta; @@ -36,25 +36,25 @@ setup_sphere_coords size_t iphi; size_t i; res_T res = RES_OK; - ASSERT(coords && radius > 0 && nslices >= 2 && nstacks >= 2); + ASSERT(coords && radius > 0 && nthetas >= 2 && nphis >= 2); darray_double_init(allocator, &sincos_theta); darray_double_init(allocator, &sincos_phi); - res = darray_double_resize(&sincos_theta, nslices*2/*sin & cos*/); + res = darray_double_resize(&sincos_theta, nthetas*2/*sin & cos*/); if(res != RES_OK) goto error; - res = darray_double_resize(&sincos_phi, nstacks*2/*sin & cos*/); + res = darray_double_resize(&sincos_phi, (nphis-1)*2/*sin & cos*/); if(res != RES_OK) goto error; /* Precompute the sinus/cosine of the theta/phi angles */ - step_theta = 2*PI / (double)nslices; - FOR_EACH(itheta, 0, nslices) { + step_theta = 2*PI / (double)nthetas; + FOR_EACH(itheta, 0, nthetas) { const double theta = -PI + (double)itheta * step_theta; darray_double_data_get(&sincos_theta)[itheta*2 + SIN] = sin(theta); darray_double_data_get(&sincos_theta)[itheta*2 + COS] = cos(theta); } - step_phi = PI/(double)nstacks; - FOR_EACH(iphi, 0, nstacks) { + step_phi = PI/(double)nphis; + FOR_EACH(iphi, 0, nphis-1) { const double phi = -PI/2 + (double)(iphi+1) * step_phi; darray_double_data_get(&sincos_phi)[iphi*2 + SIN] = sin(phi); darray_double_data_get(&sincos_phi)[iphi*2 + COS] = cos(phi); @@ -62,9 +62,9 @@ setup_sphere_coords /* Setup the contour vertices */ i = 0; - FOR_EACH(itheta, 0, nslices) { + FOR_EACH(itheta, 0, nthetas) { const double* theta = darray_double_cdata_get(&sincos_theta) + itheta*2; - FOR_EACH(iphi, 0, nstacks-1) { + FOR_EACH(iphi, 0, nphis-1) { const double* phi = darray_double_cdata_get(&sincos_phi) + iphi*2; darray_double_data_get(coords)[i++] = radius * COS[theta] * COS[phi]; darray_double_data_get(coords)[i++] = radius * SIN[theta] * COS[phi]; @@ -93,18 +93,18 @@ error: static void setup_sphere_indices (struct darray_size_t* ids, - const unsigned nslices, /* # subdivisions around the Z axis */ - const unsigned nstacks) /* # subdivisions along the Z axis */ + const unsigned nthetas, /* # subdivisions around the Z axis */ + const unsigned nphis) /* # subdivisions along the Z axis */ { size_t i, itheta, iphi; - ASSERT(ids && nslices && nstacks); + ASSERT(ids && nthetas && nphis); /* Define the indices of the contour primitives */ i = 0; - FOR_EACH(itheta, 0, nslices) { - const size_t itheta0 = itheta * (nstacks - 1); - const size_t itheta1 = ((itheta + 1) % nslices) * (nstacks - 1); - FOR_EACH(iphi, 0, nstacks-2) { + FOR_EACH(itheta, 0, nthetas) { + const size_t itheta0 = itheta * (nphis - 1); + const size_t itheta1 = ((itheta + 1) % nthetas) * (nphis - 1); + FOR_EACH(iphi, 0, nphis-2) { const size_t iphi0 = iphi + 0; const size_t iphi1 = iphi + 1; @@ -119,17 +119,17 @@ setup_sphere_indices } /* Define the indices of the polar primitives */ - FOR_EACH(itheta, 0, nstacks) { - const size_t itheta0 = itheta * (nstacks - 1); - const size_t itheta1 = ((itheta + 1) % nslices) * (nstacks - 1); + FOR_EACH(itheta, 0, nthetas) { + const size_t itheta0 = itheta * (nphis - 1); + const size_t itheta1 = ((itheta + 1) % nthetas) * (nphis - 1); - darray_size_t_data_get(ids)[i++] = nslices * (nstacks - 1); + darray_size_t_data_get(ids)[i++] = nthetas * (nphis - 1); darray_size_t_data_get(ids)[i++] = itheta0; darray_size_t_data_get(ids)[i++] = itheta1; - darray_size_t_data_get(ids)[i++] = nslices * (nstacks - 1) + 1; - darray_size_t_data_get(ids)[i++] = itheta1 + (nstacks - 2); - darray_size_t_data_get(ids)[i++] = itheta0 + (nstacks - 2); + darray_size_t_data_get(ids)[i++] = nthetas * (nphis - 1) + 1; + darray_size_t_data_get(ids)[i++] = itheta1 + (nphis - 2); + darray_size_t_data_get(ids)[i++] = itheta0 + (nphis - 2); } } @@ -149,7 +149,7 @@ s3dut_create_sphere size_t ntris; res_T res = RES_OK; - if(radius <= 0 || nslices < 2 || nstacks < 2 || !mesh) { + if(radius <= 0 || nslices < 2 || nstacks < 2 || !mesh) { res = RES_BAD_ARG; goto error; } @@ -168,7 +168,7 @@ s3dut_create_sphere res = setup_sphere_coords (allocator, &sphere->coords, radius, nslices, nstacks); if(res != RES_OK) goto error; - + setup_sphere_indices(&sphere->ids, nslices, nstacks); exit: diff --git a/src/test_s3dut_sphere.c b/src/test_s3dut_sphere.c @@ -0,0 +1,78 @@ +/* Copyright (C) |Meso|Star> 2016 (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "s3dut.h" +#include "test_s3dut_utils.h" + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct s3dut_mesh* msh; + struct s3dut_mesh_data data; + (void)argc, (void)argv; + + CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); + + CHECK(s3dut_create_sphere(NULL, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 1, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 0, 2, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 1, 2, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 0, 0, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 1, 0, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 0, 2, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 1, 2, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 1, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 0, 2, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 1, 2, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 0, 0, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 1, 0, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 0, 2, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_sphere(NULL, 1, 2, 2, &msh), RES_OK); + + CHECK(s3dut_mesh_ref_get(NULL), RES_BAD_ARG); + CHECK(s3dut_mesh_ref_get(msh), RES_OK); + CHECK(s3dut_mesh_ref_put(NULL), RES_BAD_ARG); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(s3dut_create_sphere(&allocator, 1, 2, 2, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(s3dut_create_sphere(&allocator, 1, 1, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_sphere(&allocator, 1, 2, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_sphere(&allocator,-1, 2, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_sphere(&allocator, 1, 32, 16, &msh), RES_OK); + + CHECK(s3dut_mesh_get_data(NULL, NULL), RES_BAD_ARG); + CHECK(s3dut_mesh_get_data(msh, NULL), RES_BAD_ARG); + CHECK(s3dut_mesh_get_data(NULL, &data), RES_BAD_ARG); + CHECK(s3dut_mesh_get_data(msh, &data), RES_OK); + NCHECK(data.positions, NULL); + NCHECK(data.indices, NULL); + CHECK(data.nvertices >= (32*(16-1)+2), 1); + CHECK(data.nprimitives, (32*(16-2)*2) + 2*32); + + dump_mesh_data(stdout, &data); + + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +} + diff --git a/src/test_s3dut_utils.h b/src/test_s3dut_utils.h @@ -0,0 +1,53 @@ +/* Copyright (C) |Meso|Star> 2016 (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef TEST_S3DUT_UTILS_H +#define TEST_S3DUT_UTILS_H + +#include "s3dut.h" + +#include <rsys/mem_allocator.h> +#include <stdio.h> + +static INLINE void +dump_mesh_data(FILE* stream, const struct s3dut_mesh_data* data) +{ + size_t i; + NCHECK(data, NULL); + + FOR_EACH(i, 0, data->nvertices) { + fprintf(stream, "v %g %g %g\n", SPLIT3(data->positions + i*3)); + } + FOR_EACH(i, 0, data->nprimitives) { + fprintf(stream, "f %lu %lu %lu\n", + data->indices[i*3+0] + 1, + data->indices[i*3+1] + 1, + data->indices[i*3+2] + 1); + } +} + +static INLINE void +check_memory_allocator(struct mem_allocator* allocator) +{ + if(MEM_ALLOCATED_SIZE(allocator)) { + char dump[512]; + MEM_DUMP(allocator, dump, sizeof(dump)/sizeof(char)); + fprintf(stderr, "%s\n", dump); + FATAL("Memory leaks\n"); + } +} + +#endif /* TEST_S3DUT_UTILS_H */ +