star-schiff

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

commit 1a1eb57276d2d57455b34cde392dc6013935f95a
parent 1b508a1927856bc55a8aa51411881b58c30ee52f
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri,  9 Oct 2015 15:15:19 +0200

Begin the estimation of the radiative properties

Diffstat:
Msrc/sschiff.h | 11+++++++++--
Msrc/sschiff_estimator.c | 210+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 189 insertions(+), 32 deletions(-)

diff --git a/src/sschiff.h b/src/sschiff.h @@ -58,12 +58,19 @@ struct ssp_rng; struct sschiff_refractive_index { double real, imag; }; +enum sschiff_material_property { + SSCHIFF_MATERIAL_MEDIUM_REFRACTIVE_INDEX, + SSCHIFF_MATERIAL_RELATIVE_REAL_REFRACTIVE_INDEX, + SSCHIFF_MATERIAL_RELATIVE_IMAGINARY_REFRACTIVE_INDEX +}; + struct sschiff_material { /* Retrieve the refractive complex index of the material */ - void (*get_refractive_index) + void (*get_property) (void* material, const double wavelength, - struct sschiff_refractive_index* value); + const enum sschiff_material_property property, + double* value); void* material; /* Opaque user defined representation of the material */ }; diff --git a/src/sschiff_estimator.c b/src/sschiff_estimator.c @@ -26,6 +26,8 @@ * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ +#define _POSIX_C_SOURCE 200112L + #include "sschiff.h" #include "sschiff_device.h" @@ -33,12 +35,15 @@ #include <rsys/float3.h> #include <rsys/image.h> #include <rsys/logger.h> +#include <rsys/math.h> #include <rsys/mem_allocator.h> #include <rsys/stretchy_array.h> #include <star/s3d.h> #include <star/ssp.h> +#include <math.h> + #define NDIRS 1 /* # Sampled directions */ struct sschiff_estimator { @@ -49,6 +54,12 @@ struct sschiff_estimator { ref_T ref; }; +struct accum { + double weight; + double sqr_weight; + size_t naccums; +}; + /******************************************************************************* * Helper functions ******************************************************************************/ @@ -99,7 +110,7 @@ build_transform { ASSERT(pos && basis && transform); - /* The linear part of the transformamatrix is the inverse of the + /* The linear part of the transform matrix is the inverse of the * orthonormal basis (i.e. its transpose) */ f3(transform + 0, basis[0], basis[3], basis[6]); f3(transform + 3, basis[1], basis[4], basis[7]); @@ -111,8 +122,130 @@ build_transform transform[11] = -f3_dot(basis+6, pos); } +static res_T +compute_path_length + (struct s3d_scene* scn, + const struct s3d_hit* first_hit, + const float ray_org[3], + const float ray_dir[3], + double* length) +{ + float range[2] = { 0, FLT_MAX }; + struct s3d_primitive prim_from; + struct s3d_hit hit; + double len = 0; + ASSERT(scn && first_hit && ray_org && ray_dir && !S3D_HIT_NONE(first_hit)); + + range[0] = first_hit->distance; + prim_from = first_hit->prim; + do { + do { + range[0] = nextafterf(range[0], range[1]); + S3D(scene_trace_ray(scn, ray_org, ray_dir, range, &hit)); + } while(S3D_PRIMITIVE_EQ(&hit.prim, &prim_from)); /* Self-intersection */ + + if(S3D_HIT_NONE(&hit)) return RES_BAD_ARG; + + len += hit.distance; + range[0] = hit.distance; + prim_from = hit.prim; + + do { + range[0] = nextafterf(range[0], range[1]); + S3D(scene_trace_ray(scn, ray_org, ray_dir, range, &hit)); + } while(S3D_PRIMITIVE_EQ(&hit.prim, &prim_from)); /* Self-intersection */ + + range[0] = hit.distance; + prim_from = hit.prim; + + } while(!S3D_HIT_NONE(&hit)); + + *length = len * 1.e-6/* Micron to meter */; + return RES_OK; +} + +static res_T +compute_monte_carlo_weight + (struct s3d_scene* scn, + struct ssp_rng* rng, + struct sschiff_material* mtl, + const double wavelength, + const float basis[9], /* World space basis of the RT volume */ + const float pos[3], /* World space centroid of the RT volume */ + const float lower[3], /* Lower boundary of the RT volume */ + const float upper[3], /* Upper boundary of the RT volume */ + struct accum* accum) +{ + struct s3d_hit hit; + double sample[2]; + double weight; + const float range[2] = { 0, FLT_MAX }; + float axis_x[3], axis_y[3], axis_z[3]; + float plane_size[2]; + float ray_org[3]; + float org[3]; + float x[3], y[3]; + float rcp_pdf; + res_T res = RES_OK; + ASSERT(scn && rng && mtl && basis && pos && lower && upper && accum); + + f2_sub(plane_size, upper, lower); + rcp_pdf = plane_size[0] * plane_size[1]; + + /* Define the projection axis */ + f3_mulf(axis_x, basis + 0, plane_size[0] * 0.5f); + f3_mulf(axis_y, basis + 3, plane_size[1] * 0.5f); + f3_set(axis_z, basis + 6); + + /* Compute the origin of the projection plane */ + f3_add(org, pos, f3_mulf(org, axis_z, lower[2])); + + /* Uniformly sample a position onto the projection plane and use it as the + * origin of the ray to trace */ + sample[0] = ssp_rng_uniform_double(rng, -1.0, 1.0); + sample[1] = ssp_rng_uniform_double(rng, -1.0, 1.0); + f3_mulf(x, axis_x, (float)sample[0]); + f3_mulf(y, axis_y, (float)sample[1]); + f3_add(ray_org, f3_add(ray_org, x, y), org); + + S3D(scene_trace_ray(scn, ray_org, axis_z, range, &hit)); + if(S3D_HIT_NONE(&hit)) { + weight = 0.0; + } else { + double n_r, k_r; + double n_e, k_e, lambda_e; + double path_length; + + res = compute_path_length(scn, &hit, ray_org, axis_z, &path_length); + if(res != RES_OK) goto error; + + /* Retrieve material properties */ + mtl->get_property(mtl->material, wavelength, + SSCHIFF_MATERIAL_MEDIUM_REFRACTIVE_INDEX, &n_e); + mtl->get_property(mtl->material, wavelength, + SSCHIFF_MATERIAL_RELATIVE_REAL_REFRACTIVE_INDEX, &n_r); + mtl->get_property(mtl->material, wavelength, + SSCHIFF_MATERIAL_RELATIVE_IMAGINARY_REFRACTIVE_INDEX, &k_r); + + lambda_e = wavelength / n_e; + k_e = 2.0 * PI / lambda_e; + + weight = 2.0 * rcp_pdf + * (1.0 - exp(-k_e*k_r*path_length) * cos(k_e*(n_r - 1.0)*path_length)); + } + + accum->weight += weight; + accum->sqr_weight += weight * weight; + accum->naccums += 1; + +exit: + return res; +error: + goto exit; +} + /* Cast rays into the RT volume */ -static void +static INLINE void draw_thumbnail (struct s3d_scene* scn, const float basis[9], /* World space basis of the RT volume */ @@ -186,18 +319,23 @@ draw_thumbnail } static res_T -radiative_path_length +radiative_properties (struct sschiff_device* dev, struct ssp_rng* rng, struct sschiff_integrator_desc* desc, - const int istep) + const double wavelength, + const int istep, + struct accum* accum) { struct s3d_shape* shape = NULL; struct s3d_scene* scene = NULL; struct sschiff_material material = SSCHIFF_NULL_MATERIAL; + float lower[3], upper[3]; + float aabb_pt[8][3]; + float centroid[3]; int idir; res_T res = RES_OK; - ASSERT(dev && rng && desc); + ASSERT(dev && rng && desc && accum); res = s3d_shape_create_mesh(dev->s3d, &shape); if(res != RES_OK) { @@ -223,44 +361,43 @@ radiative_path_length } S3D(scene_begin_session(scene, S3D_TRACE)); + S3D(scene_get_aabb(scene, lower, upper)); + + /* AABB vertex layout + * 6-------7 + * /' /| + * 2-------3 | + * | 4.....|.5 + * |, |/ + * 0-------1 */ + f3(aabb_pt[0], lower[0], lower[1], lower[2]); + f3(aabb_pt[1], upper[0], lower[1], lower[2]); + f3(aabb_pt[2], lower[0], upper[1], lower[2]); + f3(aabb_pt[3], upper[0], upper[1], lower[2]); + f3(aabb_pt[4], lower[0], lower[1], upper[2]); + f3(aabb_pt[5], upper[0], lower[1], upper[2]); + f3(aabb_pt[6], lower[0], upper[1], upper[2]); + f3(aabb_pt[7], upper[0], upper[1], upper[2]); + + f3_mulf(centroid, f3_add(centroid, lower, upper), 0.5f); + FOR_EACH(idir, 0, NDIRS) { - char thumb_name[64]; float dir[4]; - float centroid[3]; float basis[9]; - float lower[3], upper[3]; float transform[12]; float pt[8][3]; int i; ssp_ran_sphere_uniform(rng, dir); - S3D(scene_get_aabb(scene, lower, upper)); - - /* AABB vertex layout - * 6-------7 - * /' /| - * 2-------3 | - * | 4.....|.5 - * |, |/ - * 0-------1 */ - f3(pt[0], lower[0], lower[1], lower[2]); - f3(pt[1], upper[0], lower[1], lower[2]); - f3(pt[2], lower[0], upper[1], lower[2]); - f3(pt[3], upper[0], upper[1], lower[2]); - f3(pt[4], lower[0], lower[1], upper[2]); - f3(pt[5], upper[0], lower[1], upper[2]); - f3(pt[6], lower[0], upper[1], upper[2]); - f3(pt[7], upper[0], upper[1], upper[2]); /* Build the transformation matrix from world to footprint space. Use the * AABB centroid as the origin of the footprint space. */ - f3_mulf(centroid, f3_add(centroid, lower, upper), 0.5f); build_basis(dir, basis); build_transform(centroid, basis, transform); /* Transform the AABB from world to footprint space */ FOR_EACH(i, 0, 8) { - f3_add(pt[i], f33_mulf3(pt[i], transform, pt[i]), transform + 9); + f3_add(pt[i], f33_mulf3(pt[i], transform, aabb_pt[i]), transform + 9); } /* Compute the AABB of the footprint */ @@ -270,9 +407,20 @@ radiative_path_length f3_max(upper, upper, pt[i]); } +#if 0 + (void)istep; + res = compute_monte_carlo_weight + (scene, rng, &material, wavelength, basis, centroid, lower, upper, accum); + if(res != RES_OK) goto error; +#else /* Compute an image of the shape transformed in the footprint space */ - sprintf(thumb_name, "%d_%d.ppm", istep, idir); - draw_thumbnail(scene, basis, centroid, lower, upper, thumb_name); + { + char thumb_name[64]; + (void)wavelength; + sprintf(thumb_name, "%d_%d.ppm", istep, idir); + draw_thumbnail(scene, basis, centroid, lower, upper, thumb_name); + } +#endif } S3D(scene_end_session(scene)); @@ -347,6 +495,7 @@ sschiff_integrate struct sschiff_estimator** out_estimator) { struct sschiff_estimator* estimator = NULL; + struct accum accum; int i; res_T res = RES_OK; @@ -361,8 +510,9 @@ sschiff_integrate estimator->nsteps = steps_count; estimator->wavelength = wavelength; + memset(&accum, 0, sizeof(struct accum)); FOR_EACH(i, 0, (int)steps_count) { - res = radiative_path_length(dev, rng, desc, i); + res = radiative_properties(dev, rng, desc, wavelength, i, &accum); if(res != RES_OK) goto error; }