commit c24315e59e5f23e7595a83fcd60a476cf32d0448
parent 68b4d54fc6522c13cab48c6d8a91dd1c1e5f4e17
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 25 Nov 2016 12:17:20 +0100
Test the s3dut_<sphere|mesh> API
Diffstat:
6 files changed, 204 insertions(+), 36 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -73,7 +73,8 @@ if(NOT NO_TEST)
target_link_libraries(${_name} s3dut RSys)
add_test(${_name} ${_name})
endfunction()
- # TODO add tests here
+
+ new_test(test_s3dut_sphere)
endif()
################################################################################
diff --git a/src/s3dut.h b/src/s3dut.h
@@ -38,18 +38,17 @@
struct mem_allocator;
struct s3dut_mesh;
+struct s3dut_mesh_data {
+ const double* positions;
+ const size_t* indices;
+ size_t nvertices; /* # vertices */
+ size_t nprimitives; /* # primitives */
+};
+
/*******************************************************************************
* Stard-3DUT API
******************************************************************************/
S3DUT_API res_T
-s3dut_create_sphere
- (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */
- const double radius,
- const unsigned nslices, /* # subdivisions around the Z axis */
- const unsigned nstacks, /* # subdivisions along the Z axis */
- struct s3dut_mesh** sphere);
-
-S3DUT_API res_T
s3dut_mesh_ref_get
(struct s3dut_mesh* mesh);
@@ -57,5 +56,22 @@ S3DUT_API res_T
s3dut_mesh_ref_put
(struct s3dut_mesh* mesh);
+S3DUT_API res_T
+s3dut_mesh_get_data
+ (struct s3dut_mesh* mesh,
+ struct s3dut_mesh_data* data);
+
+/* Create a triangulared UV sphere discretized in `nslices' around the Z axis
+ * and `nstacks' along the Z axis. 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_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 */
+ struct s3dut_mesh** sphere);
+
#endif /* S3DUT_H */
diff --git a/src/s3dut_mesh.c b/src/s3dut_mesh.c
@@ -51,6 +51,26 @@ s3dut_mesh_ref_put(struct s3dut_mesh* mesh)
return RES_OK;
}
+res_T
+s3dut_mesh_get_data(struct s3dut_mesh* mesh, struct s3dut_mesh_data* data)
+{
+ size_t ncoords, nids;
+ if(!mesh || !data) return RES_BAD_ARG;
+
+ data->positions = darray_double_cdata_get(&mesh->coords);
+ data->indices = darray_size_t_cdata_get(&mesh->ids);
+
+ ncoords = darray_double_size_get(&mesh->coords);
+ nids = darray_size_t_size_get(&mesh->ids);
+ ASSERT(ncoords % 3 == 0); /* Only 3D coordinates are supported */
+ ASSERT(nids % 3 == 0); /* Only triangular primitives are supported */
+
+ data->nvertices = ncoords / 3;
+ data->nprimitives = nids / 3;
+
+ return RES_OK;
+}
+
/*******************************************************************************
* Local function
******************************************************************************/
diff --git a/src/s3dut_sphere.c b/src/s3dut_sphere.c
@@ -24,8 +24,8 @@ 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 */
+ const unsigned nthetas, /* # subdivisions around the Z axis */
+ const unsigned nphis) /* # 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 && nslices >= 2 && nstacks >= 2);
+ ASSERT(coords && radius > 0 && nthetas >= 2 && nphis >= 2);
darray_double_init(allocator, &sincos_theta);
darray_double_init(allocator, &sincos_phi);
- res = darray_double_resize(&sincos_theta, nslices*2/*sin & cos*/);
+ res = darray_double_resize(&sincos_theta, nthetas*2/*sin & cos*/);
if(res != RES_OK) goto error;
- res = darray_double_resize(&sincos_phi, nstacks*2/*sin & cos*/);
+ res = darray_double_resize(&sincos_phi, (nphis-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) {
+ step_theta = 2*PI / (double)nthetas;
+ FOR_EACH(itheta, 0, nthetas) {
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) {
+ step_phi = PI/(double)nphis;
+ FOR_EACH(iphi, 0, nphis-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, nslices) {
+ FOR_EACH(itheta, 0, nthetas) {
const double* theta = darray_double_cdata_get(&sincos_theta) + itheta*2;
- FOR_EACH(iphi, 0, nstacks-1) {
+ FOR_EACH(iphi, 0, nphis-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];
@@ -93,18 +93,18 @@ error:
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 */
+ const unsigned nthetas, /* # subdivisions around the Z axis */
+ const unsigned nphis) /* # subdivisions along the Z axis */
{
size_t i, itheta, iphi;
- ASSERT(ids && nslices && nstacks);
+ ASSERT(ids && nthetas && nphis);
/* 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) {
+ 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) {
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, nstacks) {
- const size_t itheta0 = itheta * (nstacks - 1);
- const size_t itheta1 = ((itheta + 1) % nslices) * (nstacks - 1);
+ FOR_EACH(itheta, 0, nthetas) {
+ const size_t itheta0 = itheta * (nphis - 1);
+ const size_t itheta1 = ((itheta + 1) % nthetas) * (nphis - 1);
- darray_size_t_data_get(ids)[i++] = nslices * (nstacks - 1);
+ darray_size_t_data_get(ids)[i++] = nthetas * (nphis - 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);
+ darray_size_t_data_get(ids)[i++] = nthetas * (nphis - 1) + 1;
+ darray_size_t_data_get(ids)[i++] = itheta1 + (nphis - 2);
+ darray_size_t_data_get(ids)[i++] = itheta0 + (nphis - 2);
}
}
@@ -149,7 +149,7 @@ s3dut_create_sphere
size_t ntris;
res_T res = RES_OK;
- if(radius <= 0 || nslices < 2 || nstacks < 2 || !mesh) {
+ if(radius <= 0 || nslices < 2 || nstacks < 2 || !mesh) {
res = RES_BAD_ARG;
goto error;
}
@@ -168,7 +168,7 @@ s3dut_create_sphere
res = setup_sphere_coords
(allocator, &sphere->coords, radius, nslices, nstacks);
if(res != RES_OK) goto error;
-
+
setup_sphere_indices(&sphere->ids, nslices, nstacks);
exit:
diff --git a/src/test_s3dut_sphere.c b/src/test_s3dut_sphere.c
@@ -0,0 +1,78 @@
+/* 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_sphere(NULL, 0, 0, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 1, 0, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 0, 2, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 1, 2, 0, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 0, 0, 2, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 1, 0, 2, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 0, 2, 2, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 1, 2, 2, NULL), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 0, 0, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 1, 0, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 0, 2, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 1, 2, 0, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 0, 0, 2, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 1, 0, 2, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 0, 2, 2, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(NULL, 1, 2, 2, &msh), RES_OK);
+
+ CHECK(s3dut_mesh_ref_get(NULL), RES_BAD_ARG);
+ CHECK(s3dut_mesh_ref_get(msh), RES_OK);
+ CHECK(s3dut_mesh_ref_put(NULL), RES_BAD_ARG);
+ CHECK(s3dut_mesh_ref_put(msh), RES_OK);
+ CHECK(s3dut_mesh_ref_put(msh), RES_OK);
+
+ CHECK(s3dut_create_sphere(&allocator, 1, 2, 2, &msh), RES_OK);
+ CHECK(s3dut_mesh_ref_put(msh), RES_OK);
+
+ CHECK(s3dut_create_sphere(&allocator, 1, 1, 2, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(&allocator, 1, 2, 1, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(&allocator,-1, 2, 2, &msh), RES_BAD_ARG);
+ CHECK(s3dut_create_sphere(&allocator, 1, 32, 16, &msh), RES_OK);
+
+ CHECK(s3dut_mesh_get_data(NULL, NULL), RES_BAD_ARG);
+ CHECK(s3dut_mesh_get_data(msh, NULL), RES_BAD_ARG);
+ CHECK(s3dut_mesh_get_data(NULL, &data), RES_BAD_ARG);
+ CHECK(s3dut_mesh_get_data(msh, &data), RES_OK);
+ NCHECK(data.positions, NULL);
+ NCHECK(data.indices, NULL);
+ CHECK(data.nvertices >= (32*(16-1)+2), 1);
+ CHECK(data.nprimitives, (32*(16-2)*2) + 2*32);
+
+ 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_utils.h b/src/test_s3dut_utils.h
@@ -0,0 +1,53 @@
+/* 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/>. */
+
+#ifndef TEST_S3DUT_UTILS_H
+#define TEST_S3DUT_UTILS_H
+
+#include "s3dut.h"
+
+#include <rsys/mem_allocator.h>
+#include <stdio.h>
+
+static INLINE void
+dump_mesh_data(FILE* stream, const struct s3dut_mesh_data* data)
+{
+ size_t i;
+ NCHECK(data, NULL);
+
+ FOR_EACH(i, 0, data->nvertices) {
+ fprintf(stream, "v %g %g %g\n", SPLIT3(data->positions + i*3));
+ }
+ FOR_EACH(i, 0, data->nprimitives) {
+ fprintf(stream, "f %lu %lu %lu\n",
+ data->indices[i*3+0] + 1,
+ data->indices[i*3+1] + 1,
+ data->indices[i*3+2] + 1);
+ }
+}
+
+static INLINE void
+check_memory_allocator(struct mem_allocator* allocator)
+{
+ if(MEM_ALLOCATED_SIZE(allocator)) {
+ char dump[512];
+ MEM_DUMP(allocator, dump, sizeof(dump)/sizeof(char));
+ fprintf(stderr, "%s\n", dump);
+ FATAL("Memory leaks\n");
+ }
+}
+
+#endif /* TEST_S3DUT_UTILS_H */
+