htrdr_atmosphere_sun.c (4674B)
1 /* Copyright (C) 2018-2019, 2022-2025 Centre National de la Recherche Scientifique 2 * Copyright (C) 2020-2022 Institut Mines Télécom Albi-Carmaux 3 * Copyright (C) 2022-2025 Institut Pierre-Simon Laplace 4 * Copyright (C) 2022-2025 Institut de Physique du Globe de Paris 5 * Copyright (C) 2018-2025 |Méso|Star> (contact@meso-star.com) 6 * Copyright (C) 2022-2025 Observatoire de Paris 7 * Copyright (C) 2022-2025 Université de Reims Champagne-Ardenne 8 * Copyright (C) 2022-2025 Université de Versaille Saint-Quentin 9 * Copyright (C) 2018-2019, 2022-2025 Université Paul Sabatier 10 * 11 * This program is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation, either version 3 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 23 24 #include "atmosphere/htrdr_atmosphere_c.h" 25 #include "atmosphere/htrdr_atmosphere_sun.h" 26 27 #include "core/htrdr.h" 28 #include "core/htrdr_log.h" 29 30 #include <rsys/algorithm.h> 31 #include <rsys/double33.h> 32 #include <rsys/ref_count.h> 33 #include <rsys/math.h> 34 35 #include <star/ssp.h> 36 37 struct htrdr_atmosphere_sun { 38 double half_angle; /* In radian */ 39 double cos_half_angle; 40 double solid_angle; /* In sr; solid_angle = 2*PI*(1 - cos(half_angle)) */ 41 double frame[9]; 42 double temperature; /* In K */ 43 44 ref_T ref; 45 struct htrdr* htrdr; 46 }; 47 48 /******************************************************************************* 49 * Helper functions 50 ******************************************************************************/ 51 static void 52 release_sun(ref_T* ref) 53 { 54 struct htrdr_atmosphere_sun* sun; 55 struct htrdr* htrdr; 56 ASSERT(ref); 57 sun = CONTAINER_OF(ref, struct htrdr_atmosphere_sun, ref); 58 htrdr = sun->htrdr; 59 MEM_RM(htrdr_get_allocator(htrdr), sun); 60 htrdr_ref_put(htrdr); 61 } 62 63 /******************************************************************************* 64 * Local functions 65 ******************************************************************************/ 66 res_T 67 htrdr_atmosphere_sun_create 68 (struct htrdr* htrdr, 69 struct htrdr_atmosphere_sun** out_sun) 70 { 71 const double main_dir[3] = {0, 0, 1}; /* Default main sun direction */ 72 struct htrdr_atmosphere_sun* sun = NULL; 73 res_T res = RES_OK; 74 ASSERT(htrdr && out_sun); 75 76 sun = MEM_CALLOC(htrdr_get_allocator(htrdr), 1, sizeof(*sun)); 77 if(!sun) { 78 htrdr_log_err(htrdr, "could not allocate the sun data structure.\n"); 79 res = RES_MEM_ERR; 80 goto error; 81 } 82 ref_init(&sun->ref); 83 84 sun->half_angle = 4.6524e-3; 85 sun->temperature = 5778; 86 sun->cos_half_angle = cos(sun->half_angle); 87 sun->solid_angle = 2*PI*(1-sun->cos_half_angle); 88 d33_basis(sun->frame, main_dir); 89 htrdr_ref_get(htrdr); 90 sun->htrdr = htrdr; 91 92 exit: 93 *out_sun = sun; 94 return res; 95 error: 96 if(sun) { 97 htrdr_atmosphere_sun_ref_put(sun); 98 sun = NULL; 99 } 100 goto exit; 101 } 102 103 void 104 htrdr_atmosphere_sun_ref_get(struct htrdr_atmosphere_sun* sun) 105 { 106 ASSERT(sun); 107 ref_get(&sun->ref); 108 } 109 110 void 111 htrdr_atmosphere_sun_ref_put(struct htrdr_atmosphere_sun* sun) 112 { 113 ASSERT(sun); 114 ref_put(&sun->ref, release_sun); 115 } 116 117 void 118 htrdr_atmosphere_sun_set_direction 119 (struct htrdr_atmosphere_sun* sun, 120 const double dir[3]) 121 { 122 ASSERT(sun && dir && d3_is_normalized(dir)); 123 d33_basis(sun->frame, dir); 124 } 125 126 double 127 htrdr_atmosphere_sun_sample_direction 128 (struct htrdr_atmosphere_sun* sun, 129 struct ssp_rng* rng, 130 double dir[3]) 131 { 132 ASSERT(sun && rng && dir); 133 ssp_ran_sphere_cap_uniform_local(rng, sun->cos_half_angle, dir, NULL); 134 d33_muld3(dir, sun->frame, dir); 135 return 1.0 / htrdr_atmosphere_sun_get_solid_angle(sun); 136 } 137 138 double 139 htrdr_atmosphere_sun_get_solid_angle(const struct htrdr_atmosphere_sun* sun) 140 { 141 ASSERT(sun); 142 return sun->solid_angle; 143 } 144 145 double 146 htrdr_atmosphere_sun_get_radiance 147 (const struct htrdr_atmosphere_sun* sun, 148 const double wlen/*In nm*/) 149 { 150 return htrdr_planck_monochromatic 151 (wlen*1.e-9/*From nm to m*/, sun->temperature); 152 } 153 154 int 155 htrdr_atmosphere_sun_is_dir_in_solar_cone 156 (const struct htrdr_atmosphere_sun* sun, 157 const double dir[3]) 158 { 159 const double* main_dir; 160 double dot; 161 ASSERT(sun && dir && d3_is_normalized(dir)); 162 ASSERT(d3_is_normalized(sun->frame + 6)); 163 main_dir = sun->frame + 6; 164 dot = d3_dot(dir, main_dir); 165 return dot >= sun->cos_half_angle; 166 } 167