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 84540b42fb0a9d0106fe58277f70665db3fc6382
parent 372a1886184ad1a96aed51966e8c6030130a3390
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 15 Apr 2016 16:15:12 +0200

Adapt to the new StarMC API

Diffstat:
Msrc/s4vs.c | 24++++++++++++------------
Msrc/s4vs_realization.c | 89+++++++++++++++++++++++++++++++++----------------------------------------------
Msrc/s4vs_realization.h | 6+++---
3 files changed, 52 insertions(+), 67 deletions(-)

diff --git a/src/s4vs.c b/src/s4vs.c @@ -75,8 +75,6 @@ compute_4v_s(struct s3d_scene* scene, const size_t max_steps, const double ks) /* Initialize context for MC computation */ ctx.scene = scene; - ctx.nfailures = 0; - ctx.error = 0; ctx.ks = ks; /* Setup Star-MC */ @@ -84,28 +82,30 @@ compute_4v_s(struct s3d_scene* scene, const size_t max_steps, const double ks) integrator.integrand = &s4vs_realization; /* Realization function */ integrator.type = &smc_double; /* Type of the Monte Carlo weight */ integrator.max_steps = max_steps; /* Realization count */ + 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); - - if(ctx.error) { - fprintf(stderr, - "Too many failures. The scene might not match the prerequisites:\n" - "it must be closed and its normals must point *into* the volume.\n"); - goto error; - } - 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)); + + if(estimator_status.NF >= integrator.max_failures) { + fprintf(stderr, + "Too many failures (%lu). The scene might not match the prerequisites:\n" + "it must be closed and its normals must point *into* the volume.\n", + (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: %d/%lu\nElapsed time: %s\n", - reference, length, sig_length, ctx.nfailures, max_steps, buf); + 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); exit: /* Clean-up data */ diff --git a/src/s4vs_realization.c b/src/s4vs_realization.c @@ -34,10 +34,7 @@ #include "s4vs_realization.h" -/* Maximum number of failures before an error occurs */ -#define MAX_FAILURES 10 - -void +res_T s4vs_realization(void* out_length, struct ssp_rng* rng, void* context) { struct s4vs_context* ctx = (struct s4vs_context*)context; @@ -47,39 +44,36 @@ s4vs_realization(void* out_length, struct ssp_rng* rng, void* context) struct s3d_hit hit; double length = 0; double lambda = 0; - int nfailures = 0; - - do { /* Sample the scene surface to define the random walk starting point */ - float u, v, w; - - /* 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)); - - /* 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); - - /* Cosine weighted sampling of the hemisphere around the sampled normal */ - ssp_ran_hemisphere_cos(rng, normal, dir); - - /* Find the 1st hit from the sampled location along the sampled direction */ - range[0] = 1.e-6f; - range[1] = FLT_MAX; - do { - S3D(scene_trace_ray(ctx->scene, pos, dir, range, &hit)); - range[0] += 1.e-6f; - } while(S3D_PRIMITIVE_EQ(&hit.prim, &prim)); /* Handle self-hit */ + float u, v, w; - /* No intersection <=> numerical imprecision or geometry leakage */ - } while(S3D_HIT_NONE(&hit) && ++nfailures < MAX_FAILURES); + /* Sample the scene surface to define the random walk starting point */ + + /* 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)); + + /* 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); - /* Too many ray-tracing failures => the geometry is inconsistent */ - if(nfailures >= MAX_FAILURES) goto error; + /* Cosine weighted sampling of the hemisphere around the sampled normal */ + ssp_ran_hemisphere_cos(rng, normal, dir); + + /* Find the 1st hit from the sampled location along the sampled direction */ + range[0] = 1.e-6f; + range[1] = FLT_MAX; + do { + S3D(scene_trace_ray(ctx->scene, pos, dir, 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 */ /* Here the starting point and a propagation direction have been sampled */ /* and we have determined the distance of the geometry in this direction */ @@ -98,27 +92,18 @@ s4vs_realization(void* out_length, struct ssp_rng* rng, void* context) length += lambda; f3_add(pos, pos, f3_mulf(dir, dir, (float)lambda)); - do { /* 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)); + 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 */ - } while(S3D_HIT_NONE(&hit) && ++nfailures < MAX_FAILURES); - - /* Too many ray-tracing failures => the geometry is inconsistent */ - if(nfailures >= MAX_FAILURES) goto error; + if(S3D_HIT_NONE(&hit)) + return RES_UNKNOWN_ERR; /* failed realization */ } -exit: - ATOMIC_ADD(&ctx->nfailures, nfailures); /* Register the number of failures */ SMC_DOUBLE(out_length) = length; - return; -error: - ctx->error = 1; /* Notify that an error occurs */ - length = 0; /* Reset the path length */ - goto exit; + return RES_OK; } diff --git a/src/s4vs_realization.h b/src/s4vs_realization.h @@ -29,6 +29,8 @@ #ifndef S4V_S_REALIZATION_H #define S4V_S_REALIZATION_H +#include <rsys/rsys.h> + /* forward definition */ struct ssp_rng; @@ -36,13 +38,11 @@ struct s4vs_context { struct s3d_sampler* sampler; struct s3d_scene* scene; double ks; - int nfailures; - int error; }; /******************************************************************************* * MC realization function ******************************************************************************/ -extern void s4vs_realization(void* length, struct ssp_rng* rng, void* context); +extern res_T s4vs_realization(void* length, struct ssp_rng* rng, void* context); #endif /* REALIZATION_H */