commit 135e3ce32d4f72f490520b23edebbef1f56dda6c
parent 851bebb0434c56c7388eb094e43355a2307bb960
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Tue, 20 Sep 2016 18:30:36 +0200
BugFix: sun cannot accommodate single value spectrum (monochromatic sun)
Diffstat:
5 files changed, 261 insertions(+), 18 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -60,6 +60,7 @@ set(SSOL_FILES_SRC
ssol_object.c
ssol_instance.c
ssol_ranst_sun_dir.c
+ ssol_ranst_sun_wl.c
ssol_scene.c
ssol_shape.c
ssol_spectrum.c
@@ -80,6 +81,7 @@ set(SSOL_FILES_INC
ssol_object_c.h
ssol_instance_c.h
ssol_ranst_sun_dir.h
+ ssol_ranst_sun_wl.h
ssol_scene_c.h
ssol_shape_c.h
ssol_spectrum_c.h
@@ -139,7 +141,7 @@ if(NOT NO_TEST)
build_test(${_name} ${ARGN})
register_test(${_name} ${_name})
endfunction()
-
+
new_test(test_ssol_device)
new_test(test_ssol_image)
new_test(test_ssol_material)
diff --git a/src/ssol_ranst_sun_wl.c b/src/ssol_ranst_sun_wl.c
@@ -0,0 +1,187 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "ssol.h"
+#include "ssol_ranst_sun_wl.h"
+
+#include <star/ssp.h>
+
+#include <rsys/double33.h>
+#include <rsys/math.h>
+#include <rsys/mem_allocator.h>
+#include <rsys/rsys.h>
+#include <rsys/ref_count.h>
+
+ /*******************************************************************************
+ * Distributions types for wavelengths
+ ******************************************************************************/
+struct ran_piecewise_wl_state {
+ struct ssp_ranst_piecewise_linear* spectrum;
+};
+
+struct ran_dirac_wl_state {
+ double wavelength;
+};
+
+enum wl_ran_type {
+ WL_DIRAC,
+ WL_PIECEWISE,
+ WL_TYPES_COUNT__
+};
+
+/* One single type for all distributions. Only the state type depends on the
+* distribution type */
+struct ranst_sun_wl {
+ double(*get)
+ (const struct ranst_sun_wl* ran, struct ssp_rng* rng);
+ union {
+ struct ran_piecewise_wl_state piecewise;
+ struct ran_dirac_wl_state dirac;
+ } state;
+ enum wl_ran_type type;
+
+ ref_T ref;
+ struct mem_allocator* allocator;
+};
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static void
+distrib_sun_wl_release(ref_T* ref)
+{
+ struct ranst_sun_wl* ran;
+ ASSERT(ref);
+ ran = CONTAINER_OF(ref, struct ranst_sun_wl, ref);
+ switch (ran->type) {
+ case WL_DIRAC:
+ break;
+ case WL_PIECEWISE:
+ SSP(ranst_piecewise_linear_ref_put(ran->state.piecewise.spectrum));
+ ran->state.piecewise.spectrum = NULL;
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ MEM_RM(ran->allocator, ran);
+}
+
+/*******************************************************************************
+ * Piecewise random variate
+ ******************************************************************************/
+static double
+ran_piecewise_get
+ (const struct ranst_sun_wl* ran,
+ struct ssp_rng* rng)
+{
+ ASSERT(ran && rng && ran->type == WL_PIECEWISE && ran->state.piecewise.spectrum);
+ return ssp_ranst_piecewise_linear_get(ran->state.piecewise.spectrum, rng);
+}
+
+/*******************************************************************************
+ * Dirac distribution
+ ******************************************************************************/
+static double
+ran_dirac_get
+(const struct ranst_sun_wl* ran,
+ struct ssp_rng* rng)
+{
+ (void) rng;
+ ASSERT(ran && rng && ran->type == WL_DIRAC);
+ return ran->state.dirac.wavelength;
+}
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+res_T
+ranst_sun_wl_create
+ (struct mem_allocator* allocator,
+ struct ranst_sun_wl** out_ran)
+{
+ struct ranst_sun_wl* ran = NULL;
+
+ if (!out_ran) return RES_BAD_ARG;
+
+ allocator = allocator ? allocator : &mem_default_allocator;
+
+ ran = MEM_CALLOC(allocator, 1, sizeof(struct ranst_sun_wl));
+ if (!ran) return RES_MEM_ERR;
+
+ ref_init(&ran->ref);
+ ran->allocator = allocator;
+ *out_ran = ran;
+
+ return RES_OK;
+}
+
+res_T
+ranst_sun_wl_ref_get(struct ranst_sun_wl* ran)
+{
+ if (!ran) return RES_BAD_ARG;
+ ref_get(&ran->ref);
+ return RES_OK;
+}
+
+res_T
+ranst_sun_wl_ref_put(struct ranst_sun_wl* ran)
+{
+ if (!ran) return RES_BAD_ARG;
+ ref_put(&ran->ref, distrib_sun_wl_release);
+ return RES_OK;
+}
+
+double
+ranst_sun_wl_get
+ (const struct ranst_sun_wl* ran,
+ struct ssp_rng* rng)
+{
+ ASSERT(ran);
+ return ran->get(ran, rng);
+}
+
+res_T
+ranst_sun_wl_setup
+ (struct ranst_sun_wl* ran,
+ const double* frequencies,
+ const double* intensities,
+ const size_t sz)
+{
+ res_T res = RES_OK;
+ if (!ran || !frequencies || !intensities || !sz)
+ return RES_BAD_ARG;
+ if (sz > 1) {
+ ran->type = WL_PIECEWISE;
+ ran->get = &ran_piecewise_get;
+ res = ssp_ranst_piecewise_linear_create(
+ ran->allocator, &ran->state.piecewise.spectrum);
+ if (res != RES_OK) goto error;
+ res = ssp_ranst_piecewise_linear_setup
+ (ran->state.piecewise.spectrum, frequencies, intensities, sz);
+ if (res != RES_OK) goto error;
+ }
+ else {
+ ran->type = WL_DIRAC;
+ ran->get = &ran_dirac_get;
+ ran->state.dirac.wavelength = frequencies[0];
+ }
+end:
+ return res;
+error:
+ if (ran->state.piecewise.spectrum)
+ SSP(ranst_piecewise_linear_ref_put(ran->state.piecewise.spectrum));
+ ran->state.piecewise.spectrum = NULL;
+ goto end;
+}
+
diff --git a/src/ssol_ranst_sun_wl.h b/src/ssol_ranst_sun_wl.h
@@ -0,0 +1,52 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SSOL_RANST_SUN_WL_H
+#define SSOL_RANST_SUN_WL_H
+
+/* Random variate state of a sun direction */
+struct ranst_sun_wl;
+
+/* External types */
+struct ssp_rng;
+struct mem_allocator;
+
+extern LOCAL_SYM res_T
+ranst_sun_wl_create
+ (struct mem_allocator* allocator,
+ struct ranst_sun_wl** ran);
+
+extern LOCAL_SYM res_T
+ranst_sun_wl_setup
+ (struct ranst_sun_wl* ran,
+ const double* frequencies,
+ const double* intensities,
+ const size_t sz);
+
+extern LOCAL_SYM res_T
+ranst_sun_wl_ref_get
+ (struct ranst_sun_wl* ran);
+
+extern LOCAL_SYM res_T
+ranst_sun_wl_ref_put
+ (struct ranst_sun_wl* ran);
+
+extern LOCAL_SYM double
+ranst_sun_wl_get
+ (const struct ranst_sun_wl* ran,
+ struct ssp_rng* rng);
+
+#endif /* SSOL_RANST_SUN_WL_H */
+
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -25,6 +25,8 @@
#include "ssol_spectrum_c.h"
#include "ssol_instance_c.h"
#include "ssol_brdf_composite.h"
+#include "ssol_ranst_sun_dir.h"
+#include "ssol_ranst_sun_wl.h"
#include <rsys/mem_allocator.h>
#include <rsys/ref_count.h>
@@ -75,15 +77,14 @@ set_sun_distributions(struct solver_data* data)
dev = data->scene->dev;
ASSERT(dev && dev->allocator);
/* first set the spectrum distribution */
- res = ssp_ranst_piecewise_linear_create
- (dev->allocator, &data->sun_spectrum_ran);
+ res = ranst_sun_wl_create(dev->allocator, &data->sun_wl_ran);
if (res != RES_OK) goto error;
spectrum = sun->spectrum;
frequencies = darray_double_cdata_get(&spectrum->frequencies);
intensities = darray_double_cdata_get(&spectrum->intensities);
sz = darray_double_size_get(&spectrum->frequencies);
- res = ssp_ranst_piecewise_linear_setup
- (data->sun_spectrum_ran, frequencies, intensities, sz);
+ res = ranst_sun_wl_setup(
+ data->sun_wl_ran, frequencies, intensities, sz);
if (res != RES_OK) goto error;
/* then the direction distribution */
res = ranst_sun_dir_create(dev->allocator, &data->sun_dir_ran);
@@ -108,12 +109,12 @@ set_sun_distributions(struct solver_data* data)
exit:
return res;
error:
- if (data->sun_spectrum_ran) {
- SSP(ranst_piecewise_linear_ref_put(data->sun_spectrum_ran));
- data->sun_spectrum_ran = NULL;
+ if (data->sun_wl_ran) {
+ CHECK(ranst_sun_wl_ref_put(data->sun_wl_ran), RES_OK);
+ data->sun_wl_ran = NULL;
}
if (data->sun_dir_ran) {
- ASSERT(ranst_sun_dir_ref_put(data->sun_dir_ran) == RES_OK);
+ CHECK(ranst_sun_dir_ref_put(data->sun_dir_ran), RES_OK);
data->sun_dir_ran = NULL;
}
goto exit;
@@ -123,10 +124,10 @@ static void
release_solver_data(struct solver_data* data)
{
ASSERT(data);
- if (data->view_rt) s3d_scene_view_ref_put(data->view_rt);
- if (data->view_samp) s3d_scene_view_ref_put(data->view_samp);
- if (data->sun_dir_ran) ranst_sun_dir_ref_put(data->sun_dir_ran);
- if (data->sun_spectrum_ran) ssp_ranst_piecewise_linear_ref_put(data->sun_spectrum_ran);
+ if (data->view_rt) S3D(scene_view_ref_put(data->view_rt));
+ if (data->view_samp) S3D(scene_view_ref_put(data->view_samp));
+ if (data->sun_dir_ran) CHECK(ranst_sun_dir_ref_put(data->sun_dir_ran), RES_OK);
+ if (data->sun_wl_ran) CHECK(ranst_sun_wl_ref_put(data->sun_wl_ran), RES_OK);
if (data->brdfs) brdf_composite_ref_put(data->brdfs);
*data = SOLVER_DATA_NULL;
}
@@ -198,8 +199,8 @@ check_fst_segment(const struct segment* seg)
if (seg->on_punched) ASSERT_NAN(seg->hit_pos_local, 3);
NCHECK(seg->on_punched, 99);
ASSERT_NAN(seg->org, 3);
- ASSERT(seg->weight > 0);
ASSERT_NAN(&seg->tmin, 1);
+ ASSERT(seg->weight > 0);
}
static void
@@ -252,6 +253,7 @@ setup_next_segment(struct realisation* rs)
seg->weight = prev->weight
* brdf_composite_sample(
data->brdfs, data->rng, prev->dir, data->fragment.Ns, seg->dir);
+
return res;
}
@@ -462,8 +464,7 @@ static void
sample_wavelength(struct realisation* rs)
{
ASSERT(rs);
- rs->freq = ssp_ranst_piecewise_linear_get
- (rs->data.sun_spectrum_ran, rs->data.rng);
+ rs->freq = ranst_sun_wl_get(rs->data.sun_wl_ran, rs->data.rng);
}
/* check if the sampled point as described in rs->start receives sun light
diff --git a/src/ssol_solver_c.h b/src/ssol_solver_c.h
@@ -16,7 +16,6 @@
#ifndef SSOL_SOLVER_C_H
#define SSOL_SOLVER_C_H
-#include "ssol_ranst_sun_dir.h"
#include "ssol_material_c.h"
#include "ssol_c.h"
@@ -27,6 +26,8 @@
#include <star/ssp.h>
#include <star/s3d.h>
+struct ranst_sun_dir;
+struct ranst_sun_wl;
#define DARRAY_NAME quadric
#define DARRAY_DATA struct ssol_quadric
@@ -104,7 +105,7 @@ struct solver_data {
struct s3d_scene_view* view_samp;
/* The random distributions for sun sampling */
struct ranst_sun_dir* sun_dir_ran;
- struct ssp_ranst_piecewise_linear* sun_spectrum_ran;
+ struct ranst_sun_wl* sun_wl_ran;
/* Tmp data used for propagation */
struct brdf_composite* brdfs;
struct surface_fragment fragment;