star-4v_s

An invariant property of diffuse random walks
git clone git://git.meso-star.fr/star-4v_s.git
Log | Files | Refs | README | LICENSE

commit 8d01b745cb962d05578f3dd50438747fdef98e51
parent 2138be840bccc66722a6650914a1a959e9b7ae34
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue,  3 May 2016 10:01:59 +0200

Clean-up and refactoring

Diffstat:
Msrc/s4vs.c | 23++++++++---------------
Msrc/s4vs_realization.c | 74++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/s4vs_realization.h | 1+
3 files changed, 43 insertions(+), 55 deletions(-)

diff --git a/src/s4vs.c b/src/s4vs.c @@ -26,7 +26,6 @@ * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ -#include <rsys/clock_time.h> #include <rsys/cstr.h> #include <rsys/float3.h> #include <rsys/mem_allocator.h> @@ -40,16 +39,12 @@ static res_T compute_4v_s(struct s3d_scene* scene, const size_t max_steps, const double ks) { - char buf[512]; - struct time begin, end, elapsed; struct s4vs_context ctx; - float S, V, reference; struct smc_device* smc = NULL; struct smc_integrator integrator; struct smc_estimator* estimator = NULL; struct smc_estimator_status estimator_status; - double length; - double sig_length; + float S, V, reference; int mask; res_T res = RES_OK; ASSERT(scene && max_steps > 0 && ks > 0); @@ -76,6 +71,7 @@ compute_4v_s(struct s3d_scene* scene, const size_t max_steps, const double ks) /* Initialize context for MC computation */ ctx.scene = scene; ctx.ks = ks; + ctx.g = PI/4.0; /* Setup Star-MC */ SMC(device_create(NULL, NULL, SMC_NTHREADS_DEFAULT, NULL, &smc)); @@ -85,11 +81,7 @@ compute_4v_s(struct s3d_scene* scene, const size_t max_steps, const double ks) integrator.max_failures = max_steps / 1000; /* cancel if 0.1% of the realization fail */ /* Solve */ - time_current(&begin); SMC(solve(smc, &integrator, &ctx, &estimator)); - time_current(&end); - time_sub(&elapsed, &end, &begin); - time_dump(&elapsed, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf)); /* Print the simulation results */ SMC(estimator_get_status(estimator, &estimator_status)); @@ -101,11 +93,12 @@ compute_4v_s(struct s3d_scene* scene, const size_t max_steps, const double ks) (unsigned long)estimator_status.NF); goto error; } - length = SMC_DOUBLE(estimator_status.E); - sig_length = SMC_DOUBLE(estimator_status.SE); - printf("4V/S = %g ~ %g +/- %g\n# failures: %lu/%lu\nElapsed time: %s\n", - reference, length, sig_length, - (unsigned long)estimator_status.NF, (unsigned long)max_steps, buf); + printf("4V/S = %g ~ %g +/- %g\n# failures: %lu/%lu\n", + reference, + SMC_DOUBLE(estimator_status.E), + SMC_DOUBLE(estimator_status.SE), + (unsigned long)estimator_status.NF, + (unsigned long)max_steps); exit: /* Clean-up data */ diff --git a/src/s4vs_realization.c b/src/s4vs_realization.c @@ -40,70 +40,64 @@ s4vs_realization(void* out_length, struct ssp_rng* rng, void* context) struct s4vs_context* ctx = (struct s4vs_context*)context; struct s3d_attrib attrib; struct s3d_primitive prim; - float normal[3], dir[4], pos[3], range[2], st[2]; + float normal[3], u[4], x[3], range[2], st[2]; struct s3d_hit hit; - double length = 0; - double lambda = 0; - float u, v, w; - - /* Sample the scene surface to define the random walk starting point */ + double w = 0; + double sigma = 0; + int keep_running = 0; + float r0, r1, r2; /* Sample a surface location, i.e. primitive ID and parametric coordinates */ - u = ssp_rng_canonical_float(rng); - v = ssp_rng_canonical_float(rng); - w = ssp_rng_canonical_float(rng); - S3D(scene_sample(ctx->scene, u, v, w, &prim, st)); + r0 = ssp_rng_canonical_float(rng); + r1 = ssp_rng_canonical_float(rng); + r2 = ssp_rng_canonical_float(rng); + S3D(scene_sample(ctx->scene, r0, r1, r2, &prim, st)); /* retrieve the sampled geometric normal and position */ S3D(primitive_get_attrib(&prim, S3D_GEOMETRY_NORMAL, st, &attrib)); f3_normalize(normal, attrib.value); S3D(primitive_get_attrib(&prim, S3D_POSITION, st, &attrib)); - f3_set(pos, attrib.value); + f3_set(x, attrib.value); /* Cosine weighted sampling of the hemisphere around the sampled normal */ - ssp_ran_hemisphere_cos(rng, normal, dir); + ssp_ran_hemisphere_cos(rng, normal, u); /* Find the 1st hit from the sampled location along the sampled direction */ range[0] = 1.e-6f; - range[1] = FLT_MAX; + range[1] = (float)INF; do { - S3D(scene_trace_ray(ctx->scene, pos, dir, range, &hit)); + S3D(scene_trace_ray(ctx->scene, x, u, range, &hit)); range[0] += 1.e-6f; } while(S3D_PRIMITIVE_EQ(&hit.prim, &prim)); /* Handle self-hit */ /* No intersection <=> numerical imprecision or geometry leakage */ - if(S3D_HIT_NONE(&hit)) - return RES_UNKNOWN_ERR; /* failed realization */ + if(S3D_HIT_NONE(&hit)) return RES_UNKNOWN_ERR; - /* Here the starting point and a propagation direction have been sampled */ - /* and we have determined the distance of the geometry in this direction */ + keep_running = 1; + while(keep_running) { /* Here we go for the diffuse random walk */ + sigma = ssp_ran_exp(rng, ctx->ks); /* Sample a length according to ks */ - while(1) { /* Here we go for the diffuse random walk */ - lambda = ssp_ran_exp(rng, ctx->ks); /* Sample a length according to ks */ + if(sigma < hit.distance) { + int i; + FOR_EACH(i, 0, 3) x[i] = x[i] + (float)sigma*u[i]; + ssp_ran_sphere_hg(rng, u, ctx->g, u); - if(lambda >= hit.distance) { - /* Lambda exceeds the geometry distance: stop the random walk */ - length += hit.distance; - break; - } + /* sample a new direction */ + range[0] = 0; + range[1] = (float)INF; + S3D(scene_trace_ray(ctx->scene, x, u, range, &hit)); - /* lambda doesn't exceed the geometry distance */ - /* the random walk can continue after a diffusion */ - length += lambda; - f3_add(pos, pos, f3_mulf(dir, dir, (float)lambda)); + w = w + sigma; - /* sample a new direction */ - ssp_ran_sphere_uniform(rng, dir); - range[0] = 0; - /* find the first intersection with the geometry */ - /* to refresh the geometry's distance */ - S3D(scene_trace_ray(ctx->scene, pos, dir, range, &hit)); - - /* No intersection <=> numerical imprecision or geometry leakage */ - if(S3D_HIT_NONE(&hit)) - return RES_UNKNOWN_ERR; /* failed realization */ + /* No intersection <=> numerical imprecision or geometry leakage */ + if(S3D_HIT_NONE(&hit)) return RES_UNKNOWN_ERR; + + } else { /* Stop the random walk */ + w = w + hit.distance; + keep_running = 0; + } } - SMC_DOUBLE(out_length) = length; + SMC_DOUBLE(out_length) = w; return RES_OK; } diff --git a/src/s4vs_realization.h b/src/s4vs_realization.h @@ -38,6 +38,7 @@ struct s4vs_context { struct s3d_sampler* sampler; struct s3d_scene* scene; double ks; + double g; }; /*******************************************************************************