commit 2e7b833fadf36269772afc2d4642d2f5301a8780
parent 505d4e4c0c19044aeae8638f794a3006cf961b58
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 28 Nov 2016 15:23:07 +0100
Add and test the s3dut_create_cylinder function
Diffstat:
6 files changed, 279 insertions(+), 29 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -41,7 +41,10 @@ set(VERSION_MINOR 0)
set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
-set(S3DUT_FILES_SRC s3dut_mesh.c s3dut_sphere.c)
+set(S3DUT_FILES_SRC
+ s3dut_cylinder.c
+ s3dut_mesh.c
+ s3dut_sphere.c)
set(S3DUT_FILES_INC s3dut_mesh.h)
set(S3DUT_FILES_INC_API s3dut.h)
set(S3DUT_FILES_DOC COPYING README.md)
@@ -74,6 +77,7 @@ if(NOT NO_TEST)
add_test(${_name} ${_name})
endfunction()
+ new_test(test_s3dut_cylinder)
new_test(test_s3dut_sphere)
endif()
diff --git a/src/s3dut.h b/src/s3dut.h
@@ -68,10 +68,19 @@ s3dut_mesh_get_data
S3DUT_API res_T
s3dut_create_sphere
(struct mem_allocator* allocator, /* May be NULL <=> use default allocator */
- const double radius, /* Sphere radius */
- const unsigned nslices, /* # subdivisions around the Z axis */
- const unsigned nstacks, /* # subdivisions along the Z axis */
+ const double radius,
+ const unsigned nslices, /* # subdivisions around Z axis */
+ const unsigned nstacks, /* # subdivisions along Z axis */
struct s3dut_mesh** sphere);
+S3DUT_API res_T
+s3dut_create_cylinder
+ (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */
+ const double radius,
+ const double height,
+ const unsigned nslices, /* # subdivisions around Z axis */
+ const unsigned nstacks, /* # subdivision along Z axis */
+ struct s3dut_mesh** cylinder);
+
#endif /* S3DUT_H */
diff --git a/src/s3dut_cylinder.c b/src/s3dut_cylinder.c
@@ -0,0 +1,154 @@
+/* Copyright (C) |Meso|Star> 2016 (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "s3dut.h"
+#include "s3dut_mesh.h"
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static void
+setup_cylinder_coords
+ (double* coords,
+ const double radius,
+ const double height,
+ const unsigned nslices,
+ const unsigned nstacks)
+{
+ double step_theta;
+ double step_z;
+ size_t itheta, istack;
+ size_t i = 0;
+ ASSERT(coords && radius > 0 && height > 0 && nslices >= 2 && nstacks >= 1);
+
+ /* Contour vertices */
+ step_theta = 2*PI / (double)nslices;
+ step_z = height / (double)nstacks;
+ FOR_EACH(itheta, 0, nslices) {
+ const double theta = (double)itheta * step_theta;
+ const double x = cos(theta);
+ const double y = sin(theta);
+ double z = -height * 0.5;
+
+ FOR_EACH(istack, 0, nstacks+1) {
+ coords[i++] = x;
+ coords[i++] = y;
+ coords[i++] = z;
+ z += step_z;
+ }
+ }
+
+ /* Bottom polar vertex */
+ coords[i++] = 0;
+ coords[i++] = 0;
+ coords[i++] = -height * 0.5;
+
+ /* Top polar vertex */
+ coords[i++] = 0;
+ coords[i++] = 0;
+ coords[i++] = height * 0.5;
+}
+
+static void
+setup_cylinder_indices
+ (size_t* ids,
+ const unsigned nslices,
+ const unsigned nstacks)
+{
+ size_t islice;
+ size_t istack;
+ size_t ibottom;
+ size_t itop;
+ size_t i = 0;
+ ASSERT(ids && nslices && nstacks);
+
+ FOR_EACH(islice, 0, nslices) {
+ const size_t islice0 = islice * (nstacks + 1);
+ const size_t islice1 = ((islice + 1) % nslices) * (nstacks + 1);
+ FOR_EACH(istack, 0, nstacks) {
+ const size_t istack0 = istack + 0;
+ const size_t istack1 = istack + 1;
+
+ ids[i++] = islice0 + istack0;
+ ids[i++] = islice0 + istack1;
+ ids[i++] = islice1 + istack0;
+
+ ids[i++] = islice1 + istack0;
+ ids[i++] = islice0 + istack1;
+ ids[i++] = islice1 + istack1;
+ }
+ }
+
+ ibottom = nslices * (nstacks+1);
+ FOR_EACH(islice, 0, nslices) {
+ ids[i++] = ibottom;
+ ids[i++] = islice * (nstacks+1);
+ ids[i++] = ((islice+1)%nslices) * (nstacks+1);
+ }
+
+ itop = ibottom + 1;
+ FOR_EACH(islice, 0, nslices) {
+ ids[i++] = itop;
+ ids[i++] = islice * (nstacks+1) + nstacks;
+ ids[i++] = ((islice+1)%nslices) * (nstacks+1) + nstacks;
+ }
+}
+
+/*******************************************************************************
+ * Exported functions
+ ******************************************************************************/
+res_T
+s3dut_create_cylinder
+ (struct mem_allocator* allocator,
+ const double radius,
+ const double height,
+ const unsigned nslices,
+ const unsigned nstacks,
+ struct s3dut_mesh** mesh)
+{
+ struct s3dut_mesh* cylinder = NULL;
+ double* coords = NULL;
+ size_t* ids = NULL;
+ size_t nverts;
+ size_t ntris;
+ res_T res = RES_OK;
+
+ if(radius <= 0 || height <= 0 || nslices < 2 || nstacks < 1 || !mesh) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ nverts = nslices * (nstacks+1) /*#contour vers*/ + 2/*#polar verts*/;
+ ntris = 2*nslices*nstacks /*#contour tris*/ + 2*nslices/* #cao tris*/;
+
+ res = mesh_create(allocator, S3DUT_MESH_CYLINDER, nverts, ntris, &cylinder);
+ if(res != RES_OK) goto error;
+
+ coords = darray_double_data_get(&cylinder->coords);
+ ids = darray_size_t_data_get(&cylinder->ids);
+ setup_cylinder_coords(coords, radius, height, nslices, nstacks);
+ setup_cylinder_indices(ids, nslices, nstacks);
+
+exit:
+ if(mesh) *mesh = cylinder;
+ return res;
+error:
+ if(cylinder) {
+ S3DUT(mesh_ref_put(cylinder));
+ cylinder = NULL;
+ }
+ goto exit;
+}
+
diff --git a/src/s3dut_mesh.h b/src/s3dut_mesh.h
@@ -21,6 +21,7 @@
#include <rsys/ref_count.h>
enum s3dut_mesh_type {
+ S3DUT_MESH_CYLINDER,
S3DUT_MESH_SPHERE
};
diff --git a/src/s3dut_sphere.c b/src/s3dut_sphere.c
@@ -24,8 +24,8 @@ setup_sphere_coords
(struct mem_allocator* allocator,
double* coords,
const double radius,
- const unsigned nthetas, /* # subdivisions around the Z axis */
- const unsigned nphis) /* # subdivisions along the Z axis */
+ const unsigned nslices, /* # subdivisions around the Z axis */
+ const unsigned nstacks) /* # subdivisions along the Z axis */
{
enum { SIN, COS };
struct darray_double sincos_theta;
@@ -36,25 +36,25 @@ setup_sphere_coords
size_t iphi;
size_t i;
res_T res = RES_OK;
- ASSERT(coords && radius > 0 && nthetas >= 2 && nphis >= 2);
+ ASSERT(coords && radius > 0 && nslices >= 2 && nstacks >= 2);
darray_double_init(allocator, &sincos_theta);
darray_double_init(allocator, &sincos_phi);
- res = darray_double_resize(&sincos_theta, nthetas*2/*sin & cos*/);
+ res = darray_double_resize(&sincos_theta, nslices*2/*sin & cos*/);
if(res != RES_OK) goto error;
- res = darray_double_resize(&sincos_phi, (nphis-1)*2/*sin & cos*/);
+ res = darray_double_resize(&sincos_phi, (nstacks-1)*2/*sin & cos*/);
if(res != RES_OK) goto error;
/* Precompute the sinus/cosine of the theta/phi angles */
- step_theta = 2*PI / (double)nthetas;
- FOR_EACH(itheta, 0, nthetas) {
+ step_theta = 2*PI / (double)nslices;
+ FOR_EACH(itheta, 0, nslices) {
const double theta = -PI + (double)itheta * step_theta;
darray_double_data_get(&sincos_theta)[itheta*2 + SIN] = sin(theta);
darray_double_data_get(&sincos_theta)[itheta*2 + COS] = cos(theta);
}
- step_phi = PI/(double)nphis;
- FOR_EACH(iphi, 0, nphis-1) {
+ step_phi = PI/(double)nstacks;
+ FOR_EACH(iphi, 0, nstacks-1) {
const double phi = -PI/2 + (double)(iphi+1) * step_phi;
darray_double_data_get(&sincos_phi)[iphi*2 + SIN] = sin(phi);
darray_double_data_get(&sincos_phi)[iphi*2 + COS] = cos(phi);
@@ -62,9 +62,9 @@ setup_sphere_coords
/* Setup the contour vertices */
i = 0;
- FOR_EACH(itheta, 0, nthetas) {
+ FOR_EACH(itheta, 0, nslices) {
const double* theta = darray_double_cdata_get(&sincos_theta) + itheta*2;
- FOR_EACH(iphi, 0, nphis-1) {
+ FOR_EACH(iphi, 0, nstacks-1) {
const double* phi = darray_double_cdata_get(&sincos_phi) + iphi*2;
coords[i++] = radius * COS[theta] * COS[phi];
coords[i++] = radius * SIN[theta] * COS[phi];
@@ -93,18 +93,18 @@ error:
static void
setup_sphere_indices
(size_t* ids,
- const unsigned nthetas, /* # subdivisions around the Z axis */
- const unsigned nphis) /* # subdivisions along the Z axis */
+ const unsigned nslices, /* # subdivisions around the Z axis */
+ const unsigned nstacks) /* # subdivisions along the Z axis */
{
size_t i, itheta, iphi;
- ASSERT(ids && nthetas && nphis);
+ ASSERT(ids && nslices && nstacks);
/* Define the indices of the contour primitives */
i = 0;
- FOR_EACH(itheta, 0, nthetas) {
- const size_t itheta0 = itheta * (nphis - 1);
- const size_t itheta1 = ((itheta + 1) % nthetas) * (nphis - 1);
- FOR_EACH(iphi, 0, nphis-2) {
+ FOR_EACH(itheta, 0, nslices) {
+ const size_t itheta0 = itheta * (nstacks - 1);
+ const size_t itheta1 = ((itheta + 1) % nslices) * (nstacks - 1);
+ FOR_EACH(iphi, 0, nstacks-2) {
const size_t iphi0 = iphi + 0;
const size_t iphi1 = iphi + 1;
@@ -119,17 +119,17 @@ setup_sphere_indices
}
/* Define the indices of the polar primitives */
- FOR_EACH(itheta, 0, nthetas) {
- const size_t itheta0 = itheta * (nphis - 1);
- const size_t itheta1 = ((itheta + 1) % nthetas) * (nphis - 1);
+ FOR_EACH(itheta, 0, nslices) {
+ const size_t itheta0 = itheta * (nstacks - 1);
+ const size_t itheta1 = ((itheta + 1) % nslices) * (nstacks - 1);
- ids[i++] = nthetas * (nphis - 1);
+ ids[i++] = nslices * (nstacks - 1);
ids[i++] = itheta0;
ids[i++] = itheta1;
- ids[i++] = nthetas * (nphis - 1) + 1;
- ids[i++] = itheta1 + (nphis - 2);
- ids[i++] = itheta0 + (nphis - 2);
+ ids[i++] = nslices * (nstacks - 1) + 1;
+ ids[i++] = itheta1 + (nstacks - 2);
+ ids[i++] = itheta0 + (nstacks - 2);
}
}
diff --git a/src/test_s3dut_cylinder.c b/src/test_s3dut_cylinder.c
@@ -0,0 +1,82 @@
+/* Copyright (C) |Meso|Star> 2016 (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "s3dut.h"
+#include "test_s3dut_utils.h"
+
+int
+main(int argc, char** argv)
+{
+ struct mem_allocator allocator;
+ struct s3dut_mesh* msh;
+ struct s3dut_mesh_data data;
+ (void)argc, (void)argv;
+
+ CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
+
+ CHECK(s3dut_create_cylinder(NULL, 0, 0, 0, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 0, 0, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 1, 0, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 1, 0, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 0, 2, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 0, 2, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 1, 2, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 1, 2, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 0, 0, 1, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 0, 0, 1, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 1, 0, 1, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 1, 0, 1, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 0, 2, 1, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 0, 2, 1, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 1, 2, 1, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 1, 2, 1, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 0, 0, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 0, 0, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 1, 0, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 1, 0, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 0, 2, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 0, 2, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 1, 2, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 1, 2, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 0, 0, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 0, 0, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 1, 0, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 1, 0, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 0, 2, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 0, 2, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 0, 1, 2, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(NULL, 1, 1, 2, 1, &msh), RES_OK);
+
+ CHECK(s3dut_mesh_ref_put(msh), RES_OK);
+
+ CHECK(s3dut_create_cylinder(&allocator, 1, 1, 2, 1, &msh), RES_OK);
+ CHECK(s3dut_mesh_ref_put(msh), RES_OK);
+
+ CHECK(s3dut_create_cylinder(&allocator,-1, 1, 2, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(&allocator, 1,-1, 2, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(&allocator,-1, 1, 2, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(&allocator, 1,-1, 1, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_cylinder(&allocator, 1, 2, 16, 4, &msh), RES_OK);
+
+ CHECK(s3dut_mesh_get_data(msh, &data), RES_OK);
+ dump_mesh_data(stdout, &data);
+ CHECK(s3dut_mesh_ref_put(msh), RES_OK);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHECK(mem_allocated_size(), 0);
+ return 0;
+}
+