star-schiff

Library for estimating radiative properties
git clone git://git.meso-star.com/star-schiff.git
Log | Files | Refs | README | LICENSE

commit feb29598bd7077192484e7e4da76955c16e59f06
parent a3ac5a3a7fe8378facbb497a53d9918889ddb0ba
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 29 Feb 2016 14:17:21 +0100

Refactor the geometry definition of the tests

Diffstat:
Msrc/test_sschiff_estimator_cylinder.c | 144+++----------------------------------------------------------------------------
Msrc/test_sschiff_estimator_sphere.c | 142++-----------------------------------------------------------------------------
Msrc/test_sschiff_utils.h | 297+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 304 insertions(+), 279 deletions(-)

diff --git a/src/test_sschiff_estimator_cylinder.c b/src/test_sschiff_estimator_cylinder.c @@ -47,11 +47,6 @@ struct result { double avg_proj_area_SE; }; -struct geometry { - float* vertices; - unsigned* indices; -}; - struct sampler_context { struct geometry geometry; double aspect_ratio; @@ -59,12 +54,6 @@ struct sampler_context { double sigma; }; -struct cylinder { - struct geometry* geometry; - float radius; - float height; -}; - static void get_material_property (void* mtl, @@ -78,63 +67,13 @@ get_material_property props->relative_real_refractive_index = 1.01; } -static void -get_indices(const unsigned itri, unsigned ids[3], void* ctx) -{ - struct cylinder* cylinder = ctx; - const size_t i = itri * 3; - - CHECK(sa_size(cylinder->geometry->indices) % 3, 0); - CHECK(itri < sa_size(cylinder->geometry->indices) / 3, 1); - ids[0] = cylinder->geometry->indices[i + 0]; - ids[1] = cylinder->geometry->indices[i + 1]; - ids[2] = cylinder->geometry->indices[i + 2]; -} - -static void -get_position(const unsigned ivert, float vertex[3], void* ctx) -{ - struct cylinder* cylinder = ctx; - const size_t i = ivert * 3; - - CHECK(sa_size(cylinder->geometry->vertices) % 3, 0); - CHECK(ivert < sa_size(cylinder->geometry->vertices) / 3, 1); - vertex[0] = cylinder->geometry->vertices[i + 0] * cylinder->radius; - vertex[1] = cylinder->geometry->vertices[i + 1] * cylinder->radius; - vertex[2] = cylinder->geometry->vertices[i + 2] * cylinder->height; -} - -static FINLINE void -dump_geometry(struct geometry* geom) -{ - size_t i; - NCHECK(geom, NULL); - CHECK(sa_size(geom->vertices)%3, 0); - CHECK(sa_size(geom->indices)%3, 0); - - FOR_EACH(i, 0, sa_size(geom->vertices)/3) { - printf("v %f %f %f\n", - geom->vertices[i*3+0], - geom->vertices[i*3+1], - geom->vertices[i*3+2]); - } - FOR_EACH(i, 0, sa_size(geom->indices)/3) { - printf("f %d %d %d\n", - geom->indices[i*3+0] + 1, - geom->indices[i*3+1] + 1, - geom->indices[i*3+2] + 1); - } -} - static res_T sample_cylinder (struct ssp_rng* rng, struct s3d_shape* shape, void* sampler_context) { - struct s3d_vertex_data attrib; struct sampler_context* sampler_ctx = sampler_context; struct cylinder cylinder; double sample; - size_t nverts, nprims; (void)rng, (void)sampler_context; sample = ssp_ran_lognormal(rng, log(sampler_ctx->mean_radius), log(sampler_ctx->sigma)); @@ -142,82 +81,7 @@ sample_cylinder cylinder.radius = (float)(sample / pow(3.0 / (2.0*sampler_ctx->aspect_ratio), 1.0/3.0)); cylinder.height = (float)(2.f * cylinder.radius / sampler_ctx->aspect_ratio); - attrib.usage = S3D_POSITION; - attrib.type = S3D_FLOAT3; - attrib.get = get_position; - - nverts = sa_size(cylinder.geometry->vertices) / 3/*#coords*/; - nprims = sa_size(cylinder.geometry->indices) / 3/*#indices per prim*/; - - return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, - get_indices, (unsigned)nverts, &attrib, 1, &cylinder); -} - -static void -cylinder_init(struct geometry* geometry, const unsigned nsteps) -{ - const double step = 2*PI / (double)nsteps; - unsigned istep; - - NCHECK(geometry, NULL); - NCHECK(nsteps, 0); - - geometry->vertices = NULL; - geometry->indices = NULL; - - /* Generate the vertex coordinates */ - FOR_EACH(istep, 0, nsteps) { - const float theta = (float)(istep * step); - const float x = (float)cos(theta); - const float y = (float)sin(theta); - f3(sa_add(geometry->vertices, 3), x, y, -1.f); - f3(sa_add(geometry->vertices, 3), x, y, 0.f); - } - - /* "Polar" vertices */ - f3(sa_add(geometry->vertices, 3), 0.f, 0.f, -1.f); - f3(sa_add(geometry->vertices, 3), 0.f, 0.f, 0.f); - - /* Contour primitives */ - FOR_EACH(istep, 0, nsteps) { - const unsigned id = istep * 2; - unsigned* iprim; - - iprim = sa_add(geometry->indices, 3); - iprim[0] = (id + 0); - iprim[1] = (id + 1); - iprim[2] = (id + 2) % (nsteps*2); - - iprim = sa_add(geometry->indices, 3); - iprim[0] = (id + 2) % (nsteps*2); - iprim[1] = (id + 1); - iprim[2] = (id + 3) % (nsteps*2); - } - - /* Cap primitives */ - FOR_EACH(istep, 0, nsteps) { - const unsigned id = istep * 2; - unsigned* iprim; - - iprim = sa_add(geometry->indices, 3); - iprim[0] = (nsteps * 2); - iprim[1] = (id + 0); - iprim[2] = (id + 2) % (nsteps*2); - - iprim = sa_add(geometry->indices, 3); - iprim[0] = (nsteps * 2) + 1; - iprim[1] = (id + 3) % (nsteps*2); - iprim[2] = (id + 1); - } -} - -static void -cylinder_release(struct geometry* geometry) -{ - sa_release(geometry->vertices); - sa_release(geometry->indices); - geometry->vertices = NULL; - geometry->indices = NULL; + return cylinder_setup_s3d_shape(&cylinder, shape); } static INLINE void @@ -554,7 +418,7 @@ main(int argc, char** argv) }; const size_t nx = sizeof(x)/sizeof(double); const size_t nscatt_angles = 1000; - const size_t ngeoms = 1000; + const size_t ngeoms = 100; const size_t ndirs = 100; size_t i; (void)argc, (void)argv; @@ -565,7 +429,7 @@ main(int argc, char** argv) CHECK(sschiff_device_create (NULL, &allocator, SSCHIFF_NTHREADS_DEFAULT, 1, NULL, &dev), RES_OK); - cylinder_init(&sampler_ctx.geometry, 64); + geometry_init_cylinder(&sampler_ctx.geometry, 64); FOR_EACH(i, 0, nx) { const double wavelength = 0.6; /* In micron */ @@ -635,7 +499,7 @@ main(int argc, char** argv) CHECK(sschiff_device_ref_put(dev), RES_OK); CHECK(ssp_rng_ref_put(rng), RES_OK); - cylinder_release(&sampler_ctx.geometry); + geometry_release(&sampler_ctx.geometry); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); CHECK(mem_allocated_size(), 0); diff --git a/src/test_sschiff_estimator_sphere.c b/src/test_sschiff_estimator_sphere.c @@ -43,11 +43,6 @@ struct result { double extinction_cross_section; }; -struct geometry { - float* vertices; /* List of float[3] */ - unsigned* indices; /* List of unsigned[3] */ -}; - struct sampler_context { struct geometry geometry; double wavelength; /* In micron */ @@ -58,11 +53,6 @@ struct sampler_context { double sigma; }; -struct sphere { - struct geometry* geometry; - float radius; /* In micron */ -}; - static void get_material_property (void* mtl, @@ -82,148 +72,22 @@ get_material_property ctx->relative_imaginary_refractive_index; } -static void -get_indices(const unsigned itri, unsigned ids[3], void* ctx) -{ - struct sphere* sphere = ctx; - const size_t i = itri * 3; - - CHECK(sa_size(sphere->geometry->indices) % 3, 0); - CHECK(itri < sa_size(sphere->geometry->indices) / 3, 1); - ids[0] = sphere->geometry->indices[i + 0]; - ids[1] = sphere->geometry->indices[i + 1]; - ids[2] = sphere->geometry->indices[i + 2]; -} - -static INLINE void -get_position(const unsigned ivert, float vertex[3], void* ctx) -{ - struct sphere* sphere = ctx; - const size_t i = ivert * 3; - - CHECK(sa_size(sphere->geometry->vertices) % 3, 0); - CHECK(ivert < sa_size(sphere->geometry->vertices) / 3, 1); - vertex[0] = sphere->geometry->vertices[i + 0] * sphere->radius; - vertex[1] = sphere->geometry->vertices[i + 1] * sphere->radius; - vertex[2] = sphere->geometry->vertices[i + 2] * sphere->radius; -} - static res_T sample_sphere (struct ssp_rng* rng, struct s3d_shape* shape, void* sampler_context) { - struct s3d_vertex_data attrib; struct sampler_context* sampler_ctx = sampler_context; struct sphere sphere; - size_t nverts, nprims; NCHECK(rng, NULL); - NCHECK(shape, NULL); sphere.geometry = &sampler_ctx->geometry; sphere.radius = (float)ssp_ran_lognormal (rng, log(sampler_ctx->mean_radius), log(sampler_ctx->sigma)); - attrib.usage = S3D_POSITION; - attrib.type = S3D_FLOAT3; - attrib.get = get_position; - - nverts = sa_size(sphere.geometry->vertices) / 3/*#coords*/; - nprims = sa_size(sphere.geometry->indices) / 3/*#indices per prim*/; - - return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, - get_indices, (unsigned)nverts, &attrib, 1, &sphere); -} - -static void -sphere_init(struct geometry* sphere, const unsigned ntheta) -{ - const unsigned nphi = (unsigned)(((double)ntheta + 0.5) / 2.0); - const double step_theta = 2*PI / (double)ntheta; - const double step_phi = PI / (double)nphi; - double* cos_theta = NULL; - double* sin_theta = NULL; - double* cos_phi = NULL; - double* sin_phi = NULL; - unsigned itheta, iphi; - - NCHECK(sphere, NULL); - NCHECK(ntheta, 0); - - sphere->vertices = NULL; - sphere->indices = NULL; - - /* Precompute the cosine/sinus of the theta/phi angles */ - FOR_EACH(itheta, 0, ntheta) { - const double theta = -PI + (double)itheta * step_theta; - sa_push(cos_theta, cos(theta)); - sa_push(sin_theta, sin(theta)); - } - FOR_EACH(iphi, 1, nphi) { - const double phi = -PI/2 + (double)iphi * step_phi; - sa_push(cos_phi, cos(phi)); - sa_push(sin_phi, sin(phi)); - } - /* Compute the contour vertices */ - FOR_EACH(itheta, 0, ntheta) { - FOR_EACH(iphi, 0, nphi-1) { - sa_push(sphere->vertices, (float)(cos_theta[itheta]*cos_phi[iphi])); - sa_push(sphere->vertices, (float)(sin_theta[itheta]*cos_phi[iphi])); - sa_push(sphere->vertices, (float)sin_phi[iphi]); - } - } - /* Compute the polar vertices */ - f3(sa_add(sphere->vertices, 3), 0.f, 0.f,-1.f); - f3(sa_add(sphere->vertices, 3), 0.f, 0.f, 1.f); - - /* Define the indices of the contour primitives */ - FOR_EACH(itheta, 0, ntheta) { - const unsigned itheta0 = itheta * (nphi - 1); - const unsigned itheta1 = ((itheta + 1) % ntheta) * (nphi - 1); - FOR_EACH(iphi, 0, nphi-2) { - const unsigned iphi0 = iphi + 0; - const unsigned iphi1 = iphi + 1; - - sa_push(sphere->indices, itheta0 + iphi0); - sa_push(sphere->indices, itheta0 + iphi1); - sa_push(sphere->indices, itheta1 + iphi0); - - sa_push(sphere->indices, itheta1 + iphi0); - sa_push(sphere->indices, itheta0 + iphi1); - sa_push(sphere->indices, itheta1 + iphi1); - } - } - - /* Define the indices of the polar primitives */ - FOR_EACH(itheta, 0, ntheta) { - const unsigned itheta0 = itheta * (nphi - 1); - const unsigned itheta1 = ((itheta + 1) % ntheta) * (nphi - 1); - - sa_push(sphere->indices, ntheta * (nphi - 1)); - sa_push(sphere->indices, itheta0); - sa_push(sphere->indices, itheta1); - - sa_push(sphere->indices, ntheta * (nphi - 1) + 1); - sa_push(sphere->indices, itheta1 + (nphi - 2)); - sa_push(sphere->indices, itheta0 + (nphi - 2)); - } - - /* Release the intermediary data structure */ - sa_release(cos_theta); - sa_release(sin_theta); - sa_release(cos_phi); - sa_release(sin_phi); -} - -static void -sphere_release(struct geometry* sphere) -{ - sa_release(sphere->vertices); - sa_release(sphere->indices); - sphere->vertices = NULL; - sphere->indices = NULL; + return sphere_setup_s3d_shape(&sphere, shape); } static void @@ -347,7 +211,7 @@ main(int argc, char** argv) CHECK(sschiff_device_create (NULL, &allocator, SSCHIFF_NTHREADS_DEFAULT, 1, NULL, &dev), RES_OK); - sphere_init(&sampler_ctx.geometry, 64); + geometry_init_sphere(&sampler_ctx.geometry, 64); sampler_ctx.wavelength = wlen; sampler_ctx.relative_real_refractive_index = 1.1; @@ -485,7 +349,7 @@ main(int argc, char** argv) CHECK(sschiff_device_ref_put(dev), RES_OK); CHECK(ssp_rng_ref_put(rng), RES_OK); - sphere_release(&sampler_ctx.geometry); + geometry_release(&sampler_ctx.geometry); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); CHECK(mem_allocated_size(), 0); diff --git a/src/test_sschiff_utils.h b/src/test_sschiff_utils.h @@ -29,8 +29,305 @@ #ifndef TEST_SSCHIFF_UTILS_H #define TEST_SSCHIFF_UTILS_H +#include <rsys/float3.h> +#include <rsys/stretchy_array.h> #include <rsys/mem_allocator.h> +#include <star/s3d.h> + +/******************************************************************************* + * Helper geometry data structure + ******************************************************************************/ +struct geometry { + float* vertices; /* List of float[3] */ + unsigned* indices; /* List of unsigned[3] */ +}; + +static INLINE void +geometry_init_sphere(struct geometry* sphere, const unsigned ntheta) +{ + const unsigned nphi = (unsigned)(((double)ntheta + 0.5) / 2.0); + const double step_theta = 2*PI / (double)ntheta; + const double step_phi = PI / (double)nphi; + double* cos_theta = NULL; + double* sin_theta = NULL; + double* cos_phi = NULL; + double* sin_phi = NULL; + unsigned itheta, iphi; + + NCHECK(sphere, NULL); + NCHECK(ntheta, 0); + + sphere->vertices = NULL; + sphere->indices = NULL; + + /* Precompute the cosine/sinus of the theta/phi angles */ + FOR_EACH(itheta, 0, ntheta) { + const double theta = -PI + (double)itheta * step_theta; + sa_push(cos_theta, cos(theta)); + sa_push(sin_theta, sin(theta)); + } + FOR_EACH(iphi, 1, nphi) { + const double phi = -PI/2 + (double)iphi * step_phi; + sa_push(cos_phi, cos(phi)); + sa_push(sin_phi, sin(phi)); + } + /* Compute the contour vertices */ + FOR_EACH(itheta, 0, ntheta) { + FOR_EACH(iphi, 0, nphi-1) { + sa_push(sphere->vertices, (float)(cos_theta[itheta]*cos_phi[iphi])); + sa_push(sphere->vertices, (float)(sin_theta[itheta]*cos_phi[iphi])); + sa_push(sphere->vertices, (float)sin_phi[iphi]); + } + } + /* Compute the polar vertices */ + f3(sa_add(sphere->vertices, 3), 0.f, 0.f,-1.f); + f3(sa_add(sphere->vertices, 3), 0.f, 0.f, 1.f); + + /* Define the indices of the contour primitives */ + FOR_EACH(itheta, 0, ntheta) { + const unsigned itheta0 = itheta * (nphi - 1); + const unsigned itheta1 = ((itheta + 1) % ntheta) * (nphi - 1); + FOR_EACH(iphi, 0, nphi-2) { + const unsigned iphi0 = iphi + 0; + const unsigned iphi1 = iphi + 1; + + sa_push(sphere->indices, itheta0 + iphi0); + sa_push(sphere->indices, itheta0 + iphi1); + sa_push(sphere->indices, itheta1 + iphi0); + + sa_push(sphere->indices, itheta1 + iphi0); + sa_push(sphere->indices, itheta0 + iphi1); + sa_push(sphere->indices, itheta1 + iphi1); + } + } + + /* Define the indices of the polar primitives */ + FOR_EACH(itheta, 0, ntheta) { + const unsigned itheta0 = itheta * (nphi - 1); + const unsigned itheta1 = ((itheta + 1) % ntheta) * (nphi - 1); + + sa_push(sphere->indices, ntheta * (nphi - 1)); + sa_push(sphere->indices, itheta0); + sa_push(sphere->indices, itheta1); + + sa_push(sphere->indices, ntheta * (nphi - 1) + 1); + sa_push(sphere->indices, itheta1 + (nphi - 2)); + sa_push(sphere->indices, itheta0 + (nphi - 2)); + } + + /* Release the intermediary data structure */ + sa_release(cos_theta); + sa_release(sin_theta); + sa_release(cos_phi); + sa_release(sin_phi); +} + +static INLINE void +geometry_init_cylinder(struct geometry* geometry, const unsigned nsteps) +{ + const double step = 2*PI / (double)nsteps; + unsigned istep; + + NCHECK(geometry, NULL); + NCHECK(nsteps, 0); + + geometry->vertices = NULL; + geometry->indices = NULL; + + /* Generate the vertex coordinates */ + FOR_EACH(istep, 0, nsteps) { + const float theta = (float)(istep * step); + const float x = (float)cos(theta); + const float y = (float)sin(theta); + f3(sa_add(geometry->vertices, 3), x, y, -1.f); + f3(sa_add(geometry->vertices, 3), x, y, 0.f); + } + + /* "Polar" vertices */ + f3(sa_add(geometry->vertices, 3), 0.f, 0.f, -1.f); + f3(sa_add(geometry->vertices, 3), 0.f, 0.f, 0.f); + + /* Contour primitives */ + FOR_EACH(istep, 0, nsteps) { + const unsigned id = istep * 2; + unsigned* iprim; + + iprim = sa_add(geometry->indices, 3); + iprim[0] = (id + 0); + iprim[1] = (id + 1); + iprim[2] = (id + 2) % (nsteps*2); + + iprim = sa_add(geometry->indices, 3); + iprim[0] = (id + 2) % (nsteps*2); + iprim[1] = (id + 1); + iprim[2] = (id + 3) % (nsteps*2); + } + + /* Cap primitives */ + FOR_EACH(istep, 0, nsteps) { + const unsigned id = istep * 2; + unsigned* iprim; + + iprim = sa_add(geometry->indices, 3); + iprim[0] = (nsteps * 2); + iprim[1] = (id + 0); + iprim[2] = (id + 2) % (nsteps*2); + + iprim = sa_add(geometry->indices, 3); + iprim[0] = (nsteps * 2) + 1; + iprim[1] = (id + 3) % (nsteps*2); + iprim[2] = (id + 1); + } + +} + +static INLINE void +geometry_release(struct geometry* geometry) +{ + NCHECK(geometry, NULL); + sa_release(geometry->vertices); + sa_release(geometry->indices); + geometry->vertices = NULL; + geometry->indices = NULL; +} + +static INLINE void +geometry_dump(struct geometry* geom, FILE* file) +{ + size_t i; + NCHECK(geom, NULL); + NCHECK(file, NULL); + + CHECK(sa_size(geom->vertices)%3, 0); /* Ensure 3D position */ + CHECK(sa_size(geom->indices)%3, 0); /* Ensure triangular primitives */ + + FOR_EACH(i, 0, sa_size(geom->vertices)/3) { + fprintf(file, "v %f %f %f\n", + geom->vertices[i*3+0], + geom->vertices[i*3+1], + geom->vertices[i*3+2]); + } + FOR_EACH(i, 0, sa_size(geom->indices)/3) { + fprintf(file, "f %d %d %d\n", + geom->indices[i*3+0] + 1, + geom->indices[i*3+1] + 1, + geom->indices[i*3+2] + 1); + } +} + +/******************************************************************************* + * Cylinder shape + ******************************************************************************/ +struct cylinder { + struct geometry* geometry; + float radius; + float height; +}; + +static INLINE void +cylinder_get_indices(const unsigned itri, unsigned ids[3], void* ctx) +{ + struct cylinder* cylinder = ctx; + const size_t i = itri * 3; + + CHECK(sa_size(cylinder->geometry->indices) % 3, 0); + CHECK(itri < sa_size(cylinder->geometry->indices) / 3, 1); + ids[0] = cylinder->geometry->indices[i + 0]; + ids[1] = cylinder->geometry->indices[i + 1]; + ids[2] = cylinder->geometry->indices[i + 2]; +} + +static INLINE void +cylinder_get_position(const unsigned ivert, float vertex[3], void* ctx) +{ + struct cylinder* cylinder = ctx; + const size_t i = ivert * 3; + + CHECK(sa_size(cylinder->geometry->vertices) % 3, 0); + CHECK(ivert < sa_size(cylinder->geometry->vertices) / 3, 1); + vertex[0] = cylinder->geometry->vertices[i + 0] * cylinder->radius; + vertex[1] = cylinder->geometry->vertices[i + 1] * cylinder->radius; + vertex[2] = cylinder->geometry->vertices[i + 2] * cylinder->height; +} + +static INLINE res_T +cylinder_setup_s3d_shape(struct cylinder* cylinder, struct s3d_shape* shape) +{ + struct s3d_vertex_data attrib; + size_t nverts, nprims; + + NCHECK(cylinder, NULL); + NCHECK(shape, NULL); + + attrib.usage = S3D_POSITION; + attrib.type = S3D_FLOAT3; + attrib.get = cylinder_get_position; + + nverts = sa_size(cylinder->geometry->vertices) / 3/*#coords*/; + nprims = sa_size(cylinder->geometry->indices) / 3/*#indices per prim*/; + + return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, + cylinder_get_indices, (unsigned)nverts, &attrib, 1, cylinder); +} + +/******************************************************************************* + * Spherical shape + ******************************************************************************/ +struct sphere { + struct geometry* geometry; + float radius; +}; + +static INLINE void +sphere_get_indices(const unsigned itri, unsigned ids[3], void* ctx) +{ + struct sphere* sphere = ctx; + const size_t i = itri * 3; + + CHECK(sa_size(sphere->geometry->indices) % 3, 0); + CHECK(itri < sa_size(sphere->geometry->indices) / 3, 1); + ids[0] = sphere->geometry->indices[i + 0]; + ids[1] = sphere->geometry->indices[i + 1]; + ids[2] = sphere->geometry->indices[i + 2]; +} + +static INLINE void +sphere_get_position(const unsigned ivert, float vertex[3], void* ctx) +{ + struct sphere* sphere = ctx; + const size_t i = ivert * 3; + + CHECK(sa_size(sphere->geometry->vertices) % 3, 0); + CHECK(ivert < sa_size(sphere->geometry->vertices) / 3, 1); + vertex[0] = sphere->geometry->vertices[i + 0] * sphere->radius; + vertex[1] = sphere->geometry->vertices[i + 1] * sphere->radius; + vertex[2] = sphere->geometry->vertices[i + 2] * sphere->radius; +} + +static INLINE res_T +sphere_setup_s3d_shape(struct sphere* sphere, struct s3d_shape* shape) +{ + struct s3d_vertex_data attrib; + size_t nverts, nprims; + + NCHECK(sphere, NULL); + NCHECK(shape, NULL); + + attrib.usage = S3D_POSITION; + attrib.type = S3D_FLOAT3; + attrib.get = sphere_get_position; + + nverts = sa_size(sphere->geometry->vertices) / 3/*#coords*/; + nprims = sa_size(sphere->geometry->indices) / 3/*#indices per prim*/; + + return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, + sphere_get_indices, (unsigned)nverts, &attrib, 1, sphere); +} + +/******************************************************************************* + * Miscellaneous functions + ******************************************************************************/ static void check_memory_allocator(struct mem_allocator* allocator) {