star-3dut

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

commit 2e7b833fadf36269772afc2d4642d2f5301a8780
parent 505d4e4c0c19044aeae8638f794a3006cf961b58
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 28 Nov 2016 15:23:07 +0100

Add and test the s3dut_create_cylinder function

Diffstat:
Mcmake/CMakeLists.txt | 6+++++-
Msrc/s3dut.h | 15++++++++++++---
Asrc/s3dut_cylinder.c | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/s3dut_mesh.h | 1+
Msrc/s3dut_sphere.c | 50+++++++++++++++++++++++++-------------------------
Asrc/test_s3dut_cylinder.c | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 279 insertions(+), 29 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -41,7 +41,10 @@ set(VERSION_MINOR 0) set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) -set(S3DUT_FILES_SRC s3dut_mesh.c s3dut_sphere.c) +set(S3DUT_FILES_SRC + s3dut_cylinder.c + s3dut_mesh.c + s3dut_sphere.c) set(S3DUT_FILES_INC s3dut_mesh.h) set(S3DUT_FILES_INC_API s3dut.h) set(S3DUT_FILES_DOC COPYING README.md) @@ -74,6 +77,7 @@ if(NOT NO_TEST) add_test(${_name} ${_name}) endfunction() + new_test(test_s3dut_cylinder) new_test(test_s3dut_sphere) endif() diff --git a/src/s3dut.h b/src/s3dut.h @@ -68,10 +68,19 @@ s3dut_mesh_get_data 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 */ + const double radius, + const unsigned nslices, /* # subdivisions around Z axis */ + const unsigned nstacks, /* # subdivisions along Z axis */ struct s3dut_mesh** sphere); +S3DUT_API res_T +s3dut_create_cylinder + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const double radius, + const double height, + const unsigned nslices, /* # subdivisions around Z axis */ + const unsigned nstacks, /* # subdivision along Z axis */ + struct s3dut_mesh** cylinder); + #endif /* S3DUT_H */ diff --git a/src/s3dut_cylinder.c b/src/s3dut_cylinder.c @@ -0,0 +1,154 @@ +/* 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 "s3dut_mesh.h" + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +setup_cylinder_coords + (double* coords, + const double radius, + const double height, + const unsigned nslices, + const unsigned nstacks) +{ + double step_theta; + double step_z; + size_t itheta, istack; + size_t i = 0; + ASSERT(coords && radius > 0 && height > 0 && nslices >= 2 && nstacks >= 1); + + /* Contour vertices */ + step_theta = 2*PI / (double)nslices; + step_z = height / (double)nstacks; + FOR_EACH(itheta, 0, nslices) { + const double theta = (double)itheta * step_theta; + const double x = cos(theta); + const double y = sin(theta); + double z = -height * 0.5; + + FOR_EACH(istack, 0, nstacks+1) { + coords[i++] = x; + coords[i++] = y; + coords[i++] = z; + z += step_z; + } + } + + /* Bottom polar vertex */ + coords[i++] = 0; + coords[i++] = 0; + coords[i++] = -height * 0.5; + + /* Top polar vertex */ + coords[i++] = 0; + coords[i++] = 0; + coords[i++] = height * 0.5; +} + +static void +setup_cylinder_indices + (size_t* ids, + const unsigned nslices, + const unsigned nstacks) +{ + size_t islice; + size_t istack; + size_t ibottom; + size_t itop; + size_t i = 0; + ASSERT(ids && nslices && nstacks); + + FOR_EACH(islice, 0, nslices) { + const size_t islice0 = islice * (nstacks + 1); + const size_t islice1 = ((islice + 1) % nslices) * (nstacks + 1); + FOR_EACH(istack, 0, nstacks) { + const size_t istack0 = istack + 0; + const size_t istack1 = istack + 1; + + ids[i++] = islice0 + istack0; + ids[i++] = islice0 + istack1; + ids[i++] = islice1 + istack0; + + ids[i++] = islice1 + istack0; + ids[i++] = islice0 + istack1; + ids[i++] = islice1 + istack1; + } + } + + ibottom = nslices * (nstacks+1); + FOR_EACH(islice, 0, nslices) { + ids[i++] = ibottom; + ids[i++] = islice * (nstacks+1); + ids[i++] = ((islice+1)%nslices) * (nstacks+1); + } + + itop = ibottom + 1; + FOR_EACH(islice, 0, nslices) { + ids[i++] = itop; + ids[i++] = islice * (nstacks+1) + nstacks; + ids[i++] = ((islice+1)%nslices) * (nstacks+1) + nstacks; + } +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +s3dut_create_cylinder + (struct mem_allocator* allocator, + const double radius, + const double height, + const unsigned nslices, + const unsigned nstacks, + struct s3dut_mesh** mesh) +{ + struct s3dut_mesh* cylinder = NULL; + double* coords = NULL; + size_t* ids = NULL; + size_t nverts; + size_t ntris; + res_T res = RES_OK; + + if(radius <= 0 || height <= 0 || nslices < 2 || nstacks < 1 || !mesh) { + res = RES_BAD_ARG; + goto error; + } + + nverts = nslices * (nstacks+1) /*#contour vers*/ + 2/*#polar verts*/; + ntris = 2*nslices*nstacks /*#contour tris*/ + 2*nslices/* #cao tris*/; + + res = mesh_create(allocator, S3DUT_MESH_CYLINDER, nverts, ntris, &cylinder); + if(res != RES_OK) goto error; + + coords = darray_double_data_get(&cylinder->coords); + ids = darray_size_t_data_get(&cylinder->ids); + setup_cylinder_coords(coords, radius, height, nslices, nstacks); + setup_cylinder_indices(ids, nslices, nstacks); + +exit: + if(mesh) *mesh = cylinder; + return res; +error: + if(cylinder) { + S3DUT(mesh_ref_put(cylinder)); + cylinder = NULL; + } + goto exit; +} + diff --git a/src/s3dut_mesh.h b/src/s3dut_mesh.h @@ -21,6 +21,7 @@ #include <rsys/ref_count.h> enum s3dut_mesh_type { + S3DUT_MESH_CYLINDER, S3DUT_MESH_SPHERE }; diff --git a/src/s3dut_sphere.c b/src/s3dut_sphere.c @@ -24,8 +24,8 @@ setup_sphere_coords (struct mem_allocator* allocator, double* coords, const double radius, - const unsigned nthetas, /* # subdivisions around the Z axis */ - const unsigned nphis) /* # subdivisions along the Z axis */ + const unsigned nslices, /* # subdivisions around the Z axis */ + const unsigned nstacks) /* # 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 && nthetas >= 2 && nphis >= 2); + ASSERT(coords && radius > 0 && nslices >= 2 && nstacks >= 2); darray_double_init(allocator, &sincos_theta); darray_double_init(allocator, &sincos_phi); - res = darray_double_resize(&sincos_theta, nthetas*2/*sin & cos*/); + res = darray_double_resize(&sincos_theta, nslices*2/*sin & cos*/); if(res != RES_OK) goto error; - res = darray_double_resize(&sincos_phi, (nphis-1)*2/*sin & cos*/); + res = darray_double_resize(&sincos_phi, (nstacks-1)*2/*sin & cos*/); if(res != RES_OK) goto error; /* Precompute the sinus/cosine of the theta/phi angles */ - step_theta = 2*PI / (double)nthetas; - FOR_EACH(itheta, 0, nthetas) { + step_theta = 2*PI / (double)nslices; + FOR_EACH(itheta, 0, nslices) { 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)nphis; - FOR_EACH(iphi, 0, nphis-1) { + step_phi = PI/(double)nstacks; + FOR_EACH(iphi, 0, nstacks-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, nthetas) { + FOR_EACH(itheta, 0, nslices) { const double* theta = darray_double_cdata_get(&sincos_theta) + itheta*2; - FOR_EACH(iphi, 0, nphis-1) { + FOR_EACH(iphi, 0, nstacks-1) { const double* phi = darray_double_cdata_get(&sincos_phi) + iphi*2; coords[i++] = radius * COS[theta] * COS[phi]; coords[i++] = radius * SIN[theta] * COS[phi]; @@ -93,18 +93,18 @@ error: static void setup_sphere_indices (size_t* ids, - const unsigned nthetas, /* # subdivisions around the Z axis */ - const unsigned nphis) /* # subdivisions along the Z axis */ + const unsigned nslices, /* # subdivisions around the Z axis */ + const unsigned nstacks) /* # subdivisions along the Z axis */ { size_t i, itheta, iphi; - ASSERT(ids && nthetas && nphis); + ASSERT(ids && nslices && nstacks); /* Define the indices of the contour primitives */ i = 0; - 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) { + 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) { 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, nthetas) { - const size_t itheta0 = itheta * (nphis - 1); - const size_t itheta1 = ((itheta + 1) % nthetas) * (nphis - 1); + FOR_EACH(itheta, 0, nslices) { + const size_t itheta0 = itheta * (nstacks - 1); + const size_t itheta1 = ((itheta + 1) % nslices) * (nstacks - 1); - ids[i++] = nthetas * (nphis - 1); + ids[i++] = nslices * (nstacks - 1); ids[i++] = itheta0; ids[i++] = itheta1; - ids[i++] = nthetas * (nphis - 1) + 1; - ids[i++] = itheta1 + (nphis - 2); - ids[i++] = itheta0 + (nphis - 2); + ids[i++] = nslices * (nstacks - 1) + 1; + ids[i++] = itheta1 + (nstacks - 2); + ids[i++] = itheta0 + (nstacks - 2); } } diff --git a/src/test_s3dut_cylinder.c b/src/test_s3dut_cylinder.c @@ -0,0 +1,82 @@ +/* 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_cylinder(NULL, 0, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 1, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 1, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 0, 2, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 0, 2, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 1, 2, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 1, 2, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 0, 0, 1, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 0, 0, 1, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 1, 0, 1, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 1, 0, 1, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 0, 2, 1, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 0, 2, 1, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 1, 2, 1, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 1, 2, 1, NULL), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 1, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 1, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 0, 2, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 0, 2, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 1, 2, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 1, 2, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 0, 0, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 0, 0, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 1, 0, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 1, 0, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 0, 2, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 0, 2, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 0, 1, 2, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(NULL, 1, 1, 2, 1, &msh), RES_OK); + + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(s3dut_create_cylinder(&allocator, 1, 1, 2, 1, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(s3dut_create_cylinder(&allocator,-1, 1, 2, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(&allocator, 1,-1, 2, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(&allocator,-1, 1, 2, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(&allocator, 1,-1, 1, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(&allocator, 1, 2, 16, 4, &msh), RES_OK); + + CHECK(s3dut_mesh_get_data(msh, &data), RES_OK); + 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; +} +