mrumtl

Describe materials that vary spectrally
git clone git://git.meso-star.fr/mrumtl.git
Log | Files | Refs | README | LICENSE

mrumtl_fetch.c (3733B)


      1 /* Copyright (C) 2020-2023 |Méso|Star> (contact@meso-star.com)
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "mrumtl.h"
     17 #include "mrumtl_c.h"
     18 #include "mrumtl_log.h"
     19 #include "mrumtl_brdf.h"
     20 
     21 #include <rsys/algorithm.h>
     22 
     23 /*******************************************************************************
     24  * Helper functions
     25  ******************************************************************************/
     26 static INLINE int
     27 cmp_brdf(const void* key, const void* item)
     28 {
     29   const double wavelength = (*(const double*)key);
     30   const struct mrumtl_brdf* brdf = item;
     31   if(wavelength < brdf->wlen[0]) {
     32     return -1;
     33   } else if(wavelength > brdf->wlen[1]) {
     34     return 1;
     35   } else {
     36     return 0;
     37   }
     38 }
     39 
     40 /*******************************************************************************
     41  * Exported functions
     42  ******************************************************************************/
     43 res_T
     44 mrumtl_fetch_brdf
     45   (const struct mrumtl* mrumtl,
     46    const double wavelength,
     47    const double sample, /* In [0, 1[ */
     48    size_t* out_ibrdf)
     49 {
     50   const struct mrumtl_brdf* brdfs = NULL;
     51   const struct mrumtl_brdf* brdf = NULL;
     52   size_t nbrdfs = 0;
     53   size_t ibrdf = 0;
     54   res_T res = RES_OK;
     55 
     56   if(!mrumtl
     57   || wavelength < 0
     58   || sample < 0
     59   || sample >= 1
     60   || !out_ibrdf) {
     61     res = RES_BAD_ARG;
     62     goto error;
     63   }
     64 
     65   brdfs = darray_brdf_cdata_get(&mrumtl->brdfs);
     66   nbrdfs = darray_brdf_size_get(&mrumtl->brdfs);
     67 
     68   if(!nbrdfs) {
     69     log_warn(mrumtl, "%s: no BRDF to fetch.\n", FUNC_NAME);
     70     *out_ibrdf = 0;
     71     goto exit;
     72   }
     73 
     74   brdf = search_lower_bound
     75     (&wavelength, brdfs, nbrdfs, sizeof(*brdfs), cmp_brdf);
     76 
     77   /* All BRDFs are set for a wavelength greater or equal to the submitted
     78    * wavelength */
     79   if(brdf == brdfs) {
     80     ASSERT(brdfs[0].wlen[0] > wavelength 
     81        || (brdfs[0].wlen[0] <= wavelength && wavelength <= brdfs[0].wlen[1]));
     82     ibrdf = 0;
     83   }
     84 
     85   /* All BRDFs are set for a wavelength less than the submitted wavelength */
     86   else if(!brdf) {
     87     ASSERT(brdfs[nbrdfs-1].wlen[1] < wavelength);
     88     ibrdf = nbrdfs - 1;
     89   }
     90 
     91   /* The wavelength range of the found brdf function overlaps the submitted
     92    * wavelength */
     93   else if(wavelength >= brdf->wlen[0] && wavelength <= brdf->wlen[1]) {
     94     ibrdf = (size_t)(brdf - brdfs);
     95   }
     96 
     97   /* The found BRDF is defined for a wavelength greater or equal to the
     98    * submitted wavelength */
     99   else {
    100     /* Compute the linear interpolation parameter that defines the submitted
    101      * wavelength wrt to the wavelenths boundaries of the BRDF surrounding it*/
    102     const struct mrumtl_brdf* brdf0 = brdf-1;
    103     const struct mrumtl_brdf* brdf1 = brdf;
    104     const double u =
    105       (brdf1->wlen[0] - wavelength)
    106     / (brdf1->wlen[0] - brdf0->wlen[1]);
    107 
    108     /* Consider the linear interplation parameter previously defined as a
    109      * probability and use the submitted sample to select one of the BRDFs
    110      * surrounding the submitted wavelength. */
    111     if(sample < u) {
    112       ibrdf = (size_t)(brdf - brdfs - 1);
    113     } else {
    114       ibrdf = (size_t)(brdf - brdfs);
    115     }
    116   }
    117 
    118   ASSERT(ibrdf < nbrdfs);
    119   *out_ibrdf = ibrdf;
    120 
    121 exit:
    122   return res;
    123 error:
    124   goto exit;
    125 }