solstice_sun.c (7629B)
1 /* Copyright (C) 2018-2026 |Meso|Star> (contact@meso-star.com) 2 * Copyright (C) 2016-2018 CNRS 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #include "solstice_c.h" 18 #include "solstice_sun_spectrum.h" 19 #include "parser/solparser.h" 20 #include "parser/solparser_sun.h" 21 22 #include <solstice/ssol.h> 23 24 /******************************************************************************* 25 * Helper functions 26 ******************************************************************************/ 27 static res_T 28 create_sun_buie 29 (struct solstice* solstice, 30 const struct solparser_sun* solparser_sun, 31 struct ssol_sun** out_sun) 32 { 33 struct ssol_sun* sun = NULL; 34 res_T res = RES_OK; 35 ASSERT(solstice && solparser_sun && out_sun); 36 ASSERT(solparser_sun->radang_distrib_type == SOLPARSER_SUN_RADANG_DISTRIB_BUIE); 37 38 res = ssol_sun_create_buie(solstice->ssol, &sun); 39 if(res != RES_OK) { 40 fprintf(stderr, "Could not create the solver buie sun.\n"); 41 goto error; 42 } 43 44 res = ssol_sun_set_buie_param(sun, solparser_sun->radang_distrib.buie.csr); 45 if(res != RES_OK) { 46 fprintf(stderr, "Could setup the buie parameter of the solver sun.\n"); 47 goto error; 48 } 49 50 exit: 51 *out_sun = sun; 52 return res; 53 error: 54 if(sun) { 55 SSOL(sun_ref_put(sun)); 56 sun = NULL; 57 } 58 goto exit; 59 } 60 61 static res_T 62 create_sun_dir 63 (struct solstice* solstice, 64 const struct solparser_sun* solparser_sun, 65 struct ssol_sun** out_sun) 66 { 67 struct ssol_sun* sun = NULL; 68 res_T res = RES_OK; 69 (void)solparser_sun; 70 ASSERT(solstice && solparser_sun && out_sun); 71 ASSERT(solparser_sun->radang_distrib_type 72 == SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL); 73 74 res = ssol_sun_create_directional(solstice->ssol, &sun); 75 if(res != RES_OK) { 76 fprintf(stderr, "Could not create the solver directional sun.\n"); 77 goto error; 78 } 79 80 exit: 81 *out_sun = sun; 82 return res; 83 error: 84 if(sun) { 85 SSOL(sun_ref_put(sun)); 86 sun = NULL; 87 } 88 goto exit; 89 } 90 91 static res_T 92 create_sun_pillbox 93 (struct solstice* solstice, 94 const struct solparser_sun* solparser_sun, 95 struct ssol_sun** out_sun) 96 { 97 struct ssol_sun* sun = NULL; 98 res_T res = RES_OK; 99 ASSERT(solstice && solparser_sun && out_sun); 100 ASSERT(solparser_sun->radang_distrib_type 101 == SOLPARSER_SUN_RADANG_DISTRIB_PILLBOX); 102 103 res = ssol_sun_create_pillbox(solstice->ssol, &sun); 104 if(res != RES_OK) { 105 fprintf(stderr, "Could not create the solver pillbox sun.\n"); 106 goto error; 107 } 108 109 res = ssol_sun_pillbox_set_half_angle 110 (sun, MDEG2RAD(solparser_sun->radang_distrib.pillbox.half_angle)); 111 if(res != RES_OK) { 112 fprintf(stderr, "Could not setup half_angle for the solver pillbox sun.\n"); 113 goto error; 114 } 115 116 exit: 117 *out_sun = sun; 118 return res; 119 error: 120 if(sun) { 121 SSOL(sun_ref_put(sun)); 122 sun = NULL; 123 } 124 goto exit; 125 } 126 127 static res_T 128 create_sun_gaussian 129 (struct solstice* solstice, 130 const struct solparser_sun* solparser_sun, 131 struct ssol_sun** out_sun) 132 { 133 struct ssol_sun* sun = NULL; 134 res_T res = RES_OK; 135 ASSERT(solstice && solparser_sun && out_sun); 136 ASSERT(solparser_sun->radang_distrib_type 137 == SOLPARSER_SUN_RADANG_DISTRIB_GAUSSIAN); 138 139 res = ssol_sun_create_gaussian(solstice->ssol, &sun); 140 if(res != RES_OK) { 141 fprintf(stderr, "Could not create the solver gaussian sun.\n"); 142 goto error; 143 } 144 145 res = ssol_sun_gaussian_set_std_dev 146 (sun, MDEG2RAD(solparser_sun->radang_distrib.gaussian.std_dev)); 147 if(res != RES_OK) { 148 fprintf(stderr, "Could not setup standard deviation for the solver gaussian sun.\n"); 149 goto error; 150 } 151 152 exit: 153 *out_sun = sun; 154 return res; 155 error: 156 if(sun) { 157 SSOL(sun_ref_put(sun)); 158 sun = NULL; 159 } 160 goto exit; 161 } 162 163 static void 164 get_wavelength(const size_t i, double* wlen, double* data, void* ctx) 165 { 166 const double* spectrum = ctx; 167 ASSERT(wlen && data && ctx); 168 *wlen = spectrum[i*2+0]; 169 *data = spectrum[i*2+1]; 170 } 171 172 static res_T 173 create_default_sun_spectrum 174 (struct solstice* solstice, 175 const struct solparser_sun* solparser_sun, 176 struct ssol_spectrum** out_spectrum) 177 { 178 struct ssol_spectrum* spectrum = NULL; 179 const double* data; 180 size_t size; 181 res_T res = RES_OK; 182 183 /* The solparser_sun may be used if the default spectrum is defined wrt the 184 * sun type */ 185 (void)solparser_sun; 186 187 res = ssol_spectrum_create(solstice->ssol, &spectrum); 188 if(res != RES_OK) { 189 fprintf(stderr, "Could not create the spectrum of the solver sun.\n"); 190 goto error; 191 } 192 193 if(solparser_has_spectrum(solstice->parser)) { 194 data = solstice_sun_spectrum_smarts; 195 size = solstice_sun_spectrum_smarts_size; 196 } else { 197 data = solstice_sun_spectrum_dummy; 198 size = solstice_sun_spectrum_dummy_size; 199 } 200 201 res = ssol_spectrum_setup(spectrum, get_wavelength, size, (void*)data); 202 if(res != RES_OK) { 203 fprintf(stderr, "Coul not setup the default spectrum of the solver sun.\n"); 204 goto error; 205 } 206 207 exit: 208 *out_spectrum = spectrum; 209 return res; 210 error: 211 if(spectrum) { 212 SSOL(spectrum_ref_put(spectrum)); 213 spectrum = NULL; 214 } 215 goto exit; 216 } 217 218 /******************************************************************************* 219 * Local function 220 ******************************************************************************/ 221 res_T 222 solstice_create_sun(struct solstice* solstice) 223 { 224 struct ssol_sun* sun = NULL; 225 struct ssol_spectrum* spectrum = NULL; 226 const struct solparser_sun* solparser_sun = NULL; 227 res_T res = RES_OK; 228 ASSERT(solstice); 229 230 solparser_sun = solparser_get_sun(solstice->parser); 231 switch(solparser_sun->radang_distrib_type) { 232 case SOLPARSER_SUN_RADANG_DISTRIB_BUIE: 233 res = create_sun_buie(solstice, solparser_sun, &sun); 234 break; 235 case SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL: 236 res = create_sun_dir(solstice, solparser_sun, &sun); 237 break; 238 case SOLPARSER_SUN_RADANG_DISTRIB_PILLBOX: 239 res = create_sun_pillbox(solstice, solparser_sun, &sun); 240 break; 241 case SOLPARSER_SUN_RADANG_DISTRIB_GAUSSIAN: 242 res = create_sun_gaussian(solstice, solparser_sun, &sun); 243 break; 244 default: FATAL("Unreachable code.\n"); break; 245 } 246 if(res != RES_OK) goto error; 247 248 if(!SOLPARSER_ID_IS_VALID(solparser_sun->spectrum)) { 249 res = create_default_sun_spectrum(solstice, solparser_sun, &spectrum); 250 if(res != RES_OK) goto error; 251 } else { 252 res = solstice_create_ssol_spectrum 253 (solstice, solparser_sun->spectrum, &spectrum); 254 if(res != RES_OK) goto error; 255 } 256 257 res = ssol_sun_set_spectrum(sun, spectrum); 258 if(res != RES_OK) { 259 fprintf(stderr, "Could not attach the spectrum to the sun.\n"); 260 goto error; 261 } 262 263 res = ssol_sun_set_dni(sun, solparser_sun->dni); 264 if(res != RES_OK) { 265 fprintf(stderr, "Could not setup the DNI of the sun.\n"); 266 goto error; 267 } 268 269 res = ssol_scene_attach_sun(solstice->scene, sun); 270 if(res != RES_OK) { 271 fprintf(stderr, "Could not attach the sun to the scene.\n"); 272 goto error; 273 } 274 275 exit: 276 if(spectrum) SSOL(spectrum_ref_put(spectrum)); 277 solstice->sun = sun; 278 return res; 279 error: 280 if(sun) { 281 SSOL(sun_ref_put(sun)); 282 sun = NULL; 283 } 284 285 goto exit; 286 } 287