schiff

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

commit 616515bb47336481bcbf33bb655537dacddbdaba
parent e3e1b6f775c011a498afa32e2a401cca3341c3e3
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 28 Mar 2016 16:37:04 +0200

Add the internal helical pipe mesh

Diffstat:
Msrc/schiff.c | 3---
Msrc/schiff_args.c | 32++++++++++++++++++++++++++++++++
Msrc/schiff_geometry.c | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/schiff_geometry.h | 21+++++++++++++++++++++
Msrc/schiff_mesh.c | 212+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/schiff_mesh.h | 20++++++++++++++++++--
6 files changed, 327 insertions(+), 39 deletions(-)

diff --git a/src/schiff.c b/src/schiff.c @@ -278,9 +278,6 @@ main(int argc, char** argv) int err = 0; res_T res; - schiff_mesh_init_helicoid(NULL, NULL); - exit(0); - res = schiff_args_init(&args, argc, argv); if(res != RES_OK) goto error; if(!args.ngeoms_dump && !args.wavelengths) goto exit; diff --git a/src/schiff_args.c b/src/schiff_args.c @@ -117,6 +117,12 @@ geometry_release(struct schiff_geometry* geom) case SCHIFF_CYLINDER_AS_SPHERE: param_release(&geom->data.cylinder.radius); break; + case SCHIFF_HELICAL_PIPE: + param_release(&geom->data.helical_pipe.pitch); + param_release(&geom->data.helical_pipe.height); + param_release(&geom->data.helical_pipe.helicoid_radius); + param_release(&geom->data.helical_pipe.circle_radius); + break; case SCHIFF_SPHERE: param_release(&geom->data.sphere.radius); break; @@ -859,6 +865,30 @@ parse_yaml_cylinder } static res_T +parse_yaml_helical_pipe + (const char* filename, + yaml_document_t* doc, + const yaml_node_t* node, + struct schiff_geometry* geom, + double* geom_proba) +{ + ASSERT(filename && doc && node && geom && geom_proba); + geom->type = SCHIFF_HELICAL_PIPE; + geom->data.helical_pipe.nslices_helicoid = 32; + geom->data.helical_pipe.nslices_circle = 16; + geom->data.helical_pipe.pitch.data.constant = 1; + geom->data.helical_pipe.height.data.constant = 0.6; + geom->data.helical_pipe.helicoid_radius.data.constant = 3; + geom->data.helical_pipe.circle_radius.data.constant = 1; + geom->data.helical_pipe.pitch.distribution = SCHIFF_PARAM_CONSTANT; + geom->data.helical_pipe.height.distribution = SCHIFF_PARAM_CONSTANT; + geom->data.helical_pipe.helicoid_radius.distribution = SCHIFF_PARAM_CONSTANT; + geom->data.helical_pipe.circle_radius.distribution = SCHIFF_PARAM_CONSTANT; + *geom_proba = 1; + return RES_OK; +} + +static res_T parse_yaml_sphere (const char* filename, yaml_document_t* doc, @@ -1070,6 +1100,8 @@ parse_yaml_geom_distrib res = parse_yaml_cylinder(filename, doc, val, geom, proba); } else if(!strcmp((char*)key->data.scalar.value, "sphere")) { res = parse_yaml_sphere(filename, doc, val, geom, proba); + } else if(!strcmp((char*)key->data.scalar.value, "helical_pipe")) { + res = parse_yaml_helical_pipe(filename, doc, val, geom, proba); } else if(!strcmp((char*)key->data.scalar.value, "supershape")) { res = parse_yaml_supershape(filename, doc, val, geom, proba); } else { diff --git a/src/schiff_geometry.c b/src/schiff_geometry.c @@ -49,6 +49,14 @@ struct cylinder_context { float height; }; +/* 3D Context of an helical pipe */ +struct helical_pipe_context { + double helicoid_radius; + double circle_radius; + double pitch; + double height; +}; + /* 3D Context of the supershape geometry */ struct supershape_context { double formulas[2][6]; @@ -69,6 +77,7 @@ struct mesh_context { union { struct ellipsoid_context ellipsoid; struct cylinder_context cylinder; + struct helical_pipe_context helical_pipe; struct sphere_context sphere; struct supershape_context supershape; } data; @@ -193,6 +202,14 @@ geometry_get_indices(const unsigned itri, unsigned ids[3], void* ctx) } static void +geometry_get_position(const unsigned ivert, float vertex[3], void* ctx) +{ + struct mesh_context* mesh_ctx = ctx; + ASSERT(ctx); + schiff_mesh_get_cartesian_position(mesh_ctx->mesh, ivert, vertex); +} + +static void ellipsoid_get_position(const unsigned ivert, float vertex[3], void* ctx) { struct mesh_context* mesh_ctx = ctx; @@ -368,6 +385,52 @@ geometry_sample_cylinder } static res_T +geometry_sample_helical_pipe + (struct ssp_rng* rng, + const struct schiff_geometry* geom, + struct schiff_mesh* mesh, + struct s3d_shape* shape) +{ + const struct schiff_helical_pipe* helical_pipe; + struct mesh_context mesh_ctx; + struct s3d_vertex_data attrib; + size_t nprims; + size_t nverts; + double pitch; + double height; + double hradius; + double cradius; + res_T res = RES_OK; + ASSERT(geom && geom->type == SCHIFF_HELICAL_PIPE); + + helical_pipe = &geom->data.helical_pipe; + + /* Sample the helical pipe attributes */ + hradius = eval_param(&helical_pipe->helicoid_radius, rng); + cradius = eval_param(&helical_pipe->circle_radius, rng); + pitch = eval_param(&helical_pipe->pitch, rng); + height = eval_param(&helical_pipe->height, rng); + + /* Setup the mesh vertices */ + res = schiff_mesh_setup_helical_pipe(mesh, pitch, height, hradius, cradius, + helical_pipe->nslices_helicoid, helical_pipe->nslices_circle); + if(res != RES_OK) return res; + + mesh_ctx.mesh = mesh; + mesh_ctx.type = SCHIFF_HELICAL_PIPE; + + attrib.usage = S3D_POSITION; + attrib.type = S3D_FLOAT3; + attrib.get = geometry_get_position; + + nverts = darray_float_size_get(&mesh->vertices.cartesian) / 3/*#coords*/; + nprims = darray_uint_size_get(&mesh->indices) / 3/*#indices per prim*/; + + return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, + geometry_get_indices, (unsigned)nverts, &attrib, 1, &mesh_ctx); +} + +static res_T geometry_sample_sphere (struct ssp_rng* rng, const struct schiff_geometry* geom, @@ -378,7 +441,7 @@ geometry_sample_sphere struct mesh_context mesh_ctx; struct s3d_vertex_data attrib; size_t nverts, nprims; - ASSERT(rng && geom && mesh && shape); + ASSERT(geom && mesh && shape); ASSERT(geom->type == SCHIFF_SPHERE); sphere = &geom->data.sphere; @@ -409,7 +472,7 @@ geometry_sample_supershape struct s3d_vertex_data attrib; size_t nverts, nprims; int iform, iattr; - ASSERT(rng && geom && mesh && shape); + ASSERT(geom && mesh && shape); ASSERT(geom->type == SCHIFF_SUPERSHAPE); sshape = &geom->data.supershape; @@ -441,7 +504,7 @@ geometry_sample { struct geometry_distribution_context* distrib = ctx; const struct schiff_geometry* geom; - const struct schiff_mesh* mesh; + struct schiff_mesh* mesh; size_t isamp; res_T res = RES_OK; ASSERT(rng && shape && ctx); @@ -459,6 +522,9 @@ geometry_sample case SCHIFF_CYLINDER_AS_SPHERE: res = geometry_sample_cylinder(rng, geom, mesh, shape); break; + case SCHIFF_HELICAL_PIPE: + res = geometry_sample_helical_pipe(rng, geom, mesh, shape); + break; case SCHIFF_SPHERE: res = geometry_sample_sphere(rng, geom, mesh, shape); break; @@ -556,6 +622,12 @@ schiff_geometry_distribution_init res = schiff_mesh_init_cylinder(&mem_default_allocator, &ctx->meshes[i], geoms[i].data.cylinder.nslices); break; + case SCHIFF_HELICAL_PIPE: + res = schiff_mesh_init_helical_pipe + (&mem_default_allocator, &ctx->meshes[i], + geoms[i].data.helical_pipe.nslices_helicoid, + geoms[i].data.helical_pipe.nslices_circle); + break; case SCHIFF_SPHERE: res = schiff_mesh_init_sphere(&mem_default_allocator, &ctx->meshes[i], geoms[i].data.sphere.nslices); diff --git a/src/schiff_geometry.h b/src/schiff_geometry.h @@ -43,6 +43,7 @@ enum schiff_geometry_type { SCHIFF_ELLIPSOID_AS_SPHERE,/* The ellipsoid volume is controled by a sphere */ SCHIFF_CYLINDER, SCHIFF_CYLINDER_AS_SPHERE,/* The cylinder volume is controled by a sphere */ + SCHIFF_HELICAL_PIPE, SCHIFF_SPHERE, SCHIFF_SUPERSHAPE, SCHIFF_NONE @@ -72,6 +73,25 @@ struct schiff_sphere { unsigned nslices; }; +struct schiff_helical_pipe { + struct schiff_param pitch; /* Elevation distance of a full revolution */ + struct schiff_param height; /* Total heigh of the helical pipe */ + struct schiff_param helicoid_radius; /* Radius of the helicoid */ + struct schiff_param circle_radius; /* Radius of the meridian circle */ + + unsigned nslices_helicoid; /* # Discrete steps of the helicoid */ + unsigned nslices_circle; /* # Discrete steps along 2PI */ +}; + +#define SCHIFF_HELICAL_PIPE_DEFAULT__ \ + {SCHIFF_PARAM_DEFAULT__, \ + SCHIFF_PARAM_DEFAULT__, \ + SCHIFF_PARAM_DEFAULT__, \ + SCHIFF_PARAM_DEFAULT__, \ + 128, 64} +static const struct schiff_helical_pipe SCHIFF_HELICAL_PIPE_DEFAULT = + SCHIFF_HELICAL_PIPE_DEFAULT__; + #define SCHIFF_SPHERE_DEFAULT__ {SCHIFF_PARAM_DEFAULT__, 64} static const struct schiff_sphere SCHIFF_SPHERE_DEFAULT = SCHIFF_SPHERE_DEFAULT__; @@ -116,6 +136,7 @@ struct schiff_geometry { union { struct schiff_ellipsoid ellipsoid; struct schiff_cylinder cylinder; + struct schiff_helical_pipe helical_pipe; struct schiff_sphere sphere; struct schiff_supershape supershape; } data; diff --git a/src/schiff_mesh.c b/src/schiff_mesh.c @@ -17,6 +17,7 @@ #include <rsys/float2.h> #include <rsys/float3.h> +#include <rsys/stretchy_array.h> /******************************************************************************* * Helper functions @@ -247,7 +248,7 @@ schiff_mesh_init_cylinder darray_uint_init(allocator, &cylinder->indices); nverts = nsteps*2/* #contour verts */ + 2/* #polar verts */; - ntris = nsteps*2/* #contour tris */ + 2*nsteps/* #caop tris */; + ntris = nsteps*2/* #contour tris */ + 2*nsteps/* #cap tris */; res = darray_float_resize(&cylinder->vertices.cartesian, nverts*3/*#coords*/); if(res != RES_OK) goto error; @@ -305,44 +306,193 @@ error: goto exit; } -#include <rsys/float33.h> res_T -schiff_mesh_init_helicoid +schiff_mesh_init_helical_pipe (struct mem_allocator* allocator, - struct schiff_mesh* mesh) + struct schiff_mesh* helical_pipe, + const unsigned nsteps_helicoid, + const unsigned nsteps_circle) + +{ + unsigned* indices; + unsigned* bottom_cap; + unsigned* top_cap; + size_t ihelicoid, icircle; + size_t nverts, ntris; + size_t ibottom_cap_index, itop_cap_index; + size_t ibottom_cap_vertex, itop_cap_vertex; + size_t ilast_meridian_vertex; + res_T res; + ASSERT(allocator && helical_pipe && nsteps_helicoid>=2 && nsteps_circle>=4); + + helical_pipe->coordinates = SCHIFF_CARTESIAN; + darray_float_init(allocator, &helical_pipe->vertices.cartesian); + darray_uint_init(allocator, &helical_pipe->indices); + + nverts = (nsteps_helicoid+1)*nsteps_circle/*#contour*/ + 2/*#cap*/; + ntris = (nsteps_helicoid)*nsteps_circle*2/*#contour*/ + 2*nsteps_circle/*#cap*/; + + res = darray_float_resize(&helical_pipe->vertices.cartesian, nverts*3/*#coords*/); + if(res != RES_OK) goto error; + res = darray_uint_resize(&helical_pipe->indices, ntris*3/*#indices per tri*/); + if(res != RES_OK) goto error; + + indices = darray_uint_data_get(&helical_pipe->indices); + + /* Setup the indices toward the contour primitives */ + FOR_EACH(ihelicoid, 0, nsteps_helicoid) { + /* Offset toward the first index of the current meridian */ + const size_t offset = ihelicoid * nsteps_circle; + + FOR_EACH(icircle, 0, nsteps_circle) { + size_t prim_ids[4]; + const size_t id = icircle + offset; + unsigned* iprim = indices + id*3/*#ids per prim*/*2/*#prims per step*/; + + /* Indices of the quad */ + prim_ids[0] = icircle + offset; + prim_ids[1] = icircle + nsteps_circle + offset; + prim_ids[2] = (icircle + 1) % nsteps_circle + nsteps_circle + offset; + prim_ids[3] = (icircle + 1) % nsteps_circle + offset; + /* First triangle of the quad */ + iprim[0] = (unsigned)prim_ids[0]; + iprim[1] = (unsigned)prim_ids[3]; + iprim[2] = (unsigned)prim_ids[1]; + /* Second triangule of the quad */ + iprim[3] = (unsigned)prim_ids[1]; + iprim[4] = (unsigned)prim_ids[3]; + iprim[5] = (unsigned)prim_ids[2]; + } + } + + /* Define the index of the cap vertices */ + ibottom_cap_vertex = nverts - 2; /* Index toward the bottom cap vertex */ + itop_cap_vertex = nverts - 1; /* Index toward the top cap vertex */ + + /* Index of the first vertex of the last meridian circle */ + ilast_meridian_vertex = nsteps_helicoid * nsteps_circle; + + ibottom_cap_index = /* Index of the 1st bottom cap index */ + nsteps_helicoid + * nsteps_circle + * 2 /*#prims per step*/ + * 3 /*#ids per prim*/; + itop_cap_index = /* Index of the 1st top cap index */ + ibottom_cap_index + + nsteps_circle * 3/*# ids per primitive */; + + bottom_cap = indices + ibottom_cap_index ; + top_cap = indices + itop_cap_index; + + FOR_EACH(icircle, 0, nsteps_circle) { + const size_t id = icircle * 3/*#ids per prim*/; + + bottom_cap[id + 0] = (unsigned)icircle; + bottom_cap[id + 1] = (unsigned)ibottom_cap_vertex; + bottom_cap[id + 2] = (unsigned)((icircle + 1) % nsteps_circle); + + top_cap[id + 0] = (unsigned)((icircle+1)%nsteps_circle + ilast_meridian_vertex); + top_cap[id + 1] = (unsigned)itop_cap_vertex; + top_cap[id + 2] = (unsigned)(icircle + ilast_meridian_vertex); + } + +exit: + return res; +error: + schiff_mesh_release(helical_pipe); + goto exit; +} + +res_T +schiff_mesh_setup_helical_pipe + (struct schiff_mesh* mesh, + const double pitch, + const double height, + const double hradius, /* Helicoid radius */ + const double cradius, /* Circle radius */ + const unsigned nsteps_helicoid, + const unsigned nsteps_circle) { - const double height = 0.7; - const double height_total = 3; - const double c = height / 2*PI; - const double phi_max = height_total * 2*PI / height; - const size_t circle_nsteps = 64; - const double circle_step = 2*PI / (double)circle_nsteps; - const double circle_radius = 0.5; - const size_t helicoid_nsteps = 256; - const double helicoid_step = phi_max / (double)helicoid_nsteps; - const double helicoid_radius = 1.0; - size_t icircle, ihelicoid; - /*ASSERT(allocator && mesh);*/ - - FOR_EACH(ihelicoid, 0, helicoid_nsteps) { - const double phi = (double)ihelicoid * helicoid_step; + double* meridian = NULL; + float* vertices; + double c; + double phi_max; + double step_helicoid, step_circle; + double rcp_sqrt_hradius2_add_c2; /* Precomputed value */ + size_t ihelicoid, icircle; + size_t icoord, icoord_top, icoord_bottom; + res_T res = RES_OK; + + ASSERT(mesh && pitch > 0 && height > 0 && hradius > 0 && cradius > 0); + ASSERT(mesh->coordinates == SCHIFF_CARTESIAN); + ASSERT(nsteps_helicoid * nsteps_circle * 2 * 3 + nsteps_circle*3*2/*cap*/ + == darray_uint_size_get(&mesh->indices)); + ASSERT((nsteps_helicoid+1) * nsteps_circle * 3 + 2*3/*cap*/ + == darray_float_size_get(&mesh->vertices.cartesian)); + + if(!sa_add(meridian, nsteps_circle * 3/*#coords per vertex*/)) { + res = RES_MEM_ERR; + goto error; + } + + c = pitch / 2*PI; + phi_max = height * 2*PI / pitch; + step_helicoid = phi_max / (double)nsteps_helicoid; + step_circle = 2*PI / (double)nsteps_circle; + rcp_sqrt_hradius2_add_c2 = 1.0 / sqrt(hradius*hradius + c*c); + + /* Compute the meridian positions */ + FOR_EACH(icircle, 0, nsteps_circle) { + const double theta = (double)icircle * step_circle; + const double cos_theta = cos(theta); + const double sin_theta = sin(theta); + const size_t id = icircle *3; + + meridian[id + 0] = cradius * cos_theta + hradius; + meridian[id + 1] = -cradius * c * rcp_sqrt_hradius2_add_c2 * sin_theta; + meridian[id + 2] = cradius*hradius * rcp_sqrt_hradius2_add_c2 * sin_theta; + } + + vertices = darray_float_data_get(&mesh->vertices.cartesian); + icoord = 0; + icoord_bottom = + (nsteps_helicoid + 1) + * nsteps_circle + * 3/*#coords per vertex*/; + icoord_top = icoord_bottom + 3/*#coords per vertex */; + + FOR_EACH(ihelicoid, 0, nsteps_helicoid + 1) { + const double phi = (double)ihelicoid * step_helicoid; const double cos_phi = cos(phi); const double sin_phi = sin(phi); - FOR_EACH(icircle, 0, circle_nsteps) { - double x, y, z; - const double theta = (double)icircle * circle_step; - const double circle_x = circle_radius*cos(theta) + helicoid_radius; - const double circle_y = circle_radius*sin(theta) + helicoid_radius; - - x = circle_x * cos_phi; - y = circle_x * sin_phi; - z = circle_y + c*phi; - /* TODO rotate the x, y and z coordinates with respect to the helocoid - * slope */ + FOR_EACH(icircle, 0, nsteps_circle) { + const double* pos = meridian + icircle*3; + vertices[icoord + 0] = (float)(pos[0]*cos_phi - pos[1]*sin_phi); + vertices[icoord + 1] = (float)(pos[0]*sin_phi + pos[1]*cos_phi); + vertices[icoord + 2] = (float)(pos[2] + c * phi); + icoord += 3; + } + + /* Top cap vertex */ + if(ihelicoid == 0) { + vertices[icoord_bottom + 0] = (float)(hradius * cos_phi); + vertices[icoord_bottom + 1] = (float)(hradius * sin_phi); + vertices[icoord_bottom + 2] = (float)(c*phi); + + /* Bottom cap vertex */ + } else if(ihelicoid == nsteps_helicoid) { + vertices[icoord_top + 0] = (float)(hradius * cos_phi); + vertices[icoord_top + 1] = (float)(hradius * sin_phi); + vertices[icoord_top + 2] = (float)(c * phi); } } - return RES_OK; + +exit: + if(meridian) sa_release(meridian); + return res; +error: + goto exit; } void diff --git a/src/schiff_mesh.h b/src/schiff_mesh.h @@ -64,10 +64,26 @@ schiff_mesh_init_cylinder struct schiff_mesh* mesh, const unsigned nslices); +/* Initialise the indices of the helical pipe. The vertices are still not + * defined. Use the schiff_mesh_setup_helical_pipe to define these data */ extern LOCAL_SYM res_T -schiff_mesh_init_helicoid +schiff_mesh_init_helical_pipe (struct mem_allocator* allocator, - struct schiff_mesh* mesh); + struct schiff_mesh* mesh, + const unsigned nsteps_helicoid, + const unsigned nsteps_circle); + +extern LOCAL_SYM res_T +schiff_mesh_setup_helical_pipe + (struct schiff_mesh* mesh, + const double pitch, + const double height, + const double radius_helicoid, + const double radius_circle, + /* The following attribs are assumed to be equal to attributes used by the + * init function */ + const unsigned nsteps_helicoid, + const unsigned nsteps_circle); extern LOCAL_SYM void schiff_mesh_release