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:
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;