sdis_scene_c.h (11364B)
1 /* Copyright (C) 2016-2025 |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 #ifndef SDIS_SCENE_C_H 17 #define SDIS_SCENE_C_H 18 19 #include <star/s2d.h> 20 #include <star/s3d.h> 21 22 #include <rsys/dynamic_array_uint.h> 23 #include <rsys/hash.h> 24 #include <rsys/hash_table.h> 25 #include <rsys/ref_count.h> 26 27 #include <limits.h> 28 29 #define MEDIUM_ID_MULTI UINT_MAX 30 #define ENCLOSURE_ID_NULL UINT_MAX 31 32 struct prim_prop { 33 struct sdis_interface* interf; 34 unsigned front_enclosure; /* Id of the front facing enclosure */ 35 unsigned back_enclosure; /* Id of the back facing enclosure */ 36 }; 37 38 struct hit_filter_data { 39 struct s2d_hit hit_2d; 40 struct s3d_hit hit_3d; 41 double epsilon; /* Threshold defining roughly equal intersections */ 42 43 /* When a scene is defined, primitives that do not point to the defined 44 * enclosure are filtered out */ 45 struct sdis_scene* scn; /* NULL <=> do not filter wrt enc_id */ 46 unsigned enc_id; 47 48 /* Bypass the regular filter function */ 49 s2d_hit_filter_function_T custom_filter_2d; 50 s3d_hit_filter_function_T custom_filter_3d; 51 52 /* Custom filter query data. It is ignored if custom_filter is NULL */ 53 void* custom_filter_data; 54 }; 55 #define HIT_FILTER_DATA_NULL__ \ 56 {S2D_HIT_NULL__,S3D_HIT_NULL__,0,NULL,ENCLOSURE_ID_NULL,NULL,NULL,NULL} 57 static const struct hit_filter_data HIT_FILTER_DATA_NULL = 58 HIT_FILTER_DATA_NULL__; 59 60 static INLINE void 61 prim_prop_init(struct mem_allocator* allocator, struct prim_prop* prim) 62 { 63 (void)allocator; 64 prim->interf = NULL; 65 prim->front_enclosure = UINT_MAX; 66 prim->back_enclosure = UINT_MAX; 67 } 68 69 static INLINE void 70 interface_init(struct mem_allocator* allocator, struct sdis_interface** interf) 71 { 72 (void)allocator; 73 *interf = NULL; 74 } 75 76 static INLINE void 77 medium_init(struct mem_allocator* allocator, struct sdis_medium** medium) 78 { 79 (void)allocator; 80 *medium = NULL; 81 } 82 83 struct enclosure { 84 struct s2d_scene_view* s2d_view; 85 struct s3d_scene_view* s3d_view; 86 /* Map the id of the enclosure primitives to their primitive id into the 87 * whole scene */ 88 struct darray_uint local2global; 89 90 double hc_upper_bound; 91 double S_over_V; /* in 3D = surface/volume; in 2D = perimeter/area */ 92 double V; /* 3D = volume; 2D = area; */ 93 94 unsigned medium_id; 95 }; 96 97 static INLINE void 98 enclosure_init(struct mem_allocator* allocator, struct enclosure* enc) 99 { 100 ASSERT(allocator && enc); 101 enc->s2d_view = NULL; 102 enc->s3d_view = NULL; 103 darray_uint_init(allocator, &enc->local2global); 104 enc->S_over_V = 0; 105 enc->V = 0; 106 enc->hc_upper_bound = 0; 107 enc->medium_id = MEDIUM_ID_MULTI; 108 } 109 110 static INLINE void 111 enclosure_release(struct enclosure* enc) 112 { 113 if(enc->s2d_view) S2D(scene_view_ref_put(enc->s2d_view)); 114 if(enc->s3d_view) S3D(scene_view_ref_put(enc->s3d_view)); 115 darray_uint_release(&enc->local2global); 116 } 117 118 static INLINE res_T 119 enclosure_copy(struct enclosure* dst, const struct enclosure* src) 120 { 121 if(src->s3d_view) { 122 S3D(scene_view_ref_get(src->s3d_view)); 123 dst->s3d_view = src->s3d_view; 124 } 125 if(src->s2d_view) { 126 S2D(scene_view_ref_get(src->s2d_view)); 127 dst->s2d_view = src->s2d_view; 128 } 129 dst->S_over_V = src->S_over_V; 130 dst->V = src->V; 131 dst->hc_upper_bound = src->hc_upper_bound; 132 dst->medium_id = src->medium_id; 133 return darray_uint_copy(&dst->local2global, &src->local2global); 134 } 135 136 static INLINE res_T 137 enclosure_copy_and_release(struct enclosure* dst, struct enclosure* src) 138 { 139 res_T res = RES_OK; 140 res = darray_uint_copy_and_release(&dst->local2global, &src->local2global); 141 if(res != RES_OK) return res; 142 if(src->s3d_view) { 143 /* Only transfer ownership */ 144 dst->s3d_view = src->s3d_view; 145 src->s3d_view = NULL; 146 } 147 if(src->s2d_view) { 148 /* Only transfer ownership */ 149 dst->s2d_view = src->s2d_view; 150 src->s2d_view = NULL; 151 } 152 dst->S_over_V = src->S_over_V; 153 dst->V = src->V; 154 dst->hc_upper_bound = src->hc_upper_bound; 155 dst->medium_id = src->medium_id; 156 return RES_OK; 157 } 158 159 static INLINE unsigned 160 enclosure_local2global_prim_id 161 (const struct enclosure* enc, 162 const size_t local_prim_id) 163 { 164 ASSERT(enc && local_prim_id < darray_uint_size_get(&enc->local2global)); 165 return darray_uint_cdata_get(&enc->local2global)[local_prim_id]; 166 } 167 168 static INLINE void 169 primkey_init 170 (const struct mem_allocator* allocator, 171 struct sdis_primkey* key) 172 { 173 ASSERT(allocator && key); 174 (void)allocator; 175 *key = SDIS_PRIMKEY_NULL; 176 } 177 178 /* Declare the array of interfaces */ 179 #define DARRAY_NAME interf 180 #define DARRAY_DATA struct sdis_interface* 181 #define DARRAY_FUNCTOR_INIT interface_init 182 #include <rsys/dynamic_array.h> 183 184 /* Declare the array of media */ 185 #define DARRAY_NAME medium 186 #define DARRAY_DATA struct sdis_medium* 187 #define DARRAY_FUNCTOR_INIT medium_init 188 #include <rsys/dynamic_array.h> 189 190 /* Declare the array of primitives */ 191 #define DARRAY_NAME prim_prop 192 #define DARRAY_DATA struct prim_prop 193 #define DARRAY_FUNCTOR_INIT prim_prop_init 194 #include <rsys/dynamic_array.h> 195 196 /* Declare the hash table that maps an enclosure id to its data */ 197 #define HTABLE_NAME enclosure 198 #define HTABLE_KEY unsigned 199 #define HTABLE_DATA struct enclosure 200 #define HTABLE_DATA_FUNCTOR_INIT enclosure_init 201 #define HTABLE_DATA_FUNCTOR_RELEASE enclosure_release 202 #define HTABLE_DATA_FUNCTOR_COPY enclosure_copy 203 #define HTABLE_DATA_FUNCTOR_COPY_AND_RELEASE enclosure_copy_and_release 204 #include <rsys/hash_table.h> 205 206 /* Declare the hash table that maps an enclosure id to hc upper bound */ 207 #define HTABLE_NAME d 208 #define HTABLE_KEY unsigned 209 #define HTABLE_DATA double 210 #include <rsys/hash_table.h> 211 212 /* Declare the hash table that maps the primitive key to its 2D primitve */ 213 #define HTABLE_NAME key2prim2d 214 #define HTABLE_KEY struct sdis_primkey 215 #define HTABLE_KEY_FUNCTOR_INIT primkey_init 216 #define HTABLE_KEY_FUNCTOR_HASH sdis_primkey_hash 217 #define HTABLE_KEY_FUNCTOR_EQ sdis_primkey_eq 218 #define HTABLE_DATA struct s2d_primitive 219 #include <rsys/hash_table.h> 220 221 /* Declare the hash table that maps the primitive key to its 3D primitive */ 222 #define HTABLE_NAME key2prim3d 223 #define HTABLE_KEY struct sdis_primkey 224 #define HTABLE_KEY_FUNCTOR_INIT primkey_init 225 #define HTABLE_KEY_FUNCTOR_HASH sdis_primkey_hash 226 #define HTABLE_KEY_FUNCTOR_EQ sdis_primkey_eq 227 #define HTABLE_DATA struct s3d_primitive 228 #include <rsys/hash_table.h> 229 230 struct sdis_scene { 231 struct darray_interf interfaces; /* List of interfaces own by the scene */ 232 struct darray_medium media; /* List of media own by the scene */ 233 struct darray_prim_prop prim_props; /* Per primitive properties */ 234 struct s2d_scene_view* s2d_view; 235 struct s3d_scene_view* s3d_view; 236 struct senc2d_scene* senc2d_scn; 237 struct senc3d_scene* senc3d_scn; 238 239 struct htable_d tmp_hc_ub; /* Map an enclosure id to its hc upper bound */ 240 struct htable_enclosure enclosures; /* Map an enclosure id to its data */ 241 unsigned outer_enclosure_id; 242 243 /* Map a primivei key to its Star-2D/Star-3D primitive */ 244 struct htable_key2prim2d key2prim2d; 245 struct htable_key2prim3d key2prim3d; 246 247 double fp_to_meter; 248 double tmin; /* Minimum temperature of the system (In Kelvin) */ 249 double tmax; /* Maximum temperature of the system (In Kelvin) */ 250 251 struct sdis_source* source; /* External source. May be NULL */ 252 struct sdis_radiative_env* radenv; /* Radiative environment. May be NULL */ 253 254 ref_T ref; 255 struct sdis_device* dev; 256 }; 257 258 static FINLINE size_t 259 scene_get_primitives_count(const struct sdis_scene* scn) 260 { 261 ASSERT(scn); 262 return darray_prim_prop_size_get(&scn->prim_props); 263 } 264 265 extern LOCAL_SYM struct sdis_interface* 266 scene_get_interface 267 (const struct sdis_scene* scene, 268 const unsigned iprim); 269 270 extern LOCAL_SYM res_T 271 scene_get_enclosure_id 272 (struct sdis_scene* scene, 273 const double position[], 274 unsigned* enclosure_id); 275 276 /* This function assumes that the position under test lies within a finite 277 * enclosure. The enclosure in which it is located is therefore retrieved by 278 * tracing a random ray around the current position. For infinite enclosures, 279 * you need to use the `scene_get_enclosure_id' function, which in turn may take 280 * longer. 281 * 282 * Note that the function actually calls scene_get_enclosure internally if no 283 * valid enclosure is found with the normal procedure. This may be due to 284 * numerical problems or incorrect assumptions about the current enclosure (its 285 * limits are open to infinity). */ 286 extern LOCAL_SYM res_T 287 scene_get_enclosure_id_in_closed_boundaries 288 (struct sdis_scene* scene, 289 const double position[], 290 unsigned* enclosure_id); 291 292 extern LOCAL_SYM res_T 293 scene_get_enclosure_medium 294 (struct sdis_scene* scene, 295 const struct enclosure* enclosure, 296 struct sdis_medium** medium); 297 298 extern LOCAL_SYM res_T 299 scene_compute_hash 300 (const struct sdis_scene* scn, 301 hash256_T hash); 302 303 /* Check that the primitive identifier is valid wrt the scene. If not, the 304 * function prints an error message and returns RES_BAD_ARG. */ 305 extern LOCAL_SYM res_T 306 scene_check_primitive_index 307 (const struct sdis_scene* scn, 308 const size_t iprim); 309 310 /* Check that the scene is 2D. If not, the function prints an error message and 311 * returns RES_BAD_ARG */ 312 extern LOCAL_SYM res_T 313 scene_check_dimensionality_2d 314 (const struct sdis_scene* scn); 315 316 /* Check that the scene is 3D. If not, the function prints an error message and 317 * returns RES_BAD_ARG */ 318 extern LOCAL_SYM res_T 319 scene_check_dimensionality_3d 320 (const struct sdis_scene* scn); 321 322 /* Check that the temperature range of the scene is well defined, i.e. that the 323 * minimum and maximum temperatures are known and that they define a valid 324 * range. If this is not the case, the function displays an error message and 325 * returns RES_BAD_ARG */ 326 extern LOCAL_SYM res_T 327 scene_check_temperature_range 328 (const struct sdis_scene* scn); 329 330 static INLINE void 331 scene_get_enclosure_ids 332 (const struct sdis_scene* scn, 333 const unsigned iprim, 334 unsigned encs[2]) /* Front and Back enclosure identifiers */ 335 { 336 ASSERT(scn && iprim < darray_prim_prop_size_get(&scn->prim_props)); 337 ASSERT(encs); 338 encs[0] = darray_prim_prop_cdata_get(&scn->prim_props)[iprim].front_enclosure; 339 encs[1] = darray_prim_prop_cdata_get(&scn->prim_props)[iprim].back_enclosure; 340 } 341 342 static INLINE int 343 scene_is_outside 344 (const struct sdis_scene* scn, 345 const enum sdis_side side, 346 const unsigned iprim) 347 { 348 unsigned encs[2]; 349 ASSERT(scn && scn->outer_enclosure_id != UINT_MAX); 350 scene_get_enclosure_ids(scn, iprim, encs); 351 return (encs[side] == scn->outer_enclosure_id); 352 } 353 354 static INLINE const struct enclosure* 355 scene_get_enclosure(struct sdis_scene* scn, const unsigned ienc) 356 { 357 const struct enclosure* enc = NULL; 358 ASSERT(scn); 359 enc = htable_enclosure_find(&scn->enclosures, &ienc); 360 return enc; 361 } 362 363 static INLINE int 364 scene_is_2d(const struct sdis_scene* scn) 365 { 366 ASSERT(scn && (scn->s2d_view || scn->s3d_view)); 367 return scn->s2d_view != NULL; 368 } 369 370 #endif /* SDIS_SCENE_C_H */ 371