star-3dut

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

commit 3d123b64f2cf5a6726b832c28ee5d651550f4d66
parent f035b25a197253d032d136f5ba94d786128de55a
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 25 Nov 2016 09:02:07 +0100

Implement the s3dut_create_sphere function

Diffstat:
Asrc/s3dut_sphere.c | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 184 insertions(+), 0 deletions(-)

diff --git a/src/s3dut_sphere.c b/src/s3dut_sphere.c @@ -0,0 +1,184 @@ +/* Copyright (C) |Meso|Star> 2016 (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "s3dut.h" +#include "s3dut_mesh.h" + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static res_T +setup_sphere_coords + (struct mem_allocator* allocator, + struct darray_double* coords, + const double radius, + const unsigned nslices, /* # subdivisions around the Z axis */ + const unsigned nstacks) /* # subdivisions along the Z axis */ +{ + 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*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; + FOR_EACH(iphi, 0, nstacks) { + const double phi = -PI/2 + (double)(iphi+1) * step_phi; + darray_double_data_get(&sincos_phi)[iphi*2 + SIN] = sin(phi); + darray_double_data_get(&sincos_phi)[iphi*2 + COS] = cos(phi); + } + + /* 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; + darray_double_data_get(coords)[i++] = radius * COS[theta] * COS[phi]; + darray_double_data_get(coords)[i++] = radius * SIN[theta] * COS[phi]; + darray_double_data_get(coords)[i++] = radius * SIN[phi]; + } + } + + /* Setup the bottom polar vertex */ + darray_double_data_get(coords)[i++] = 0; + darray_double_data_get(coords)[i++] = 0; + darray_double_data_get(coords)[i++] = -radius; + + /* Setup the top polar vertex */ + darray_double_data_get(coords)[i++] = 0; + darray_double_data_get(coords)[i++] = 0; + darray_double_data_get(coords)[i++] = radius; + +exit: + darray_double_release(&sincos_theta); + darray_double_release(&sincos_phi); + return res; +error: + goto exit; +} + +static void +setup_sphere_indices + (struct darray_size_t* ids, + const unsigned nslices, /* # subdivisions around the Z axis */ + const unsigned nstacks) /* # subdivisions along the Z axis */ +{ + 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; + + darray_size_t_data_get(ids)[i++] = itheta0 + iphi0; + darray_size_t_data_get(ids)[i++] = itheta0 + iphi1; + darray_size_t_data_get(ids)[i++] = itheta1 + iphi0; + + darray_size_t_data_get(ids)[i++] = itheta1 + iphi0; + darray_size_t_data_get(ids)[i++] = itheta0 + iphi1; + darray_size_t_data_get(ids)[i++] = itheta1 + iphi1; + } + } + + /* Define the indices of the polar primitives */ + FOR_EACH(itheta, 0, nstacks) { + const size_t itheta0 = itheta * (nstacks - 1); + const size_t itheta1 = ((itheta + 1) % nslices) * (nstacks - 1); + + darray_size_t_data_get(ids)[i++] = nslices * (nstacks - 1); + darray_size_t_data_get(ids)[i++] = itheta0; + darray_size_t_data_get(ids)[i++] = itheta1; + + darray_size_t_data_get(ids)[i++] = nslices * (nstacks - 1) + 1; + darray_size_t_data_get(ids)[i++] = itheta1 + (nstacks - 2); + darray_size_t_data_get(ids)[i++] = itheta0 + (nstacks - 2); + } +} + +/******************************************************************************* + * Exported function + ******************************************************************************/ +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 */ + struct s3dut_mesh** mesh) +{ + struct s3dut_mesh* sphere = 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; + } + res = mesh_create(allocator, &sphere); + if(res != RES_OK) goto error; + sphere->type = S3DUT_MESH_SPHERE; + + nverts = nslices*(nstacks-1)/* #contour verts*/ + 2/*polar verts*/; + ntris = 2*nslices*(nstacks-2)/* #contour tris*/ + 2*nslices/* #polar tris*/; + + res = darray_double_resize(&sphere->coords, nverts*3/*#coords*/); + if(res != RES_OK) goto error; + res = darray_size_t_resize(&sphere->ids, ntris*3/*#ids per triangle*/); + if(res != RES_OK) goto error; + + res = setup_sphere_coords + (allocator, &sphere->coords, radius, nslices, nstacks); + if(res != RES_OK) goto error; + + setup_sphere_indices(&sphere->ids, nslices, nstacks); + +exit: + if(mesh) *mesh = sphere; + return res; +error: + if(sphere) { + S3DUT(mesh_ref_put(sphere)); + sphere = NULL; + } + goto exit; +} +