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:
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;
+}
+