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 }