htrdr

Solving radiative transfer in heterogeneous media
git clone git://git.meso-star.fr/htrdr.git
Log | Files | Refs | README | LICENSE

htrdr_atmosphere_ground.c (7928B)


      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 
     25 #include "atmosphere/htrdr_atmosphere_ground.h"
     26 
     27 #include "core/htrdr_log.h"
     28 #include "core/htrdr_geometry.h"
     29 #include "core/htrdr_slab.h"
     30 
     31 #include <star/s3d.h>
     32 
     33 #include <rsys/cstr.h>
     34 #include <rsys/double2.h>
     35 #include <rsys/double3.h>
     36 #include <rsys/mem_allocator.h>
     37 #include <rsys/ref_count.h>
     38 
     39 struct trace_slab_context {
     40   struct htrdr_geometry* geom;
     41   const struct s3d_hit* hit_prev;
     42   struct s3d_hit* hit;
     43 };
     44 #define TRACE_SLAB_CONTEXT_NULL__ { NULL, NULL, NULL }
     45 static const struct trace_slab_context TRACE_SLAB_CONTEXT_NULL =
     46     TRACE_SLAB_CONTEXT_NULL__;
     47 
     48 struct htrdr_atmosphere_ground {
     49   struct htrdr_geometry* geom;
     50   int repeat; /* Make the ground infinite in X and Y */
     51   struct htrdr* htrdr;
     52   ref_T ref;
     53 };
     54 
     55 /*******************************************************************************
     56  * Helper functions
     57  ******************************************************************************/
     58 static INLINE res_T
     59 trace_slab
     60   (const double org[3],
     61    const double dir[3],
     62    const double range[2],
     63    void* context,
     64    int* hit)
     65 {
     66   struct trace_slab_context* ctx = context;
     67   struct htrdr_geometry_trace_ray_args rt_args =
     68     HTRDR_GEOMETRY_TRACE_RAY_ARGS_NULL;
     69   res_T res = RES_OK;
     70   ASSERT(org && dir && range && context && hit);
     71 
     72   d3_set(rt_args.ray_org, org);
     73   d3_set(rt_args.ray_dir, dir);
     74   d2_set(rt_args.ray_range, range);
     75   rt_args.hit_from = ctx->hit_prev ? *ctx->hit_prev : S3D_HIT_NULL;
     76   res = htrdr_geometry_trace_ray(ctx->geom, &rt_args, ctx->hit);
     77   if(res != RES_OK) return res;
     78 
     79   *hit = !S3D_HIT_NONE(ctx->hit);
     80   return RES_OK;
     81 }
     82 static void
     83 release_ground(ref_T* ref)
     84 {
     85   struct htrdr_atmosphere_ground* ground;
     86   struct htrdr* htrdr;
     87   ASSERT(ref);
     88   ground = CONTAINER_OF(ref, struct htrdr_atmosphere_ground, ref);
     89   if(ground->geom) htrdr_geometry_ref_put(ground->geom);
     90   htrdr = ground->htrdr;
     91   MEM_RM(htrdr_get_allocator(ground->htrdr), ground);
     92   htrdr_ref_put(htrdr);
     93 }
     94 
     95 /*******************************************************************************
     96  * Local functions
     97  ******************************************************************************/
     98 res_T
     99 htrdr_atmosphere_ground_create
    100   (struct htrdr* htrdr,
    101    const char* obj_filename, /* May be NULL */
    102    struct htrdr_materials* mats, /* May be NULL */
    103    const int repeat_ground, /* Infinitely repeat the ground in X and Y */
    104    struct htrdr_atmosphere_ground** out_ground)
    105 {
    106   struct htrdr_atmosphere_ground* ground = NULL;
    107   res_T res = RES_OK;
    108   ASSERT(htrdr && out_ground);
    109 
    110   ground = MEM_CALLOC(htrdr_get_allocator(htrdr), 1, sizeof(*ground));
    111   if(!ground) {
    112     res = RES_MEM_ERR;
    113     htrdr_log_err(htrdr,
    114       "%s: could not allocate the ground data structure -- %s.\n",
    115       FUNC_NAME, res_to_cstr(res));
    116     goto error;
    117   }
    118   ref_init(&ground->ref);
    119   ground->repeat = repeat_ground;
    120   htrdr_ref_get(htrdr);
    121   ground->htrdr = htrdr;
    122 
    123   if(!obj_filename) goto exit;
    124 
    125   if(!mats) {
    126     htrdr_log_err(htrdr, "%s: missing materials.\n", FUNC_NAME);
    127     res = RES_BAD_ARG;
    128     goto error;
    129   }
    130 
    131   res = htrdr_geometry_create(ground->htrdr, obj_filename, mats, &ground->geom);
    132   if(res != RES_OK) goto error;
    133 
    134 exit:
    135   *out_ground = ground;
    136   return res;
    137 error:
    138   if(ground) {
    139     htrdr_atmosphere_ground_ref_put(ground);
    140     ground = NULL;
    141   }
    142   goto exit;
    143 }
    144 
    145 void
    146 htrdr_atmosphere_ground_ref_get(struct htrdr_atmosphere_ground* ground)
    147 {
    148   ASSERT(ground);
    149   ref_get(&ground->ref);
    150 }
    151 
    152 void
    153 htrdr_atmosphere_ground_ref_put(struct htrdr_atmosphere_ground* ground)
    154 {
    155   ASSERT(ground);
    156   ref_put(&ground->ref, release_ground);
    157 }
    158 
    159 void
    160 htrdr_atmosphere_ground_get_interface
    161   (struct htrdr_atmosphere_ground* ground,
    162    const struct s3d_hit* hit,
    163    struct htrdr_interface* out_interface)
    164 {
    165   /* Simply wrap the geometry function */
    166   htrdr_geometry_get_interface(ground->geom, hit, out_interface);
    167 }
    168 
    169 res_T
    170 htrdr_atmosphere_ground_trace_ray
    171   (struct htrdr_atmosphere_ground* ground,
    172    const double org[3],
    173    const double dir[3], /* Must be normalized */
    174    const double range[2],
    175    const struct s3d_hit* prev_hit,
    176    struct s3d_hit* hit)
    177 {
    178   res_T res = RES_OK;
    179   ASSERT(ground && org && dir && range && hit);
    180 
    181   if(!ground->geom) { /* No ground geometry */
    182     *hit = S3D_HIT_NULL;
    183     goto exit;
    184   }
    185 
    186   if(!ground->repeat) {
    187     struct htrdr_geometry_trace_ray_args rt_args =
    188       HTRDR_GEOMETRY_TRACE_RAY_ARGS_NULL;
    189 
    190     d3_set(rt_args.ray_org, org);
    191     d3_set(rt_args.ray_dir, dir);
    192     d2_set(rt_args.ray_range, range);
    193     if(prev_hit) rt_args.hit_from = *prev_hit;
    194     res = htrdr_geometry_trace_ray(ground->geom, &rt_args, hit);
    195     if(res != RES_OK) goto error;
    196 
    197   } else {
    198     struct trace_slab_context slab_ctx = TRACE_SLAB_CONTEXT_NULL;
    199     double low[3], upp[3];
    200 
    201     htrdr_geometry_get_aabb(ground->geom, low, upp);
    202 
    203     *hit = S3D_HIT_NULL;
    204     slab_ctx.geom = ground->geom;
    205     slab_ctx.hit_prev = prev_hit;
    206     slab_ctx.hit = hit;
    207 
    208     res = htrdr_slab_trace_ray(ground->htrdr, org, dir, range, low, upp,
    209       trace_slab, 32, &slab_ctx);
    210     if(res != RES_OK) goto error;
    211   }
    212 
    213 exit:
    214   return res;
    215 error:
    216   goto exit;
    217 }
    218 
    219 res_T
    220 htrdr_atmosphere_ground_find_closest_point
    221   (struct htrdr_atmosphere_ground* ground,
    222    const double pos[3],
    223    const double radius,
    224    struct s3d_hit* hit)
    225 {
    226   double query_pos[3];
    227   double query_radius;
    228   res_T res = RES_OK;
    229   ASSERT(ground && pos && hit);
    230 
    231   if(!ground->geom) { /* No ground geometry */
    232     *hit = S3D_HIT_NULL;
    233     goto exit;
    234   }
    235 
    236   query_radius = radius;
    237   d3_set(query_pos, pos);
    238 
    239   if(ground->repeat) {
    240     double ground_low[3];
    241     double ground_upp[3];
    242     double ground_sz[3];
    243     double translation[2] = {0, 0};
    244     int64_t xy[2];
    245 
    246     /* Define the size of the ground geometry pattern */
    247     htrdr_geometry_get_aabb(ground->geom, ground_low, ground_upp);
    248     ground_sz[0] = ground_upp[0] - ground_low[0];
    249     ground_sz[1] = ground_upp[1] - ground_low[1];
    250     ground_sz[2] = ground_upp[2] - ground_low[2];
    251 
    252     /* Define the 2D index of the current ground instance. (0,0) is the index
    253      * of the non instantiated ground */
    254     xy[0] = (int64_t)floor((query_pos[0] - ground_low[0]) / ground_sz[0]);
    255     xy[1] = (int64_t)floor((query_pos[1] - ground_low[1]) / ground_sz[1]);
    256 
    257     /* Define the translation along the X and Y axis from world space to local
    258      * ground geometry space */
    259     translation[0] = -(double)xy[0] * ground_sz[0];
    260     translation[1] = -(double)xy[1] * ground_sz[1];
    261 
    262     /* Transform the query pos in local ground geometry space */
    263     query_pos[0] += translation[0];
    264     query_pos[1] += translation[1];
    265   }
    266 
    267   res = htrdr_geometry_find_closest_point
    268     (ground->geom, query_pos, query_radius, hit);
    269   if(res != RES_OK) goto error;
    270 
    271 exit:
    272   return res;
    273 error:
    274   goto exit;
    275 }