solstice-solver

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

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:
Mcmake/CMakeLists.txt | 4+++-
Asrc/ssol_ranst_sun_wl.c | 187+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ssol_ranst_sun_wl.h | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/ssol_solver.c | 31++++++++++++++++---------------
Msrc/ssol_solver_c.h | 5+++--
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;