solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

commit 7e26042b535dd3879ce752d3a6c70dbb149fc088
parent c268521dad790dc95322f2af134f415a106687fa
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 31 May 2017 09:45:33 +0200

Fix the integration with an atmosphere having a spectral absorption

The absorption of the surrounding medium was assumed to be a scalar.
However the atmosphere can have a spectral absorption, which was not
consistent with the previous assumption leading to errors when checking
for media consistency. T

This commit setups the surrounding medium with the absorption of the
atmosphere. If no atmosphere is defined the absorption is null.

Diffstat:
Msrc/ssol.h | 5-----
Msrc/ssol_atmosphere.c | 12------------
Msrc/ssol_atmosphere_c.h | 4----
Msrc/ssol_data.c | 12------------
Msrc/ssol_material.c | 42++++++++++++++++++++++++++++++++++++++++--
Msrc/ssol_material_c.h | 4----
Msrc/ssol_solver.c | 8+++-----
Msrc/ssol_spectrum.c | 11++++++++---
Msrc/ssol_spectrum_c.h | 1+
9 files changed, 52 insertions(+), 47 deletions(-)

diff --git a/src/ssol.h b/src/ssol.h @@ -1220,11 +1220,6 @@ ssol_data_copy (struct ssol_data* dst, const struct ssol_data* src); -SSOL_API int -ssol_data_eq - (const struct ssol_data* op0, - const struct ssol_data* op1); - SSOL_API double ssol_data_get_value (const struct ssol_data* data, diff --git a/src/ssol_atmosphere.c b/src/ssol_atmosphere.c @@ -125,15 +125,3 @@ ssol_atmosphere_set_absorption return RES_OK; } -/******************************************************************************* - * Local functions - ******************************************************************************/ -double -atmosphere_get_absorption - (const struct ssol_atmosphere* atmosphere, - const double wavelength) -{ - ASSERT(atmosphere && wavelength >= 0); - return ssol_data_get_value(&atmosphere->absorption, wavelength); -} - diff --git a/src/ssol_atmosphere_c.h b/src/ssol_atmosphere_c.h @@ -29,9 +29,5 @@ struct ssol_atmosphere { ref_T ref; }; -extern LOCAL_SYM double -atmosphere_get_absorption - (const struct ssol_atmosphere* atmosphere, - const double wavelength); #endif /* SSOL_ATMOSPHERE_C_H */ diff --git a/src/ssol_data.c b/src/ssol_data.c @@ -76,18 +76,6 @@ ssol_data_copy(struct ssol_data* dst, const struct ssol_data* src) return dst; } -int -ssol_data_eq(const struct ssol_data* a, const struct ssol_data* b) -{ - ASSERT(a && b); - if(a->type != b->type) return 0; - switch(a->type) { - case SSOL_DATA_REAL: return a->value.real == b->value.real; - case SSOL_DATA_SPECTRUM: return a->value.spectrum == b->value.spectrum; - default: FATAL("Unreachable code.\n"); break; - } -} - double ssol_data_get_value(const struct ssol_data* data, const double wavelength) { diff --git a/src/ssol_material.c b/src/ssol_material.c @@ -36,6 +36,44 @@ /******************************************************************************* * Helper functions ******************************************************************************/ +/* Define if the submitted ssol_data are *certainly* equals or not. Note that it + * does not check explicitly the spectrum data since it would be too expensive; + * it compares their checksum and that's why one cannot certify that the data + * are strictly equals. Anyway, since this function is used to detect medium + * inconsistencies, it is actually really sufficient to use this strategy. */ +static INLINE int +ssol_data_ceq(const struct ssol_data* a, const struct ssol_data* b) +{ + int i; + ASSERT(a && b); + + if(a->type != b->type) { + i = 0; + } else { + switch(a->type) { + case SSOL_DATA_REAL: + i = a->value.real == b->value.real; + break; + case SSOL_DATA_SPECTRUM: + i = a->value.spectrum->checksum[0] == b->value.spectrum->checksum[0] + && a->value.spectrum->checksum[1] == b->value.spectrum->checksum[1]; + break; + default: FATAL("Unreachable code\n"); break; + } + } + return i; +} + +/* Define if the submitted media are *certainly* equals. Refer to the + * check_ssol_data for more details. */ +static INLINE int +media_ceq(const struct ssol_medium* a, const struct ssol_medium* b) +{ + ASSERT(a && b); + return ssol_data_ceq(&a->refractive_index, &b->refractive_index) + && ssol_data_ceq(&a->absorption, &b->absorption); +} + static void shade_normal_default (struct ssol_device* dev, @@ -66,7 +104,7 @@ setup_dielectric_bsdf ASSERT(medium && bsdf); (void)wavelength, (void)fragment; - if(!MEDIA_EQ(medium, &mtl->out_medium)) { + if(!media_ceq(medium, &mtl->out_medium)) { log_error(mtl->dev, "Inconsistent medium description.\n"); res = RES_BAD_OP; goto error; @@ -683,7 +721,7 @@ material_get_next_medium switch(mtl->type) { /* The material is an interface between 2 media */ case SSOL_MATERIAL_DIELECTRIC: - if(MEDIA_EQ(&mtl->out_medium, medium)) { + if(media_ceq(&mtl->out_medium, medium)) { ssol_medium_copy(next_medium, &mtl->in_medium); } else { ssol_medium_copy(next_medium, &mtl->out_medium); diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h @@ -23,10 +23,6 @@ struct s3d_primitive; struct ssf_bsdf; struct ssol_device; -#define MEDIA_EQ(A, B) \ - ( ssol_data_eq(&((A)->refractive_index), &((B)->refractive_index)) \ - && ssol_data_eq(&((A)->absorption), &((B)->absorption))) - struct dielectric { int dummy; }; diff --git a/src/ssol_solver.c b/src/ssol_solver.c @@ -729,6 +729,7 @@ trace_radiative_path FILE* output) /* May be NULL */ { struct path path; + struct ssol_medium medium = SSOL_MEDIUM_VACUUM; struct s3d_hit hit = S3D_HIT_NULL; struct point pt; float org[3], dir[3], range[2] = { 0, FLT_MAX }; @@ -773,11 +774,8 @@ trace_radiative_path ACCUM_WEIGHT(thread_ctx->shadowed, pt.weight); if(tracker) path.type = SSOL_PATH_SHADOW; } else { - struct ssol_medium medium = SSOL_MEDIUM_VACUUM; if(scn->atmosphere) { - /* Assume that the path starts from an uniform atmosphere */ - ssol_data_set_real(&medium.absorption, - atmosphere_get_absorption(scn->atmosphere, pt.wl)); + ssol_data_copy(&medium.absorption, &scn->atmosphere->absorption); } /* Setup the ray as if it starts from the current point position in order * to handle the points that start from a virtual material */ @@ -872,7 +870,6 @@ trace_radiative_path if(tracker) { path.type = hit_a_receiver ? SSOL_PATH_SUCCESS : SSOL_PATH_MISSING; } - ssol_medium_clear(&medium); } if(tracker) { @@ -880,6 +877,7 @@ trace_radiative_path if(res != RES_OK) goto error; } exit: + ssol_medium_clear(&medium); if(tracker) path_release(&path); return res; error: diff --git a/src/ssol_spectrum.c b/src/ssol_spectrum.c @@ -17,11 +17,11 @@ #include "ssol_spectrum_c.h" #include "ssol_device_c.h" -#include <rsys/rsys.h> +#include <rsys/algorithm.h> +#include <rsys/hash.h> +#include <rsys/math.h> #include <rsys/mem_allocator.h> #include <rsys/ref_count.h> -#include <rsys/math.h> -#include <rsys/algorithm.h> /******************************************************************************* * Helper functions @@ -196,12 +196,17 @@ ssol_spectrum_setup current_wl = *(wavelengths + i); } + spectrum->checksum[0] = hash_fnv64(wavelengths, nwlens*sizeof(double)); + spectrum->checksum[1] = hash_fnv64(intensities, nwlens*sizeof(double)); + exit: return res; error: if(spectrum) { darray_double_clear(&spectrum->wavelengths); darray_double_clear(&spectrum->intensities); + spectrum->checksum[0] = 0; + spectrum->checksum[1] = 0; } goto exit; } diff --git a/src/ssol_spectrum_c.h b/src/ssol_spectrum_c.h @@ -22,6 +22,7 @@ struct ssol_spectrum { struct darray_double wavelengths; struct darray_double intensities; + uint64_t checksum[2]; struct ssol_device* dev; ref_T ref;