schiff

Estimate the radiative properties of soft particless
git clone git://git.meso-star.com/schiff.git
Log | Files | Refs | README | LICENSE

commit 2d88b9297ff2e0b60079e844c4f24306a7c50e14
parent 6bcdc78bd3d4a622aadb501e95808c34c3659493
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon,  9 Nov 2015 09:50:25 +0100

Optimise the generation of the super shape mesh

The sinus and cosine of the theta/phi angles are precomputed and stored
into the mesh and indexed by the indices of the theta/phi angles.

Diffstat:
Msrc/schiff_geometry.c | 24+++++++++---------------
Msrc/schiff_mesh.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/schiff_mesh.h | 40++++++++++++++++++++++++++++------------
3 files changed, 112 insertions(+), 69 deletions(-)

diff --git a/src/schiff_geometry.c b/src/schiff_geometry.c @@ -141,9 +141,7 @@ static void super_shape_get_position(const unsigned ivert, float vertex[3], void* ctx) { struct geometry_context* geom = ctx; - float angles[2]; - double cos_angles[2]; - double sin_angles[2]; + struct sin_cos angles[2]; double uv[2]; int iform; ASSERT(geom && geom->type == SCHIFF_SUPER_SHAPE); @@ -154,21 +152,17 @@ super_shape_get_position(const unsigned ivert, float vertex[3], void* ctx) double m, k, g; double* form = geom->data.super_shape.formulas[iform]; - m = cos(form[M] * angles[iform] / 4.0); + m = cos(form[M] * angles[iform].angle / 4.0); m = fabs(m) / form[A]; - k = sin(form[M] * angles[iform] / 4.0); + k = sin(form[M] * angles[iform].angle / 4.0); k = fabs(k) / form[B]; g = pow(m, form[N1]) + pow(k, form[N2]); uv[iform] = pow(g, (-1.0/form[N0])); - - cos_angles[iform] = cos(angles[iform]); - sin_angles[iform] = sin(angles[iform]); } - vertex[0] = (float)(uv[0] * cos_angles[0] * uv[1] * cos_angles[1]); - vertex[1] = (float)(uv[0] * sin_angles[0] * uv[1] * cos_angles[1]); - vertex[2] = (float)(uv[1] * sin_angles[1]); - + vertex[0] = (float)(uv[0] * angles[0].cosine * uv[1] * angles[1].cosine); + vertex[1] = (float)(uv[0] * angles[0].sinus * uv[1] * angles[1].cosine); + vertex[2] = (float)(uv[1] * angles[1].sinus); } static res_T @@ -202,7 +196,7 @@ geometry_sample_cylinder mtl->get_property = get_material_property; mtl->material = distrib->properties; - nverts = darray_float_size_get(&distrib->mesh->vertices) / 3/*#coords*/; + nverts = darray_float_size_get(&distrib->mesh->vertices.cartesian) / 3/*#coords*/; nprims = darray_uint_size_get(&distrib->mesh->indices) / 3/*#indices per prim*/; return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, @@ -235,7 +229,7 @@ geometry_sample_sphere mtl->get_property = get_material_property; mtl->material = distrib->properties; - nverts = darray_float_size_get(&distrib->mesh->vertices) / 3/*#coords*/; + nverts = darray_float_size_get(&distrib->mesh->vertices.cartesian) / 3/*#coords*/; nprims = darray_uint_size_get(&distrib->mesh->indices) / 3/*#indices*/; return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, @@ -287,7 +281,7 @@ geometry_sample_super_shape mtl->get_property = get_material_property; mtl->material = distrib->properties; - nverts = darray_float_size_get(&distrib->mesh->vertices) / 2/*#theta/phi*/; + nverts = darray_uint_size_get(&distrib->mesh->vertices.polar) / 2/*#theta/phi*/; nprims = darray_uint_size_get(&distrib->mesh->indices) / 3/*#indices*/; return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, diff --git a/src/schiff_mesh.c b/src/schiff_mesh.c @@ -31,12 +31,6 @@ #include <rsys/float2.h> #include <rsys/float3.h> -struct sin_cos { double sinus, cosine; }; - -#define DARRAY_NAME sincos -#define DARRAY_DATA struct sin_cos -#include <rsys/dynamic_array.h> - /******************************************************************************* * Helper functions ******************************************************************************/ @@ -98,8 +92,6 @@ schiff_mesh_init_sphere const unsigned nphis = (unsigned)(((double)nthetas + 0.5) / 2.0); const double step_theta = 2*PI / (double)nthetas; const double step_phi = PI / (double)nphis; - struct darray_sincos sincos_thetas; - struct darray_sincos sincos_phis; size_t nverts; size_t ntris; size_t i; @@ -108,56 +100,59 @@ schiff_mesh_init_sphere ASSERT(allocator && sphere && nthetas); sphere->coordinates = SCHIFF_CARTESIAN; - darray_float_init(allocator, &sphere->vertices); + darray_float_init(allocator, &sphere->vertices.cartesian); darray_uint_init(allocator, &sphere->indices); - darray_sincos_init(allocator, &sincos_thetas); - darray_sincos_init(allocator, &sincos_phis); + darray_sincos_init(allocator, &sphere->thetas); + darray_sincos_init(allocator, &sphere->phis); nverts = nthetas*(nphis-1)/* #contour verts */ + 2/* polar verts */; ntris = 2*nthetas*(nphis-2)/* #contour tris */ + 2*nthetas/* #polar tris */; - res = darray_float_resize(&sphere->vertices, nverts * 3/*#coords per vert*/); + res = darray_float_resize(&sphere->vertices.cartesian, nverts * 3/*#coords*/); if(res != RES_OK) goto error; res = darray_uint_resize(&sphere->indices, ntris * 3/*#indices per tri*/); if(res != RES_OK) goto error; - res = darray_sincos_resize(&sincos_thetas, nthetas); + res = darray_sincos_resize(&sphere->thetas, nthetas); if(res != RES_OK) goto error; - res = darray_sincos_resize(&sincos_phis, nphis); + res = darray_sincos_resize(&sphere->phis, nphis); if(res != RES_OK) goto error; /* Precompute the cosine/sinus of the theta/phi angles */ FOR_EACH(itheta, 0, nthetas) { const double theta = -PI + (double)itheta * step_theta; - darray_sincos_data_get(&sincos_thetas)[itheta].sinus = sin(theta); - darray_sincos_data_get(&sincos_thetas)[itheta].cosine = cos(theta); + darray_sincos_data_get(&sphere->thetas)[itheta].angle = theta; + darray_sincos_data_get(&sphere->thetas)[itheta].sinus = (float)sin(theta); + darray_sincos_data_get(&sphere->thetas)[itheta].cosine = (float)cos(theta); } FOR_EACH(iphi, 0, nphis-1) { const double phi = -PI/2 + (double)(iphi + 1) * step_phi; - darray_sincos_data_get(&sincos_phis)[iphi].sinus = sin(phi); - darray_sincos_data_get(&sincos_phis)[iphi].cosine = cos(phi); + darray_sincos_data_get(&sphere->phis)[iphi].angle = (float)phi; + darray_sincos_data_get(&sphere->phis)[iphi].sinus = (float)sin(phi); + darray_sincos_data_get(&sphere->phis)[iphi].cosine = (float)cos(phi); } /* Build the contour vertices */ i = 0; FOR_EACH(itheta, 0, nthetas) { - const struct sin_cos* theta = darray_sincos_data_get(&sincos_thetas) + itheta; + const struct sin_cos* theta = darray_sincos_data_get(&sphere->thetas) + itheta; FOR_EACH(iphi, 0, nphis-1) { - const struct sin_cos* phi = darray_sincos_data_get(&sincos_phis) + iphi; - darray_float_data_get(&sphere->vertices)[i++] = (float)(theta->cosine * phi->cosine); - darray_float_data_get(&sphere->vertices)[i++] = (float)(theta->sinus * phi->cosine); - darray_float_data_get(&sphere->vertices)[i++] = (float)phi->sinus; + const struct sin_cos* phi = darray_sincos_data_get(&sphere->phis) + iphi; + darray_float_data_get(&sphere->vertices.cartesian)[i++] = + (float)(theta->cosine * phi->cosine); + darray_float_data_get(&sphere->vertices.cartesian)[i++] = + (float)(theta->sinus * phi->cosine); + darray_float_data_get(&sphere->vertices.cartesian)[i++] = + (float)phi->sinus; } } /* Setup polar vertices */ - f3(darray_float_data_get(&sphere->vertices) + i + 0, 0.f, 0.f,-1.f); - f3(darray_float_data_get(&sphere->vertices) + i + 3, 0.f, 0.f, 1.f); + f3(darray_float_data_get(&sphere->vertices.cartesian) + i+0, 0.f, 0.f,-1.f); + f3(darray_float_data_get(&sphere->vertices.cartesian) + i+3, 0.f, 0.f, 1.f); /* Define the indices of the sphere */ setup_sphere_indices(&sphere->indices, nthetas, nphis); exit: - darray_sincos_release(&sincos_thetas); - darray_sincos_release(&sincos_phis); return res; error: schiff_mesh_release(sphere); @@ -182,30 +177,58 @@ schiff_mesh_init_sphere_polar ASSERT(allocator && sphere && nthetas); sphere->coordinates = SCHIFF_POLAR; - darray_float_init(allocator, &sphere->vertices); + darray_uint_init(allocator, &sphere->vertices.polar); darray_uint_init(allocator, &sphere->indices); + darray_sincos_init(allocator, &sphere->thetas); + darray_sincos_init(allocator, &sphere->phis); nverts = nthetas*(nphis-1)/* #contour verts */ + 2/* polar verts */; ntris = 2*nthetas*(nphis-2)/* #contour tris */ + 2*nthetas/* #polar tris */; - res = darray_float_resize(&sphere->vertices, nverts * 2/* theta phi*/); + res = darray_uint_resize(&sphere->vertices.polar, nverts * 2/* theta phi*/); if(res != RES_OK) goto error; res = darray_uint_resize(&sphere->indices, ntris * 3/*#indices per tri*/); if(res != RES_OK) goto error; + res = darray_sincos_resize(&sphere->thetas, nthetas); + if(res != RES_OK) goto error; + res = darray_sincos_resize(&sphere->phis, nphis + 1/*Polar*/); + if(res != RES_OK) goto error; + + /* Cosine/Sinus of the theta/phi contour angles */ + FOR_EACH(itheta, 0, nthetas) { + const double theta = -PI + (double)itheta * step_theta; + darray_sincos_data_get(&sphere->thetas)[itheta].angle = theta; + darray_sincos_data_get(&sphere->thetas)[itheta].sinus = (float)sin(theta); + darray_sincos_data_get(&sphere->thetas)[itheta].cosine = (float)cos(theta); + } + FOR_EACH(iphi, 0, nphis-1) { + const double phi = -PI/2 + (double)(iphi + 1) * step_phi; + darray_sincos_data_get(&sphere->phis)[iphi].angle = (float)phi; + darray_sincos_data_get(&sphere->phis)[iphi].sinus = (float)sin(phi); + darray_sincos_data_get(&sphere->phis)[iphi].cosine = (float)cos(phi); + } + + /* Cosine/Sinus of the theta/phi polar angles */ + darray_sincos_data_get(&sphere->phis)[nphis-1].angle =-(float)PI/2; + darray_sincos_data_get(&sphere->phis)[nphis-1].sinus =-1.f; + darray_sincos_data_get(&sphere->phis)[nphis-1].cosine = 0.f; + darray_sincos_data_get(&sphere->phis)[nphis-0].angle = (float)PI/2; + darray_sincos_data_get(&sphere->phis)[nphis-0].sinus = 1.f; + darray_sincos_data_get(&sphere->phis)[nphis-0].cosine = 0.f; /* Build the contour vertices */ i = 0; FOR_EACH(itheta, 0, nthetas) { - const double theta = -PI + (double)itheta * step_theta; FOR_EACH(iphi, 0, nphis-1) { - const double phi = -PI/2 + (double)(iphi + 1) * step_phi; - darray_float_data_get(&sphere->vertices)[i++] = (float)theta; - darray_float_data_get(&sphere->vertices)[i++] = (float)phi; + darray_uint_data_get(&sphere->vertices.polar)[i++] = itheta; + darray_uint_data_get(&sphere->vertices.polar)[i++] = iphi; } } /* Setup polar vertices */ - f2(darray_float_data_get(&sphere->vertices) + i+0,-(float)PI,-(float)PI/2.0); - f2(darray_float_data_get(&sphere->vertices) + i+2, (float)PI, (float)PI/2.0); + darray_uint_data_get(&sphere->vertices.polar)[i++] = 0; + darray_uint_data_get(&sphere->vertices.polar)[i++] = nphis-1; + darray_uint_data_get(&sphere->vertices.polar)[i++] = 0; + darray_uint_data_get(&sphere->vertices.polar)[i++] = nphis-0; /* Define the indices of the sphere */ setup_sphere_indices(&sphere->indices, nthetas, nphis); @@ -231,13 +254,13 @@ schiff_mesh_init_cylinder ASSERT(allocator && cylinder && nsteps); cylinder->coordinates = SCHIFF_CARTESIAN; - darray_float_init(allocator, &cylinder->vertices); + darray_float_init(allocator, &cylinder->vertices.cartesian); darray_uint_init(allocator, &cylinder->indices); nverts = nsteps*2/* #contour verts */ + 2/* #polar verts */; ntris = nsteps*2/* #contour tris */ + 2*nsteps/* #caop tris */; - res = darray_float_resize(&cylinder->vertices, nverts*3/*#coords per vert*/); + res = darray_float_resize(&cylinder->vertices.cartesian, nverts*3/*#coords*/); if(res != RES_OK) goto error; res = darray_uint_resize(&cylinder->indices, ntris*3/*#indices per tri*/); if(res != RES_OK) goto error; @@ -247,13 +270,13 @@ schiff_mesh_init_cylinder const float theta = (float)(i* step); const float x = (float)cos(theta); const float y = (float)sin(theta); - f3(darray_float_data_get(&cylinder->vertices) + (i*2 + 0)*3, x, y, 0.f); - f3(darray_float_data_get(&cylinder->vertices) + (i*2 + 1)*3, x, y, 1.f); + f3(darray_float_data_get(&cylinder->vertices.cartesian)+(i*2+0)*3, x,y,0); + f3(darray_float_data_get(&cylinder->vertices.cartesian)+(i*2+1)*3, x,y,1); } /* "Polar" vertices */ - f3(darray_float_data_get(&cylinder->vertices) + (i*2 + 0)*3, 0.f, 0.f, 0.f); - f3(darray_float_data_get(&cylinder->vertices) + (i*2 + 1)*3, 0.f, 0.f, 1.f); + f3(darray_float_data_get(&cylinder->vertices.cartesian)+(i*2+0)*3, 0,0,0); + f3(darray_float_data_get(&cylinder->vertices.cartesian)+(i*2+1)*3, 0,0,1); /* Contour primitives */ FOR_EACH(i, 0, nsteps) { @@ -297,7 +320,17 @@ void schiff_mesh_release(struct schiff_mesh* mesh) { ASSERT(mesh); - darray_float_release(&mesh->vertices); + switch(mesh->coordinates) { + case SCHIFF_CARTESIAN: + darray_float_release(&mesh->vertices.cartesian); + break; + case SCHIFF_POLAR: + darray_uint_release(&mesh->vertices.polar); + break; + default: FATAL("Unreachable code\n"); break; + } darray_uint_release(&mesh->indices); + darray_sincos_release(&mesh->thetas); + darray_sincos_release(&mesh->phis); } diff --git a/src/schiff_mesh.h b/src/schiff_mesh.h @@ -32,15 +32,28 @@ #include <rsys/dynamic_array_float.h> #include <rsys/dynamic_array_uint.h> +struct sin_cos { double angle, sinus, cosine; }; + +#define DARRAY_NAME sincos +#define DARRAY_DATA struct sin_cos +#include <rsys/dynamic_array.h> + enum schiff_coordinates { SCHIFF_POLAR, SCHIFF_CARTESIAN }; struct schiff_mesh { - struct darray_float vertices; - struct darray_uint indices; enum schiff_coordinates coordinates; + union { + struct darray_float cartesian; + struct darray_uint polar; + } vertices; + struct darray_uint indices; + + /* Used only by polar coordinates */ + struct darray_sincos thetas; /* List of thetas, cos(theta) , sin(theta) */ + struct darray_sincos phis; /* List of phis, cos(phi), sin(phi) */ }; extern LOCAL_SYM res_T @@ -88,25 +101,28 @@ schiff_mesh_get_cartesian_position { const size_t i = ivert * 3; ASSERT(mesh && vertex && mesh->coordinates == SCHIFF_CARTESIAN); - ASSERT(darray_float_size_get(&mesh->vertices) % 3 == 0); - ASSERT(ivert < darray_float_size_get(&mesh->vertices) / 3); - vertex[0] = darray_float_data_get(&mesh->vertices)[i + 0]; - vertex[1] = darray_float_data_get(&mesh->vertices)[i + 1]; - vertex[2] = darray_float_data_get(&mesh->vertices)[i + 2]; + ASSERT(darray_float_size_get(&mesh->vertices.cartesian) % 3 == 0); + ASSERT(ivert < darray_float_size_get(&mesh->vertices.cartesian) / 3); + vertex[0] = darray_float_data_get(&mesh->vertices.cartesian)[i + 0]; + vertex[1] = darray_float_data_get(&mesh->vertices.cartesian)[i + 1]; + vertex[2] = darray_float_data_get(&mesh->vertices.cartesian)[i + 2]; } static INLINE void schiff_mesh_get_polar_position (struct schiff_mesh* mesh, const unsigned ivert, - float angles[2]) /* theta, phi */ + struct sin_cos angles[2]) { const size_t i = ivert * 2; + const unsigned* iangles; ASSERT(mesh && angles && mesh->coordinates == SCHIFF_POLAR); - ASSERT(darray_float_size_get(&mesh->vertices) % 2 == 0); - ASSERT(ivert < darray_float_size_get(&mesh->vertices) / 2); - angles[0] = darray_float_data_get(&mesh->vertices)[i + 0]; - angles[1] = darray_float_data_get(&mesh->vertices)[i + 1]; + ASSERT(darray_uint_size_get(&mesh->vertices.polar) % 2 == 0); + ASSERT(ivert < darray_uint_size_get(&mesh->vertices.polar) / 2); + + iangles = darray_uint_cdata_get(&mesh->vertices.polar) + i; + angles[0] = darray_sincos_data_get(&mesh->thetas)[iangles[0]]; + angles[1] = darray_sincos_data_get(&mesh->phis)[iangles[1]]; } #endif /* SBOX_SCHIFF_MESH_H */