star-3dut

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

commit f55f1b6436f282848a2227b81558af7f4f220a98
parent 2e35463ed59d3d4c7babc0764786c602d66f3ed5
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 12 Oct 2017 11:09:01 +0200

Add the s3dut_create_super_shape function

Diffstat:
Mcmake/CMakeLists.txt | 3++-
Msrc/s3dut.h | 23+++++++++++++++++++++++
Msrc/s3dut_mesh.h | 3++-
Msrc/s3dut_sphere.c | 16++++++++--------
Asrc/s3dut_super_shape.c | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 145 insertions(+), 10 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -45,7 +45,8 @@ set(S3DUT_FILES_SRC s3dut_cuboid.c s3dut_cylinder.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) diff --git a/src/s3dut.h b/src/s3dut.h @@ -45,6 +45,18 @@ struct s3dut_mesh_data { size_t nprimitives; /* # primitives */ }; +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) @@ -190,4 +202,15 @@ s3dut_create_thick_truncated_sphere const int cap_mask, /* Combination of s3dut_cap_flag. Ignored if no clamp */ struct s3dut_mesh** sphere); +/* TODO comment */ +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); + #endif /* S3DUT_H */ diff --git a/src/s3dut_mesh.h b/src/s3dut_mesh.h @@ -26,7 +26,8 @@ enum s3dut_mesh_type { S3DUT_MESH_THICK_CYLINDER, S3DUT_MESH_HEMISPHERE, S3DUT_MESH_SPHERE, - S3DUT_MESH_THICK_SPHERE + S3DUT_MESH_THICK_SPHERE, + S3DUT_MESH_SUPER_SHAPE }; struct s3dut_mesh { diff --git a/src/s3dut_sphere.c b/src/s3dut_sphere.c @@ -258,18 +258,18 @@ s3dut_create_hemisphere z_range[0] = 0; z_range[1] = +radius; return s3dut_create_truncated_sphere - (allocator, radius, nslices, nstacks, z_range, 0, mesh); + (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 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; const int top_truncated = z_range && z_range[1] < +radius; diff --git a/src/s3dut_super_shape.c b/src/s3dut_super_shape.c @@ -0,0 +1,110 @@ +/* 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/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_dot(xyz, xyz); + spherical->theta = acos(xyz[2]/spherical->r); + spherical->phi = atan(xyz[1]/xyz[0]); +} + +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, + const struct s3dut_super_formula* formula0, + const struct s3dut_super_formula* formula1, + const double radius, + const unsigned nslices, + const unsigned nstacks, + struct s3dut_mesh** mesh) +{ + struct s3dut_mesh* sshape = NULL; + size_t nverts; + size_t ivert; + res_T res = RES_OK; + + if(radius<=0 || !formula0 || !formula1 || nslices<3 || nstacks<2 || !mesh) { + res = RES_BAD_ARG; + goto error; + } + + res = s3dut_create_sphere(allocator, radius, nslices, nstacks, &sshape); + if(res != RES_OK) goto error; + + /* Positionned 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; + pos[1] = uv[0] * sin_theta * uv[1] * cos_phi; + pos[2] = uv[1] * sin_phi; + } + + 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; +} +