star-3dut

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

commit edca541949cd31ce411b0c5da65c38c7a7cb3c17
parent 8fe72bbfa9fa55c83177df4212c4e87f074494ca
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Tue, 21 Nov 2017 16:29:02 +0100

Merge branch 'release_0.3'

Diffstat:
MREADME.md | 25+++++++++++++++++++++++++
Mcmake/CMakeLists.txt | 14++++++++++----
Msrc/s3dut.h | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/s3dut_cylinder.c | 212++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Dsrc/s3dut_hemisphere.c | 172-------------------------------------------------------------------------------
Msrc/s3dut_mesh.h | 5++++-
Msrc/s3dut_sphere.c | 331+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Asrc/s3dut_super_shape.c | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_s3dut_cylinder.c | 4++--
Msrc/test_s3dut_hemisphere.c | 24++++++++++++------------
Asrc/test_s3dut_super_shape.c | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_s3dut_thick_cylinder.c | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_s3dut_thick_truncated_sphere.c | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_s3dut_thick_truncated_super_shape.c | 185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_s3dut_thin_cylinder.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_s3dut_truncated_sphere.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16 files changed, 1490 insertions(+), 281 deletions(-)

diff --git a/README.md b/README.md @@ -15,6 +15,31 @@ the install directories of its dependencies. ## Release notes +### Version 0.3 + +- Add the `s3dut_create_thin_cylinder` function that creates a triangulated + cylinder. Both ends can be closed or left open. + +- Add the `s3dut_create_thick_cylinder` function that creates a thick + triangulated cylinder. Both ends can be closed or left open. + +- Add the `s3dut_create_truncated_sphere` function that creates a triangulated + UV sphere (possibly) truncated along the Z axis. Truncated ends can be closed + or left open. + +- Add the `s3dut_create_thick_truncated_sphere` function that creates a thick + triangulated UV sphere (possibly) truncated along the Z axis. Truncated ends + can be closed or left open. + +- Add the `s3dut_create_super_shape` function that creates a triangulated super + shape. + +- Add the `s3dut_create_thick_truncated_super_shape` function that creates a + thick triangulated super shape (possibly) truncated along the Z axis. + Truncated ends can be closed or left open. + +- Increase min number of slices for `s3dut_create_hemisphere` from 2 to 3. + ### Version 0.2 - Add the `s3dut_create_hemisphere` function that creates a triangulated UV diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -37,16 +37,16 @@ include(rcmake_runtime) # Define targets ################################################################################ set(VERSION_MAJOR 0) -set(VERSION_MINOR 2) +set(VERSION_MINOR 3) set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(S3DUT_FILES_SRC s3dut_cuboid.c s3dut_cylinder.c - s3dut_hemisphere.c s3dut_mesh.c - s3dut_sphere.c) + s3dut_sphere.c + s3dut_super_shape.c) set(S3DUT_FILES_INC s3dut_mesh.h) set(S3DUT_FILES_INC_API s3dut.h) set(S3DUT_FILES_DOC COPYING README.md) @@ -60,7 +60,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) set(MATH_LIB m) endif() -add_library(s3dut SHARED +add_library(s3dut SHARED ${S3DUT_FILES_SRC} ${S3DUT_FILES_INC} ${S3DUT_FILES_INC_API}) set_target_properties(s3dut PROPERTIES DEFINE_SYMBOL S3DUT_SHARED_BUILD @@ -83,8 +83,14 @@ if(NOT NO_TEST) new_test(test_s3dut_cuboid) new_test(test_s3dut_cylinder) + new_test(test_s3dut_thin_cylinder) + new_test(test_s3dut_thick_cylinder) new_test(test_s3dut_hemisphere) new_test(test_s3dut_sphere) + new_test(test_s3dut_super_shape) + new_test(test_s3dut_thick_truncated_super_shape) + new_test(test_s3dut_thick_truncated_sphere) + new_test(test_s3dut_truncated_sphere) rcmake_copy_runtime_libraries(test_s3dut_cuboid) endif() diff --git a/src/s3dut.h b/src/s3dut.h @@ -45,6 +45,25 @@ struct s3dut_mesh_data { size_t nprimitives; /* # primitives */ }; +/* Defines the radius 'r' with respect the an angle 'a': + * r(a) = ( |cos(M*a/4)/A)|^N1 + |sin(M*a/4)/B|^N2 )^{-1/N0} */ +struct s3dut_super_formula { + double A; + double B; + double M; + double N0; + double N1; + double N2; +}; +#define S3DUT_SUPER_FORMULA_NULL__ {0, 0, 0, 0, 0, 0} +static const struct s3dut_super_formula S3DUT_SUPER_FORMULA_NULL = + S3DUT_SUPER_FORMULA_NULL__; + +enum s3dut_cap_flag { + S3DUT_CAP_NEG_Z = BIT(0), + S3DUT_CAP_POS_Z = BIT(1) +}; + /******************************************************************************* * Stard-3DUT API ******************************************************************************/ @@ -74,11 +93,10 @@ s3dut_create_sphere struct s3dut_mesh** sphere); /* Create a triangulated cylinder centered in 0 discretized in `nslices' around - * the Z axis and `nstacks' along the Z axis. The top and the bottom of the - * cylinder is closed with a triangle fan whose center is on the Z axis. Face - * vertices are CCW ordered with respect to the cylinder center, i.e. they are - * CW ordered from the outside - * point of view. */ + * the Z axis and `nstacks' along the Z axis. The top and the bottom ends of + * the cylinder are closed with triangle fans whose center is on the Z axis. + * Face vertices are CCW ordered with respect to the cylinder center, i.e. they + * are CW ordered from the outside point of view. */ S3DUT_API res_T s3dut_create_cylinder (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ @@ -88,6 +106,42 @@ s3dut_create_cylinder const unsigned nstacks, /* # subdivision along Z axis in [1, INF) */ struct s3dut_mesh** cylinder); +/* Create a triangulated cylinder centered in 0 discretized in `nslices' around + * the Z axis and `nstacks' along the Z axis. The top and the bottom ends of + * the cylinder can be closed or not with a triangle fan whose center is on the + * Z axis, according to the `cap_mask' argument. Face vertices are CCW ordered + * with respect to the cylinder center, i.e. they are CW ordered from the + * outside point of view. Similar to s3dut_create_cylinder with the ability to + * close ends or not. */ +S3DUT_API res_T +s3dut_create_thin_cylinder + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const double radius, /* In ]0, INF) */ + const double height, /* In ]0, INF) */ + const unsigned nslices, /* # subdivisions around Z axis in [3, INF) */ + const unsigned nstacks, /* # subdivision along Z axis in [1, INF) */ + const int cap_mask, /* Combination of s3dut_cap_flag */ + struct s3dut_mesh** cylinder); + +/* Create a triangulated thick cylinder centered in 0 discretized in `nslices' + * around the Z axis and `nstacks' along the Z axis, with walls of thickness + * `thickness'. The top and the bottom of the cylinder can be closed or not, + * according to the `cap_mask' argument. Closed ends are closed by a wall of + * thickness `thickness' made of 2 triangle fans centered on the Z axis. Face + * vertices are CCW ordered with respect to the walls' inside, i.e. they are + * CW ordered from any point of view outside of the walls. */ +S3DUT_API res_T +s3dut_create_thick_cylinder + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const double radius, /* In ]thickness, INF); exterior radius */ + const double height, /* In ]min_height, INF); min_height = 0, + tickness or 2*thickness according to cap_mask */ + const double thickness, /* In ]0, INF) */ + const unsigned nslices, /* # subdivisions around Z axis in [3, INF) */ + const unsigned nstacks, /* # subdivision along Z axis in [1, INF) */ + const int cap_mask, /* Combination of s3dut_cap_flag */ + struct s3dut_mesh** cylinder); + /* Create a triangulated cuboid centered in 0. Face vertices are CCW ordered * with respect to the cylinder center, i.e. they are CW ordered from the * outside point of view. */ @@ -108,10 +162,89 @@ S3DUT_API res_T s3dut_create_hemisphere (struct mem_allocator* allocator, const double radius, - const unsigned nslices, /* # subdivisions around Z axis in [2, INF) */ + const unsigned nslices, /* # subdivisions around Z axis in [3, INF) */ const unsigned nstacks, /* # subdivisions along Z axis int [2, INF) */ struct s3dut_mesh** hemisphere); +/* Create a triangulated UV sphere centered in 0 discretized in `nslices' + * around the Z axis and `nstacks' along the Z axis. The top and the bottom of + * the sphere can be truncated at some specified z, according to the `z_range' + * parameter. If truncated, the top and the bottom of the sphere can be closed + * with a triangle fan whose center is on the Z axis or not, according to the + * `cap_mask' argument. 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_truncated_sphere + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const double radius, /* In ]0, INF) */ + const unsigned nslices, /* # subdivisions around Z axis in [3, INF) */ + const unsigned nstacks, /* # subdivisions along Z axis in [2, INF) */ + const double z_range[2], /* Clamp the sphere to z_range. NULL <=> no clamp */ + const int cap_mask, /* Combination of s3dut_cap_flag. Ignored if no clamp */ + struct s3dut_mesh** sphere); + +/* Create a triangulated thick UV sphere centered in 0 discretized in `nslices' + * around the Z axis and `nstacks' along the Z axis, with walls of thickness + * `thickness'. The top and the bottom of the sphere can be truncated at some + * specified z, according to the `z_range' parameter. If truncated, the top and + * the bottom of the sphere can be closed or not, according to the `cap_mask' + * argument. Closed ends are closed by a wall of thickness `thickness' + * made of 2 triangle fans centered on the Z axis. Face vertices are CCW + * ordered with respect to the walls' inside, i.e. they are CW ordered from any + * point of view outside of the walls. */ +S3DUT_API res_T +s3dut_create_thick_truncated_sphere + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const double radius, /* In ]thickness, INF); exterior radius */ + const double thickness, /* In ]0, INF) */ + const unsigned nslices, /* # subdivisions around Z axis in [3, INF) */ + const unsigned nstacks, /* # subdivisions along Z axis in [2, INF) */ + const double z_range[2], /* Clamp the sphere to z_range. NULL <=> no clamp */ + const int cap_mask, /* Combination of s3dut_cap_flag. Ignored if no clamp */ + struct s3dut_mesh** sphere); -#endif /* S3DUT_H */ +/* Create a triangulated super shape centered in 0 and discretized in `nslices' + * around the Z axis and `nstacks' along the Z axis. Face vertices are CCW + * ordered with respect to the center of the super shape. + * + * Assuming a point with the spherical coordinates {r, theta, phi} - with r the + * radius of the sphere, theta in [-PI,2PI] and phi in [-PI/2, PI/2] - the + * corresponding 3D coordinates onto the super shape is obtained by evaluating + * the following relations: + * x = r0(theta)*cos(theta) * r1(phi)*cos(phi) + * y = r0(theta)*sin(theta) * r1(phi)*cos(phi) + * z = r1(phi)*sin(phi) + * with r0 and r1 refering to the two super formulas. */ +S3DUT_API res_T +s3dut_create_super_shape + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const struct s3dut_super_formula* formula0, + const struct s3dut_super_formula* formula1, + const double radius, /* In [0, INF) */ + const unsigned nslices, /* # subdivisions around Z axis in [3, INF) */ + const unsigned nstacks, /* # subdivisions along Z axis in [2, INF) */ + struct s3dut_mesh** super_shape); + +/* Create a triangulated super shape centered in 0 and discretized in `nslices' + * around the Z axis and `nstacks' along the Z axis, with walls of thickness + * `thickness'. Refer to the comments of the s3dut_create_super_shape function + * for informations on super shape geometry. The top and the bottom of the + * super shape can be truncated at some specified z, according to the `z_range' + * parameter. If truncated, the top and the bottom of the super shape can be + * closed with a triangle fan whose center is on the Z axis or not, according + * to the `cap_mask' argument. Face vertices are CCW ordered with from the + * inside point of view. */ +S3DUT_API res_T +s3dut_create_thick_truncated_super_shape + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const struct s3dut_super_formula* formula0, + const struct s3dut_super_formula* formula1, + const double radius, /* In [0, INF) */ + const double thickness, /* In ]0, INF) */ + const unsigned nslices, /* # subdivisions around Z axis in [3, INF) */ + const unsigned nstacks, /* # subdivisions along Z axis in [2, INF) */ + const double z_range[2], /* Clamp the sphere to z_range. NULL <=> no clamp */ + const int cap_mask, /* Combination of s3dut_cap_flag. Ignored if no clamp */ + struct s3dut_mesh** super_shape); +#endif /* S3DUT_H */ diff --git a/src/s3dut_cylinder.c b/src/s3dut_cylinder.c @@ -19,16 +19,20 @@ /******************************************************************************* * Helper functions ******************************************************************************/ -static void +static double* setup_cylinder_coords (double* coords, const double radius, - const double height, + const double z_bottom, + const double z_top, const unsigned nslices, - const unsigned nstacks) + const unsigned nstacks, + const int close_bottom, + const int close_top) { double step_theta; double step_z; + const double height = z_top - z_bottom; size_t itheta, istack; size_t i = 0; ASSERT(coords && radius > 0 && height > 0 && nslices >= 3 && nstacks >= 1); @@ -40,32 +44,41 @@ setup_cylinder_coords const double theta = (double)itheta * step_theta; const double x = cos(theta); const double y = sin(theta); - double z = -height * 0.5; + double z = z_bottom; FOR_EACH(istack, 0, nstacks+1) { coords[i++] = x*radius; coords[i++] = y*radius; coords[i++] = z; - z += step_z; + z = (istack==nstacks) ? z_top : z+step_z; /* No rounding error! */ } } /* Bottom polar vertex */ - coords[i++] = 0; - coords[i++] = 0; - coords[i++] = -height * 0.5; + if(close_bottom) { + coords[i++] = 0; + coords[i++] = 0; + coords[i++] = z_bottom; + } /* Top polar vertex */ - coords[i++] = 0; - coords[i++] = 0; - coords[i++] = height * 0.5; + if(close_top) { + coords[i++] = 0; + coords[i++] = 0; + coords[i++] = z_top; + } + return coords + i; } -static void +static size_t* setup_cylinder_indices (size_t* ids, + const size_t offset, const unsigned nslices, - const unsigned nstacks) + const unsigned nstacks, + const int close_bottom, + const int close_top, + const int cw_out) { size_t islice; size_t istack; @@ -75,35 +88,71 @@ setup_cylinder_indices 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); + const size_t islice0 = offset + islice * (nstacks+1); + const size_t islice1 = offset + ((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] = islice0 + istack0; + ids[cw_out?i+1:i+2] = islice0 + istack1; + ids[cw_out?i+2:i+1] = islice1 + istack0; + i += 3; - ids[i++] = islice1 + istack0; - ids[i++] = islice0 + istack1; - ids[i++] = islice1 + istack1; + ids[i] = islice1 + istack0; + ids[cw_out?i+1:i+2] = islice0 + istack1; + ids[cw_out?i+2:i+1] = islice1 + istack1; + i += 3; } } - ibottom = nslices * (nstacks+1); - FOR_EACH(islice, 0, nslices) { - ids[i++] = ibottom; - ids[i++] = islice * (nstacks+1); - ids[i++] = ((islice+1)%nslices) * (nstacks+1); + if(close_bottom) { + ibottom = nslices * (nstacks+1); + FOR_EACH(islice, 0, nslices) { + ids[i] = offset + ibottom; + ids[cw_out?i+1:i+2] = offset + islice * (nstacks+1); + ids[cw_out?i+2:i+1] = offset + ((islice+1)%nslices) * (nstacks+1); + i += 3; + } + } + + if(close_top) { + itop = (close_bottom) ? nslices * (nstacks+1) + 1 : nslices * (nstacks+1); + FOR_EACH(islice, 0, nslices) { + ids[i] = offset + itop; + ids[cw_out?i+1:i+2] = offset + ((islice+1)%nslices) * (nstacks+1) + nstacks; + ids[cw_out?i+2:i+1] = offset + islice * (nstacks+1) + nstacks; + i += 3; + } } + return ids + i; +} + +static size_t* +close_wall + (size_t* ids, + const size_t fst_id_out, + const size_t fst_id_in, + const unsigned nslices, + const unsigned nstacks, + const int bottom) +{ + size_t islice; + size_t i = 0; + ASSERT(ids && nslices >= 3 && nstacks >= 1); - itop = ibottom + 1; FOR_EACH(islice, 0, nslices) { - ids[i++] = itop; - ids[i++] = ((islice+1)%nslices) * (nstacks+1) + nstacks; - ids[i++] = islice * (nstacks+1) + nstacks; + ids[i] = fst_id_out + islice * (nstacks+1); + ids[bottom?i+1:i+2] = fst_id_in + ((islice+1) % nslices) * (nstacks+1); + ids[bottom?i+2:i+1] = fst_id_in + islice * (nstacks+1); + i += 3; + + ids[i] = fst_id_out + islice * (nstacks+1); + ids[bottom?i+1:i+2] = fst_id_out + ((islice+1) % nslices) * (nstacks+1); + ids[bottom?i+2:i+1] = fst_id_in + ((islice+1) % nslices) * (nstacks+1); + i += 3; } + return ids + i; } /******************************************************************************* @@ -118,11 +167,28 @@ s3dut_create_cylinder const unsigned nstacks, struct s3dut_mesh** mesh) { + return s3dut_create_thin_cylinder(allocator, radius, height, nslices, + nstacks, S3DUT_CAP_POS_Z|S3DUT_CAP_NEG_Z, mesh); +} + +res_T +s3dut_create_thin_cylinder + (struct mem_allocator* allocator, + const double radius, + const double height, + const unsigned nslices, + const unsigned nstacks, + const int close_ends, + struct s3dut_mesh** mesh) +{ struct s3dut_mesh* cylinder = NULL; double* coords = NULL; size_t* ids = NULL; size_t nverts; size_t ntris; + const int close_bottom = close_ends & S3DUT_CAP_NEG_Z; + const int close_top = close_ends & S3DUT_CAP_POS_Z; + const unsigned nb_closed_ends = (close_bottom ? 1u : 0) + (close_top ? 1u : 0); res_T res = RES_OK; if(radius <= 0 || height <= 0 || nslices < 3 || nstacks < 1 || !mesh) { @@ -130,16 +196,17 @@ s3dut_create_cylinder goto error; } - nverts = nslices * (nstacks+1) /*#contour vers*/ + 2/*#polar verts*/; - ntris = 2*nslices*nstacks /*#contour tris*/ + 2*nslices/* #cao tris*/; + nverts = nslices * (nstacks+1)/*#contour*/ + nb_closed_ends/*#polar*/; + ntris = 2*nslices*nstacks/*#contour*/ + nb_closed_ends * nslices/*#polar*/; 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); + setup_cylinder_coords(coords, radius, -0.5*height, +0.5*height, + nslices, nstacks, close_bottom, close_top); + setup_cylinder_indices(ids, 0, nslices, nstacks, close_bottom, close_top, 1); exit: if(mesh) *mesh = cylinder; @@ -152,3 +219,80 @@ error: goto exit; } +res_T +s3dut_create_thick_cylinder + (struct mem_allocator* allocator, + const double radius, + const double height, + const double thickness, + const unsigned nslices, + const unsigned nstacks, + const int close_ends, + struct s3dut_mesh** mesh) +{ + struct s3dut_mesh* cylinder = NULL; + double* coords_out = NULL; + double* coords_in = NULL; + size_t* ids_out = NULL; + size_t* ids_in = NULL; + size_t* ids_walls = NULL; + size_t nverts; + size_t ntris; + size_t id_offset; + const int close_bottom = close_ends & S3DUT_CAP_NEG_Z; + const int close_top = close_ends & S3DUT_CAP_POS_Z; + const unsigned nb_closed_ends = (close_bottom ? 1u : 0) + (close_top ? 1u : 0); + res_T res = RES_OK; + + if(radius <= thickness || height <= 0 || thickness <= 0 + || height <= (double)nb_closed_ends * thickness + || nslices < 3 || nstacks < 1 || !mesh) { + res = RES_BAD_ARG; + goto error; + } + + nverts = 2 * (nslices*(nstacks+1)/*#contour*/ + nb_closed_ends/*#polar*/); + ntris = 2 * + ( 2 * nslices*nstacks /*#contour*/ + + 2 * nslices/*#trg fans tris, regardless of closedness*/); + + res = mesh_create + (allocator, S3DUT_MESH_THICK_CYLINDER, nverts, ntris, &cylinder); + if(res != RES_OK) goto error; + + coords_out = darray_double_data_get(&cylinder->coords); + ids_out = darray_size_t_data_get(&cylinder->ids); + /* External cylinder */ + coords_in = setup_cylinder_coords(coords_out, radius, -0.5*height, + +0.5*height, nslices, nstacks, close_bottom, close_top); + ids_in = setup_cylinder_indices + (ids_out, 0, nslices, nstacks, close_bottom, close_top, 1); + /* Internal cylinder */ + id_offset = (size_t)(coords_in - coords_out); + ASSERT(id_offset % 3 == 0); + id_offset /= 3; + setup_cylinder_coords(coords_in, + radius - thickness, + close_bottom ? -0.5*height + thickness : -0.5*height, + close_top ? +0.5*height -thickness : +0.5*height, + nslices, nstacks, close_bottom, close_top); + ids_walls = setup_cylinder_indices + (ids_in, id_offset, nslices, nstacks, close_bottom, close_top, 0); + /* Close walls where the cylinder is open */ + if(!close_bottom) { + ids_walls = close_wall(ids_walls, 0, id_offset, nslices, nstacks, 1); + } + if(!close_top) { + close_wall(ids_walls, nstacks, id_offset + nstacks, nslices, nstacks, 0); + } + +exit: + if(mesh) *mesh = cylinder; + return res; +error: + if(cylinder) { + S3DUT(mesh_ref_put(cylinder)); + cylinder = NULL; + } + goto exit; +} diff --git a/src/s3dut_hemisphere.c b/src/s3dut_hemisphere.c @@ -1,172 +0,0 @@ -/* Copyright (C) |Meso|Star> 2016-2017 (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 res_T -setup_hemisphere_coords - (struct mem_allocator* allocator, - double* coords, - const double radius, - const unsigned nslices, /* # subdivisions around the Z axis */ - const unsigned nstacks) /* # subdivisions along the Z axis */ -{ - enum { SIN, COS }; - struct darray_double sincos_theta; - struct darray_double sincos_phi; - double step_theta; - double step_phi; - size_t itheta; - size_t iphi; - size_t i; - res_T res = RES_OK; - 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, nslices*2/*sin & cos*/); - if(res != RES_OK) goto error; - 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)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)nstacks * 2.0); - FOR_EACH(iphi, 0, nstacks-1) { - const double phi = (double)(iphi) * step_phi; - darray_double_data_get(&sincos_phi)[iphi*2 + SIN] = sin(phi); - darray_double_data_get(&sincos_phi)[iphi*2 + COS] = cos(phi); - } - - /* Setup the contour vertices */ - i = 0; - FOR_EACH(itheta, 0, nslices) { - const double* theta = darray_double_cdata_get(&sincos_theta) + itheta*2; - 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]; - coords[i++] = radius * SIN[phi]; - } - } - - /* Setup the top polar vertex */ - coords[i++] = 0; - coords[i++] = 0; - coords[i++] = radius; - -exit: - darray_double_release(&sincos_theta); - darray_double_release(&sincos_phi); - return res; -error: - goto exit; -} - -static void -setup_hemisphere_indices - (size_t* ids, - const unsigned nslices, /* # subdivisions around the Z axis */ - const unsigned nstacks) /* # subdivisions along the Z axis */ -{ - size_t i, itheta, iphi; - ASSERT(ids && nslices && nstacks); - - /* 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) { - const size_t iphi0 = iphi + 0; - const size_t iphi1 = iphi + 1; - - ids[i++] = itheta0 + iphi0; - ids[i++] = itheta0 + iphi1; - ids[i++] = itheta1 + iphi0; - - ids[i++] = itheta1 + iphi0; - ids[i++] = itheta0 + iphi1; - ids[i++] = itheta1 + iphi1; - } - } - - /* Define the indices of the polar primitives */ - FOR_EACH(itheta, 0, nslices) { - const size_t itheta0 = itheta * (nstacks - 1); - const size_t itheta1 = ((itheta + 1) % nslices) * (nstacks - 1); - - ids[i++] = nslices * (nstacks - 1); - ids[i++] = itheta1 + (nstacks - 2); - ids[i++] = itheta0 + (nstacks - 2); - } -} - - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -s3dut_create_hemisphere - (struct mem_allocator* allocator, - const double radius, - const unsigned nslices, /* # subdivisions around the Z axis */ - const unsigned nstacks, /* # subdivisions along the Z axis */ - struct s3dut_mesh** mesh) -{ - struct s3dut_mesh* hemisphere = NULL; - size_t nverts; - size_t ntris; - res_T res = RES_OK; - - if(radius <= 0 || nslices < 2 || nstacks < 2 || !mesh) { - res = RES_BAD_ARG; - goto error; - } - - nverts = nslices*(nstacks-1)/* #contour verts*/ + 1/*polar vertex*/; - ntris = 2*nslices*(nstacks-2)/* #contour tris*/ + nslices/* #polar tris*/; - - res = mesh_create(allocator, S3DUT_MESH_HEMISPHERE, nverts, ntris, &hemisphere); - if(res != RES_OK) goto error; - - res = setup_hemisphere_coords(allocator, - darray_double_data_get(&hemisphere->coords), radius, nslices, nstacks); - if(res != RES_OK) goto error; - - setup_hemisphere_indices - (darray_size_t_data_get(&hemisphere->ids), nslices, nstacks); - -exit: - if(mesh) *mesh = hemisphere; - return res; -error: - if(hemisphere) { - S3DUT(mesh_ref_put(hemisphere)); - hemisphere = NULL; - } - goto exit; -} - diff --git a/src/s3dut_mesh.h b/src/s3dut_mesh.h @@ -23,8 +23,11 @@ enum s3dut_mesh_type { S3DUT_MESH_CUBOID, S3DUT_MESH_CYLINDER, + S3DUT_MESH_THICK_CYLINDER, S3DUT_MESH_HEMISPHERE, - S3DUT_MESH_SPHERE + S3DUT_MESH_SPHERE, + S3DUT_MESH_THICK_SPHERE, + S3DUT_MESH_SUPER_SHAPE }; struct s3dut_mesh { diff --git a/src/s3dut_sphere.c b/src/s3dut_sphere.c @@ -22,28 +22,43 @@ static res_T setup_sphere_coords (struct mem_allocator* allocator, - double* coords, + double** coords_ptr, const double radius, + const double z_range[2], const unsigned nslices, /* # subdivisions around the Z axis */ - const unsigned nstacks) /* # subdivisions along the Z axis */ + const unsigned nstacks, /* # subdivisions along the Z axis */ + const int close_ends) { enum { SIN, COS }; + double* coords; struct darray_double sincos_theta; struct darray_double sincos_phi; double step_theta; - double step_phi; + const int top_truncated = z_range && z_range[1] < +radius; + const int bottom_truncated = z_range && z_range[0] > -radius; + const unsigned nb_truncated = (unsigned)(top_truncated + bottom_truncated); + const int close_top = top_truncated && (close_ends & S3DUT_CAP_POS_Z); + const int close_bottom = bottom_truncated && (close_ends & S3DUT_CAP_NEG_Z); + const unsigned nrings = nstacks - 1 + nb_truncated; + const double phi_z_min + = bottom_truncated ? asin(CLAMP(z_range[0] / radius, -1, 1)) : -PI / 2; + const double phi_z_max + = top_truncated ? asin(CLAMP(z_range[1] / radius, -1, 1)) : +PI / 2; + double step_phi + = (phi_z_max - phi_z_min) / (double)(nrings + 1 - nb_truncated); size_t itheta; size_t iphi; - size_t i; + size_t i = 0; res_T res = RES_OK; - ASSERT(coords && radius > 0 && nslices >= 3 && nstacks >= 2); + ASSERT(coords_ptr && *coords_ptr && radius > 0); + coords = *coords_ptr; darray_double_init(allocator, &sincos_theta); darray_double_init(allocator, &sincos_phi); res = darray_double_resize(&sincos_theta, nslices*2/*sin & cos*/); if(res != RES_OK) goto error; - res = darray_double_resize(&sincos_phi, (nstacks-1)*2/*sin & cos*/); + res = darray_double_resize(&sincos_phi, nrings*2/*sin & cos*/); if(res != RES_OK) goto error; /* Precompute the sinus/cosine of the theta/phi angles */ @@ -53,9 +68,9 @@ setup_sphere_coords 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-1) { - const double phi = -PI/2 + (double)(iphi+1) * step_phi; + FOR_EACH(iphi, 0, nrings) { + const double phi + = phi_z_min + (double)(iphi + !bottom_truncated) * step_phi; darray_double_data_get(&sincos_phi)[iphi*2 + SIN] = sin(phi); darray_double_data_get(&sincos_phi)[iphi*2 + COS] = cos(phi); } @@ -64,7 +79,7 @@ setup_sphere_coords i = 0; FOR_EACH(itheta, 0, nslices) { const double* theta = darray_double_cdata_get(&sincos_theta) + itheta*2; - FOR_EACH(iphi, 0, nstacks-1) { + FOR_EACH(iphi, 0, nrings) { 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]; @@ -72,65 +87,148 @@ setup_sphere_coords } } - /* Setup the bottom polar vertex */ - coords[i++] = 0; - coords[i++] = 0; - coords[i++] = -radius; + if(close_bottom || !bottom_truncated) { + /* Setup the bottom polar vertex */ + coords[i++] = 0; + coords[i++] = 0; + coords[i++] = bottom_truncated ? z_range[0] : -radius; + } - /* Setup the top polar vertex */ - coords[i++] = 0; - coords[i++] = 0; - coords[i++] = radius; + if(close_top || !top_truncated) { + /* Setup the top polar vertex */ + coords[i++] = 0; + coords[i++] = 0; + coords[i++] = top_truncated ? z_range[1] : +radius; + } exit: darray_double_release(&sincos_theta); darray_double_release(&sincos_phi); + *coords_ptr = coords + i; return res; error: goto exit; } -static void +static size_t* setup_sphere_indices (size_t* ids, + const size_t offset, const unsigned nslices, /* # subdivisions around the Z axis */ - const unsigned nstacks) /* # subdivisions along the Z axis */ + const unsigned nstacks, /* # subdivisions along the Z axis */ + const double radius, + const double z_range[2], + const int close_ends, + const int cw_out) { + const int top_truncated = z_range && z_range[1] < +radius; + const int bottom_truncated = z_range && z_range[0] > -radius; + const int close_top = top_truncated && (close_ends & S3DUT_CAP_POS_Z); + const int close_bottom = bottom_truncated && (close_ends & S3DUT_CAP_NEG_Z); + const unsigned nb_truncated = (unsigned)(top_truncated + bottom_truncated); + const unsigned nrings = nstacks - 1 + nb_truncated; + size_t ibottom; + size_t itop; size_t i, itheta, iphi; ASSERT(ids && nslices && nstacks); - /* Define the indices of the contour primitives */ + /* 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) { + const size_t itheta0 = offset + itheta * nrings; + const size_t itheta1 = offset + ((itheta + 1) % nslices) * nrings; + FOR_EACH(iphi, 0, nrings-1) { const size_t iphi0 = iphi + 0; const size_t iphi1 = iphi + 1; - ids[i++] = itheta0 + iphi0; - ids[i++] = itheta0 + iphi1; - ids[i++] = itheta1 + iphi0; + ids[i] = itheta0 + iphi0; + ids[cw_out?i+1:i+2] = itheta0 + iphi1; + ids[cw_out?i+2:i+1] = itheta1 + iphi0; + i += 3; - ids[i++] = itheta1 + iphi0; - ids[i++] = itheta0 + iphi1; - ids[i++] = itheta1 + iphi1; + ids[i] = itheta1 + iphi0; + ids[cw_out?i+1:i+2] = itheta0 + iphi1; + ids[cw_out?i+2:i+1] = itheta1 + iphi1; + i += 3; } } /* Define the indices of the polar primitives */ FOR_EACH(itheta, 0, nslices) { - const size_t itheta0 = itheta * (nstacks - 1); - const size_t itheta1 = ((itheta + 1) % nslices) * (nstacks - 1); + const size_t itheta0 = offset + itheta * nrings; + const size_t itheta1 = offset + ((itheta + 1) % nslices) * nrings; + + if(close_bottom || !bottom_truncated) { + ibottom = nslices * nrings; + ids[i] = offset + ibottom; + ids[cw_out?i+1:i+2] = itheta0; + ids[cw_out?i+2:i+1] = itheta1; + i += 3; + } - ids[i++] = nslices * (nstacks - 1); - ids[i++] = itheta0; - ids[i++] = itheta1; + if(close_top || !top_truncated) { + itop = (close_bottom || !bottom_truncated) + ? nslices * nrings + 1 : nslices * nrings; + ids[i] = offset + itop; + ids[cw_out?i+1:i+2] = itheta1 + (nrings - 1); + ids[cw_out?i+2:i+1] = itheta0 + (nrings - 1); + i += 3; + } + } + return ids + i; +} + +static size_t* +close_wall + (size_t* ids, + const size_t fst_id_out, + const size_t fst_id_in, + const unsigned nslices, + const unsigned external_nrings, + const unsigned internal_nrings, + const int bottom) +{ + size_t islice; + size_t i = 0; + ASSERT(ids && nslices >= 3 && external_nrings >= 1 && internal_nrings >= 1); - ids[i++] = nslices * (nstacks - 1) + 1; - ids[i++] = itheta1 + (nstacks - 2); - ids[i++] = itheta0 + (nstacks - 2); + FOR_EACH(islice, 0, nslices) { + ids[i] = fst_id_out + islice * external_nrings; + ids[bottom?i+1:i+2] = fst_id_in + ((islice+1) % nslices) * internal_nrings; + ids[bottom?i+2:i+1] = fst_id_in + islice * internal_nrings; + i += 3; + + ids[i] = fst_id_out + islice * external_nrings; + ids[bottom?i+1:i+2] = fst_id_out + ((islice+1) % nslices) * external_nrings; + ids[bottom?i+2:i+1] = fst_id_in + ((islice+1) % nslices) * internal_nrings; + i += 3; } + return ids + i; +} + +static void +sphere_accum_counts + (const double radius, + const unsigned nslices, + const unsigned nstacks, + const double z_range[2], + const int close_ends, + unsigned* nrings, + size_t* ntris, + size_t* nverts) +{ + const int top_truncated = z_range && z_range[1] < +radius; + const int bottom_truncated = z_range && z_range[0] > -radius; + const int close_top = top_truncated && (close_ends & S3DUT_CAP_POS_Z); + const int close_bottom = bottom_truncated && (close_ends & S3DUT_CAP_NEG_Z); + const unsigned nb_truncated = (unsigned)(top_truncated + bottom_truncated); + const unsigned nb_closed_ends = (close_top ? 1u : 0) + (close_bottom ? 1u : 0); + const unsigned nb_pole_vrtx = nb_closed_ends + (2 - nb_truncated); + ASSERT(nrings && ntris && nverts); + *nrings = nstacks - 1 + nb_truncated;; + *nverts += nslices*(*nrings) /* #contour verts*/ + nb_pole_vrtx; /*polar verts*/ + *ntris += 2 * nslices * (*nrings -1) /* #contour tris */ + + (2 - nb_truncated + nb_closed_ends) * nslices; /* #polar tris */ } /******************************************************************************* @@ -140,31 +238,72 @@ res_T s3dut_create_sphere (struct mem_allocator* allocator, const double radius, - const unsigned nslices, /* # subdivisions around the Z axis */ - const unsigned nstacks, /* # subdivisions along the Z axis */ + const unsigned nslices, + const unsigned nstacks, + struct s3dut_mesh** mesh) +{ + return s3dut_create_truncated_sphere + (allocator, radius, nslices, nstacks, NULL, 0, mesh); +} + +res_T +s3dut_create_hemisphere + (struct mem_allocator* allocator, + const double radius, + const unsigned nslices, + const unsigned nstacks, + struct s3dut_mesh** mesh) +{ + double z_range[2]; + z_range[0] = 0; + z_range[1] = +radius; + return s3dut_create_truncated_sphere + (allocator, radius, nslices, nstacks, z_range, 0, mesh); +} + +res_T +s3dut_create_truncated_sphere + (struct mem_allocator* allocator, + const double radius, + const unsigned nslices, + const unsigned nstacks, + const double z_range[2], + const int close_ends, struct s3dut_mesh** mesh) { struct s3dut_mesh* sphere = NULL; - size_t nverts; - size_t ntris; + const int top_truncated = z_range && z_range[1] < +radius; + const int bottom_truncated = z_range && z_range[0] > -radius; + const int close_top = top_truncated && (close_ends & S3DUT_CAP_POS_Z); + const int close_bottom = bottom_truncated && (close_ends & S3DUT_CAP_NEG_Z); + const unsigned nb_truncated = (unsigned)(top_truncated + bottom_truncated); + const unsigned nb_closed_ends = (close_top ? 1u : 0) + (close_bottom ? 1u : 0); + const unsigned nb_pole_vrtx = nb_closed_ends + (2 - nb_truncated); + const unsigned nrings = nstacks - 1 + nb_truncated; + const size_t nverts = nslices*nrings/* #contour verts*/ + + nb_pole_vrtx/*polar verts*/; + const size_t ntris = 2 * nslices*(nrings - 1)/* #contour tris*/ + + nb_pole_vrtx*nslices/* #polar tris*/; + double* coords; res_T res = RES_OK; + ASSERT(nb_truncated <= 2); - if(radius <= 0 || nslices < 3 || nstacks < 2 || !mesh) { + if(radius <= 0 || nslices < 3 || nstacks < 2 || !mesh + || (z_range && z_range[0] >= z_range[1])) { res = RES_BAD_ARG; goto error; } - nverts = nslices*(nstacks-1)/* #contour verts*/ + 2/*polar verts*/; - ntris = 2*nslices*(nstacks-2)/* #contour tris*/ + 2*nslices/* #polar tris*/; - res = mesh_create(allocator, S3DUT_MESH_SPHERE, nverts, ntris, &sphere); if(res != RES_OK) goto error; - res = setup_sphere_coords(allocator, darray_double_data_get(&sphere->coords), - radius, nslices, nstacks); + coords = darray_double_data_get(&sphere->coords); + res = setup_sphere_coords(allocator, &coords, radius, z_range, nslices, + nstacks, close_ends); if(res != RES_OK) goto error; - setup_sphere_indices(darray_size_t_data_get(&sphere->ids), nslices, nstacks); + setup_sphere_indices(darray_size_t_data_get(&sphere->ids), 0, + nslices, nstacks, radius, z_range, close_ends, 1); exit: if(mesh) *mesh = sphere; @@ -177,3 +316,97 @@ error: goto exit; } +res_T +s3dut_create_thick_truncated_sphere + (struct mem_allocator* allocator, + const double radius, + const double thickness, + const unsigned nslices, + const unsigned nstacks, + const double z_range[2], + const int c_e, + struct s3dut_mesh** mesh) +{ + struct s3dut_mesh* sphere = NULL; + int close_ends = c_e; + double* coords = NULL; + double* prev_coords; + size_t* ids_out = NULL; + size_t* ids_in = NULL; + size_t* ids_walls = NULL; + size_t id_offset; + const double internal_radius = radius - thickness; + const int top_truncated = z_range && (z_range[1] < +radius); + const int bottom_truncated = z_range && (z_range[0] > -radius); + const int close_top = top_truncated && (close_ends & S3DUT_CAP_POS_Z); + const int close_bottom = bottom_truncated && (close_ends & S3DUT_CAP_NEG_Z); + const int top_seam = z_range && (z_range[1] < internal_radius) && !close_top; + const int bottom_seam + = z_range && (z_range[0] > -internal_radius) && ! close_bottom; + unsigned external_nrings; + unsigned internal_nrings; + const unsigned nb_seams = (unsigned)(top_seam + bottom_seam); + size_t nverts = 0; + size_t ntris = 0; + double z_internal_range[2]; + res_T res = RES_OK; + + if(radius <= thickness || thickness <= 0 || nslices < 3 || nstacks < 2 + || !mesh || (z_range && z_range[0] >= z_range[1])) { + return RES_BAD_ARG; + } + + /* Special case when a single sphere is truncated */ + if(top_truncated && (z_range[1] >= internal_radius)) { + close_ends |= S3DUT_CAP_POS_Z; /* close the external sphere's top end */ + } + if(bottom_truncated && (z_range[0] <= -internal_radius)) { + close_ends |= S3DUT_CAP_NEG_Z; /* close the external sphere's bottom end */ + } + z_internal_range[0] = (bottom_truncated && !close_bottom) + ? z_range[0] : (z_range ? z_range[0] : -radius) + thickness; + z_internal_range[1] = (top_truncated && !close_top) ? + z_range[1] : (z_range ? z_range[1] : +radius) - thickness; + sphere_accum_counts(radius, nslices, nstacks, z_range, close_ends, + &external_nrings, &ntris, &nverts); + sphere_accum_counts(radius-thickness, nslices, nstacks, z_internal_range, + close_ends, &internal_nrings, &ntris, &nverts); + ntris += 2 * nb_seams * nslices; /* # seam tris */ + res = mesh_create(allocator, S3DUT_MESH_THICK_SPHERE, nverts, ntris, &sphere); + if(res != RES_OK) goto error; + + coords = darray_double_data_get(&sphere->coords); + ids_out = darray_size_t_data_get(&sphere->ids); + /* External sphere */ + prev_coords = coords; + setup_sphere_coords + (allocator, &coords, radius, z_range, nslices, nstacks, close_ends); + ids_in = setup_sphere_indices(ids_out, 0, nslices, nstacks, radius, z_range, + close_ends, 1); + /* Internal sphere */ + id_offset = (size_t)(coords - prev_coords); + ASSERT(id_offset % 3 == 0); + id_offset /= 3; + setup_sphere_coords(allocator, &coords, radius - thickness, z_internal_range, + nslices, nstacks, close_ends); + ids_walls = setup_sphere_indices (ids_in, id_offset, nslices, + nstacks, radius - thickness, z_internal_range, close_ends, 0); + if(bottom_seam) { + ids_walls = close_wall(ids_walls, 0, id_offset, nslices, external_nrings, + internal_nrings, 1); + } + if(top_seam) { + ids_walls = close_wall(ids_walls, nstacks, id_offset + nstacks, nslices, + external_nrings, internal_nrings, 0); + } + +exit: + if(mesh) *mesh = sphere; + return res; +error: + if(sphere) { + S3DUT(mesh_ref_put(sphere)); + sphere = NULL; + } + goto exit; +} diff --git a/src/s3dut_super_shape.c b/src/s3dut_super_shape.c @@ -0,0 +1,138 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (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" + +#include <rsys/double2.h> +#include <rsys/double3.h> +#include <math.h> + +struct spherical { + double r; + double theta; + double phi; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static FINLINE void +cartesian_to_spherical(const double* xyz, struct spherical* spherical) +{ + ASSERT(spherical && xyz); + spherical->r = d3_len(xyz); + spherical->phi = asin(xyz[2]/spherical->r); + /* Map the atan results in [-PI, PI] to ensure that theta lies in [-PI,2PI] + * rather than [-PI/2, 3PI/2] that would violate the super formula + * constraints */ + spherical->theta = xyz[0] == 0 ? PI/2 : atan(xyz[1]/xyz[0]) - PI/2; + if(xyz[0] < 0) spherical->theta += PI; +} + +static FINLINE double +super_formula_eval(const struct s3dut_super_formula* form, const double angle) +{ + double m, k, g; + ASSERT(form); + m = fabs(cos(form->M * angle / 4.0)) / form->A; + k = fabs(sin(form->M * angle / 4.0)) / form->B; + g = pow(m, form->N1) + pow(k, form->N2); + return pow(g, (-1.0/form->N0)); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +s3dut_create_super_shape + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const struct s3dut_super_formula* formula0, + const struct s3dut_super_formula* formula1, + const double radius, /* In [0, INF) */ + const unsigned nslices, /* # subdivisions around Z axis in [3, INF) */ + const unsigned nstacks, /* # subdivisions along Z axis in [2, INF) */ + struct s3dut_mesh** super_shape) +{ + return s3dut_create_thick_truncated_super_shape(allocator, formula0, + formula1, radius, 0, nslices, nstacks, NULL, 0, super_shape); +} + +res_T +s3dut_create_thick_truncated_super_shape + (struct mem_allocator* allocator, + const struct s3dut_super_formula* formula0, + const struct s3dut_super_formula* formula1, + const double radius, + const double thickness, + const unsigned nslices, + const unsigned nstacks, + const double z_range[2], + const int cap_mask, + struct s3dut_mesh** mesh) +{ + struct s3dut_mesh* sshape = NULL; + size_t nverts; + size_t ivert; + res_T res = RES_OK; + + if(!formula0 || !formula1 || !mesh) { + res = RES_BAD_ARG; + goto error; + } + + if(thickness == 0) { + res = s3dut_create_truncated_sphere(allocator, radius, nslices, nstacks, + z_range, cap_mask, &sshape); + } else { + res = s3dut_create_thick_truncated_sphere(allocator, radius, thickness, + nslices, nstacks, z_range, cap_mask, &sshape); + } + if(res != RES_OK) goto error; + + /* Positioned the sphere vertices wrt to the super formulas */ + nverts = darray_double_size_get(&sshape->coords) / 3u; + FOR_EACH(ivert, 0, nverts) { + double* pos = darray_double_data_get(&sshape->coords) + ivert*3; + struct spherical spherical; + double uv[2]; + double cos_theta, cos_phi; + double sin_theta, sin_phi; + + cartesian_to_spherical(pos, &spherical); + + uv[0] = super_formula_eval(formula0, spherical.theta); + uv[1] = super_formula_eval(formula1, spherical.phi); + + cos_theta = cos(spherical.theta); + sin_theta = sin(spherical.theta); + cos_phi = cos(spherical.phi); + sin_phi = sin(spherical.phi); + + pos[0] = uv[0] * cos_theta * uv[1] * cos_phi * spherical.r; + pos[1] = uv[0] * sin_theta * uv[1] * cos_phi * spherical.r; + pos[2] = uv[1] * sin_phi * spherical.r; + } + + sshape->type = S3DUT_MESH_SUPER_SHAPE; + +exit: + if(mesh) *mesh = sshape; + return res; +error: + if(sshape) { S3DUT(mesh_ref_put(sshape)); sshape = NULL; } + goto exit; +} + diff --git a/src/test_s3dut_cylinder.c b/src/test_s3dut_cylinder.c @@ -64,8 +64,8 @@ main(int argc, char** argv) CHECK(s3dut_create_cylinder(&allocator, 1, 1, 3, 1, &msh), RES_OK); CHECK(s3dut_mesh_ref_put(msh), RES_OK); - CHECK(s3dut_create_cylinder(&allocator,-1, 1, 3, 1, &msh), RES_BAD_ARG); - CHECK(s3dut_create_cylinder(&allocator, 1,-1, 3, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(&allocator, -1, 1, 3, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_cylinder(&allocator, 1, -1, 3, 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, 3, 0, &msh), RES_BAD_ARG); CHECK(s3dut_create_cylinder(&allocator, 1, 2, 16, 4, &msh), RES_OK); diff --git a/src/test_s3dut_hemisphere.c b/src/test_s3dut_hemisphere.c @@ -32,20 +32,20 @@ main(int argc, char** argv) CHECK(s3dut_create_hemisphere(NULL, 0, 0, 0, NULL), RES_BAD_ARG); CHECK(s3dut_create_hemisphere(NULL, 1, 0, 0, NULL), RES_BAD_ARG); - CHECK(s3dut_create_hemisphere(NULL, 0, 2, 0, NULL), RES_BAD_ARG); - CHECK(s3dut_create_hemisphere(NULL, 1, 2, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_hemisphere(NULL, 0, 3, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_hemisphere(NULL, 1, 3, 0, NULL), RES_BAD_ARG); CHECK(s3dut_create_hemisphere(NULL, 0, 0, 2, NULL), RES_BAD_ARG); CHECK(s3dut_create_hemisphere(NULL, 1, 0, 2, NULL), RES_BAD_ARG); - CHECK(s3dut_create_hemisphere(NULL, 0, 2, 2, NULL), RES_BAD_ARG); - CHECK(s3dut_create_hemisphere(NULL, 1, 2, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_hemisphere(NULL, 0, 3, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_hemisphere(NULL, 1, 3, 2, NULL), RES_BAD_ARG); CHECK(s3dut_create_hemisphere(NULL, 0, 0, 0, &msh), RES_BAD_ARG); CHECK(s3dut_create_hemisphere(NULL, 1, 0, 0, &msh), RES_BAD_ARG); - CHECK(s3dut_create_hemisphere(NULL, 0, 2, 0, &msh), RES_BAD_ARG); - CHECK(s3dut_create_hemisphere(NULL, 1, 2, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_hemisphere(NULL, 0, 3, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_hemisphere(NULL, 1, 3, 0, &msh), RES_BAD_ARG); CHECK(s3dut_create_hemisphere(NULL, 0, 0, 2, &msh), RES_BAD_ARG); CHECK(s3dut_create_hemisphere(NULL, 1, 0, 2, &msh), RES_BAD_ARG); - CHECK(s3dut_create_hemisphere(NULL, 0, 2, 2, &msh), RES_BAD_ARG); - CHECK(s3dut_create_hemisphere(NULL, 1, 2, 2, &msh), RES_OK); + CHECK(s3dut_create_hemisphere(NULL, 0, 3, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_hemisphere(NULL, 1, 3, 2, &msh), RES_OK); CHECK(s3dut_mesh_ref_get(NULL), RES_BAD_ARG); CHECK(s3dut_mesh_ref_get(msh), RES_OK); @@ -53,12 +53,12 @@ main(int argc, char** argv) CHECK(s3dut_mesh_ref_put(msh), RES_OK); CHECK(s3dut_mesh_ref_put(msh), RES_OK); - CHECK(s3dut_create_hemisphere(&allocator, 1, 2, 2, &msh), RES_OK); + CHECK(s3dut_create_hemisphere(&allocator, 1, 3, 2, &msh), RES_OK); CHECK(s3dut_mesh_ref_put(msh), RES_OK); CHECK(s3dut_create_hemisphere(&allocator, 1, 1, 2, &msh), RES_BAD_ARG); - CHECK(s3dut_create_hemisphere(&allocator, 1, 2, 1, &msh), RES_BAD_ARG); - CHECK(s3dut_create_hemisphere(&allocator,-1, 2, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_hemisphere(&allocator, 1, 3, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_hemisphere(&allocator,-1, 3, 2, &msh), RES_BAD_ARG); CHECK(s3dut_create_hemisphere(&allocator, 1, 32, 16, &msh), RES_OK); CHECK(s3dut_mesh_get_data(NULL, NULL), RES_BAD_ARG); @@ -68,7 +68,7 @@ main(int argc, char** argv) NCHECK(data.positions, NULL); NCHECK(data.indices, NULL); CHECK(data.nvertices >= (32*(16-1)+1), 1); - CHECK(data.nprimitives, (32*(16-2)*2) + 32); + CHECK(data.nprimitives, (32*(16-1)*2) + 32); FOR_EACH(i, 0, data.nvertices) { double v[3]; diff --git a/src/test_s3dut_super_shape.c b/src/test_s3dut_super_shape.c @@ -0,0 +1,119 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (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; + struct s3dut_super_formula f0, f1; + (void)argc, (void)argv; + + CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); + + f0.A = 1; f0.B = 1; f0.M = 5; f0.N0 = 1; f0.N1 = 1; f0.N2 = 2; + f1.A = 1; f1.B = 1; f1.M = 5; f1.N0 = 1; f1.N1 = 1; f1.N2 = 3; + + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 1, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 1, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 1, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 1, 0, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 0, 3, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 0, 3, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 0, 3, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 0, 3, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 1, 3, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 1, 3, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 1, 3, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 1, 3, 0, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 0, 0, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 0, 0, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 0, 0, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 0, 0, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 1, 0, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 1, 0, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 1, 0, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 1, 0, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 0, 3, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 0, 3, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 0, 3, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 0, 3, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 1, 3, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 1, 3, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 1, 3, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 1, 3, 2, NULL), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 1, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 1, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 1, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 1, 0, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 0, 3, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 0, 3, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 0, 3, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 0, 3, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 1, 3, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 1, 3, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 1, 3, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 1, 3, 0, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 0, 0, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 0, 0, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 0, 0, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 0, 0, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 1, 0, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 1, 0, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 1, 0, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 1, 0, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 0, 3, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 0, 3, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 0, 3, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 0, 3, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, NULL, 1, 3, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, NULL, 1, 3, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, NULL, &f1, 1, 3, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(NULL, &f0, &f1, 1, 3, 2, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(s3dut_create_super_shape(&allocator, &f0, &f1, 1, 3, 2, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(s3dut_create_super_shape(&allocator, &f0, &f1, 1, 2, 2, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(&allocator, &f0, &f1, 1, 3, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(&allocator, &f0, &f1,-1, 3, 1, &msh), RES_BAD_ARG); + CHECK(s3dut_create_super_shape(&allocator, &f0, &f1, 1, 32, 16, &msh), RES_OK); + + CHECK(s3dut_mesh_get_data(msh, &data), RES_OK); + NCHECK(data.positions, NULL); + NCHECK(data.indices, NULL); + + 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_thick_cylinder.c b/src/test_s3dut_thick_cylinder.c @@ -0,0 +1,123 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (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); + #define CR_CYL s3dut_create_thick_cylinder + CHECK(CR_CYL(NULL, 0, 0, 0, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0.1, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0.1, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0.1, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0.1, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0.1, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0.1, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0.1, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0.1, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0.1, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0.1, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0.1, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0.1, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0.1, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0.1, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0.1, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0.1, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0.1, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0.1, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0.1, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0.1, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0.1, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0.1, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0.1, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0.1, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0.1, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0.1, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0.1, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0.1, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0.1, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0.1, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0.1, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0.1, 3, 1, 0, &msh), RES_OK); + + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(CR_CYL(&allocator, 1, 1, 0.1, 3, 1, 0, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(CR_CYL(&allocator,-1, 1, 0.1, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(&allocator, 1,-1, 0.1, 3, 1, 0, &msh), RES_BAD_ARG); + + CHECK(CR_CYL(&allocator, 1, 1, -0.1, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(&allocator, 1, 1, 1, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(&allocator, 2, 1, 0.5, 3, 1, + S3DUT_CAP_POS_Z| S3DUT_CAP_NEG_Z, &msh), RES_BAD_ARG); + CHECK(CR_CYL(&allocator, 2, 0.5, 0.5, 3, 1, S3DUT_CAP_POS_Z, &msh), RES_BAD_ARG); + CHECK(CR_CYL(&allocator, 2, 0.5, 0.5, 3, 1, S3DUT_CAP_NEG_Z, &msh), RES_BAD_ARG); + + CHECK(CR_CYL(&allocator, 1, 1, 0.1, 2, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(&allocator, 1, 1, 0.1, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(&allocator, 1, 2, 0.1, 16, 4, S3DUT_CAP_POS_Z, &msh), RES_OK); + #undef CR_CYL + + 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; +} + diff --git a/src/test_s3dut_thick_truncated_sphere.c b/src/test_s3dut_thick_truncated_sphere.c @@ -0,0 +1,114 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (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" + +#include <rsys/double3.h> +#include <rsys/math.h> + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct s3dut_mesh* msh; + struct s3dut_mesh_data data; + double z_range[2]; + (void)argc, (void)argv; + + CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); + + #define CR_SPH s3dut_create_thick_truncated_sphere + + CHECK(CR_SPH(NULL, 0, 0, 2, 1, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0, 2, 1, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0.1, 2, 1, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0.1, 2, 1, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0, 3, 1, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0, 3, 1, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0.1, 3, 1, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0.1, 3, 1, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0, 2, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0, 2, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0.1, 2, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0.1, 2, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0.1, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0.1, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0, 2, 1, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0, 2, 1, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0.1, 2, 1, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0.1, 2, 1, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0, 3, 1, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0, 3, 1, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0.1, 3, 1, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0.1, 3, 1, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0, 2, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0, 2, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0.1, 2, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0.1, 2, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 0, 0.1, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CR_SPH(NULL, 1, 0.1, 3, 2, NULL, 0, &msh), RES_OK); + + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + z_range[0] = -0.8; + z_range[1] = -0.1; + CHECK(CR_SPH(&allocator, 1, 0.1, 16, 8, z_range, S3DUT_CAP_NEG_Z, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(CR_SPH(&allocator, 1, 0.1, 16, 8, z_range, S3DUT_CAP_POS_Z, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(CR_SPH(&allocator, 1, 0.1, 16, 8, z_range, + S3DUT_CAP_POS_Z | S3DUT_CAP_NEG_Z, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + z_range[0] = 0; + z_range[1] = 0.8; + CHECK(CR_SPH(&allocator, 1, 0.1, 16, 8, z_range, 0, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + z_range[0] = 0; + z_range[1] = 2; + CHECK(CR_SPH(&allocator, 1, 0.1, 16, 8, z_range, 0, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + z_range[0] = -0.5; + z_range[1] = -0.8; + CHECK(CR_SPH(&allocator, 1, 0.1, 16, 8, z_range, 0, &msh), RES_BAD_ARG); + + z_range[0] = 0; + z_range[1] = 0.8; + CHECK(CR_SPH(&allocator, 1, 0.1, 16, 8, z_range, S3DUT_CAP_NEG_Z, &msh), RES_OK); + + CHECK(s3dut_mesh_get_data(msh, &data), RES_OK); + NCHECK(data.positions, NULL); + NCHECK(data.indices, NULL); + #undef CR_TS + + 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_thick_truncated_super_shape.c b/src/test_s3dut_thick_truncated_super_shape.c @@ -0,0 +1,185 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (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; + struct s3dut_super_formula f0, f1; + double z_range[2]; + (void)argc, (void)argv; + + CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); + + f0.A = 1; f0.B = 1; f0.M = 5; f0.N0 = 1; f0.N1 = 1; f0.N2 = 2; + f1.A = 1; f1.B = 1; f1.M = 5; f1.N0 = 1; f1.N1 = 1; f1.N2 = 3; + + #define CREATE s3dut_create_thick_truncated_super_shape + CHECK(CREATE(NULL, NULL, NULL, 0, -1, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, -1, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, -1, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, -1, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, -1, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, -1, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, -1, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, -1, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, 0, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, 0, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, 0, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, 0, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, 0, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, 0, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, 0, 0, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, -1, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, -1, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, -1, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, -1, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, -1, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, -1, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, -1, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, -1, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, 0, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, 0, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, 0, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, 0, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, 0, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, 0, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, 0, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, 0, 3, 0, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, -1, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, -1, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, -1, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, -1, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, -1, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, -1, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, -1, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, -1, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, 0, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, 0, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, 0, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, 0, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, 0, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, 0, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, 0, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, 0, 0, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, -1, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, -1, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, -1, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, -1, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, -1, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, -1, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, -1, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, -1, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, 0, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, 0, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, 0, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, 0, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, 0, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, 0, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, 0, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, 0, 3, 2, NULL, 0, NULL), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, -1, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, -1, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, -1, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, -1, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, -1, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, -1, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, -1, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, -1, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, 0, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, 0, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, 0, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, 0, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, 0, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, 0, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, 0, 0, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, -1, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, -1, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, -1, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, -1, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, -1, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, -1, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, -1, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, -1, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, 0, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, 0, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, 0, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, 0, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, 0, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, 0, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, 0, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, 0, 3, 0, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, -1, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, -1, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, -1, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, -1, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, -1, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, -1, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, -1, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, -1, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, 0, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, 0, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, 0, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, 0, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, 0, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, 0, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, 0, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, 0, 0, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, -1, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, -1, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, -1, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, -1, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, -1, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, -1, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, -1, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, -1, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 0, 0, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 0, 0, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 0, 0, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 0, 0, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, NULL, 1, 0, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, NULL, 1, 0, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, NULL, &f1, 1, 0, 3, 2, NULL, 0, &msh), RES_BAD_ARG); + CHECK(CREATE(NULL, &f0, &f1, 1, 0, 3, 2, NULL, 0, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(CREATE(&allocator, &f0, &f1, 1, 0, 3, 2, NULL, 0, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + z_range[0] = -0.1, z_range[1] = 0.5; + CHECK(CREATE(&allocator, &f0, &f1, 1, 0.3, 32, 16, z_range, S3DUT_CAP_NEG_Z, + &msh), RES_OK); + + CHECK(s3dut_mesh_get_data(msh, &data), RES_OK); + NCHECK(data.positions, NULL); + NCHECK(data.indices, NULL); + + 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_thin_cylinder.c b/src/test_s3dut_thin_cylinder.c @@ -0,0 +1,93 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (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); + + #define CR_CYL s3dut_create_thin_cylinder + + CHECK(CR_CYL(NULL, 0, 0, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 3, 0, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 3, 1, 0, NULL), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 0, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 0, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 0, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 0, 1, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(NULL, 1, 1, 3, 1, 0, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(CR_CYL(&allocator, 1, 1, 3, 1, 0, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(CR_CYL(&allocator, 1, 1, 3, 1, 0, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + CHECK(CR_CYL(&allocator, 1, 1, 3, 1, S3DUT_CAP_POS_Z, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + CHECK(CR_CYL(&allocator, 1, 1, 3, 1, S3DUT_CAP_NEG_Z, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + CHECK(CR_CYL(&allocator, 1, 1, 3, 1, + S3DUT_CAP_POS_Z | S3DUT_CAP_NEG_Z, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(CR_CYL(&allocator, -1, 1, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(&allocator, 1, -1, 3, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(&allocator, 1, 1, 2, 1, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(&allocator, 1, 1, 3, 0, 0, &msh), RES_BAD_ARG); + CHECK(CR_CYL(&allocator, 1, 2, 16, 4, S3DUT_CAP_NEG_Z, &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; +} + diff --git a/src/test_s3dut_truncated_sphere.c b/src/test_s3dut_truncated_sphere.c @@ -0,0 +1,65 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (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" + +#include <rsys/double3.h> +#include <rsys/math.h> + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct s3dut_mesh* msh; + struct s3dut_mesh_data data; + double z_range[2]; + (void)argc, (void)argv; + + CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); + + #define CR_TS s3dut_create_truncated_sphere + z_range[0] = z_range[1] = 0; + CHECK(CR_TS(NULL, 1, 16, 8, z_range, 0, &msh), RES_BAD_ARG); + z_range[1] = -0.5; + CHECK(CR_TS(NULL, 1, 16, 8, z_range, 0, &msh), RES_BAD_ARG); + z_range[1] = +0.5; + CHECK(CR_TS(NULL, 1, 16, 8, z_range, 0, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + CHECK(CR_TS(NULL, 1, 16, 8, NULL, 0, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + CHECK(CR_TS(&allocator, 1, 16, 8, NULL, 0, &msh), RES_OK); + CHECK(s3dut_mesh_ref_put(msh), RES_OK); + + z_range[0] = 0; + z_range[1] = 0.9; + CHECK(CR_TS(&allocator, 1, 16, 8, z_range, S3DUT_CAP_NEG_Z, &msh), RES_OK); + + CHECK(s3dut_mesh_get_data(msh, &data), RES_OK); + NCHECK(data.positions, NULL); + NCHECK(data.indices, NULL); + #undef CR_TS + + 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; +} +