htrdr

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

commit a1aef46023def6863cbdcda68cec023c96c1a463
parent ee7c9e6439f70ec2a427f9f2a2321cc6a6fa3379
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 16 Oct 2018 14:20:44 +0200

Add the ground data API

Diffstat:
Mcmake/CMakeLists.txt | 4+++-
Msrc/htrdr.c | 8+++++---
Msrc/htrdr.h | 3+--
Msrc/htrdr_compute_radiance_sw.c | 84+++++++------------------------------------------------------------------------
Asrc/htrdr_ground.c | 240+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/htrdr_ground.h | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/htrdr_sky.h | 2+-
7 files changed, 308 insertions(+), 84 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -24,7 +24,7 @@ option(NO_TEST "Do not build the tests" OFF) # Check dependencies ################################################################################ find_package(RCMake 0.3 REQUIRED) -find_package(RSys 0.6 REQUIRED) +find_package(RSys 0.7 REQUIRED) find_package(Star3D 0.5 REQUIRED) find_package(Star3DAW 0.3.1 REQUIRED) find_package(StarSF 0.6 REQUIRED) @@ -66,6 +66,7 @@ set(HTRDR_FILES_SRC htrdr_compute_radiance_sw.c htrdr_draw_radiance_sw.c htrdr_grid.c + htrdr_ground.c htrdr_main.c htrdr_rectangle.c htrdr_sky.c @@ -77,6 +78,7 @@ set(HTRDR_FILES_INC htrdr_buffer.h htrdr_camera.h htrdr_grid.h + htrdr_ground.h htrdr_rectangle.h htrdr_sky.h htrdr_sun.h diff --git a/src/htrdr.c b/src/htrdr.c @@ -20,6 +20,7 @@ #include "htrdr_args.h" #include "htrdr_buffer.h" #include "htrdr_camera.h" +#include "htrdr_ground.h" #include "htrdr_sky.h" #include "htrdr_sun.h" #include "htrdr_solve.h" @@ -29,7 +30,6 @@ #include <rsys/str.h> #include <star/s3d.h> -#include <star/s3daw.h> #include <star/ssf.h> #include <star/svx.h> @@ -149,6 +149,7 @@ error: goto exit; } +#if 0 static res_T setup_geometry(struct htrdr* htrdr, const char* filename) { @@ -210,6 +211,7 @@ exit: error: goto exit; } +#endif static res_T open_file_stamp @@ -370,7 +372,7 @@ htrdr_init goto error; } - res = setup_geometry(htrdr, args->filename_obj); + res = htrdr_ground_create(htrdr, args->filename_obj, 0, &htrdr->ground); if(res != RES_OK) goto error; proj_ratio = @@ -431,9 +433,9 @@ void htrdr_release(struct htrdr* htrdr) { ASSERT(htrdr); - if(htrdr->s3d_scn_view) S3D(scene_view_ref_put(htrdr->s3d_scn_view)); if(htrdr->s3d) S3D(device_ref_put(htrdr->s3d)); if(htrdr->svx) SVX(device_ref_put(htrdr->svx)); + if(htrdr->ground) htrdr_ground_ref_put(htrdr->ground); if(htrdr->sky) htrdr_sky_ref_put(htrdr->sky); if(htrdr->sun) htrdr_sun_ref_put(htrdr->sun); if(htrdr->cam) htrdr_camera_ref_put(htrdr->cam); diff --git a/src/htrdr.h b/src/htrdr.h @@ -45,8 +45,7 @@ struct htrdr { struct svx_device* svx; struct s3d_device* s3d; - struct s3d_scene_view* s3d_scn_view; - + struct htrdr_ground* ground; struct htrdr_sky* sky; struct htrdr_sun* sun; diff --git a/src/htrdr_compute_radiance_sw.c b/src/htrdr_compute_radiance_sw.c @@ -15,6 +15,7 @@ #include "htrdr.h" #include "htrdr_c.h" +#include "htrdr_ground.h" #include "htrdr_solve.h" #include "htrdr_sky.h" #include "htrdr_sun.h" @@ -28,14 +29,6 @@ #include <rsys/float2.h> #include <rsys/float3.h> -struct ray_context { - float range[2]; - struct s3d_hit hit_prev; -}; -static const struct ray_context RAY_CONTEXT_NULL = { - {0, INF}, S3D_HIT_NULL__ -}; - struct scattering_context { struct ssp_rng* rng; const struct htrdr_sky* sky; @@ -68,24 +61,6 @@ static const struct transmissivity_context TRANSMISSION_CONTEXT_NULL = { /******************************************************************************* * Helper functions ******************************************************************************/ -/* Check that `hit' roughly lies on an edge. For triangular primitives, a - * simple but approximative way is to test that its position have at least one - * barycentric coordinate roughly equal to 0 or 1. */ -static FINLINE int -hit_on_edge(const struct s3d_hit* hit) -{ - const float on_edge_eps = 1.e-4f; - float w; - ASSERT(hit && !S3D_HIT_NONE(hit)); - w = 1.f - hit->uv[0] - hit->uv[1]; - return eq_epsf(hit->uv[0], 0.f, on_edge_eps) - || eq_epsf(hit->uv[0], 1.f, on_edge_eps) - || eq_epsf(hit->uv[1], 0.f, on_edge_eps) - || eq_epsf(hit->uv[1], 1.f, on_edge_eps) - || eq_epsf(w, 0.f, on_edge_eps) - || eq_epsf(w, 1.f, on_edge_eps); -} - static int scattering_hit_filter (const struct svx_hit* hit, @@ -245,23 +220,12 @@ transmissivity struct s3d_hit s3d_hit; struct svx_hit svx_hit; struct transmissivity_context transmissivity_ctx = TRANSMISSION_CONTEXT_NULL; - struct ray_context rctx = RAY_CONTEXT_NULL; - float ray_pos[3]; - float ray_dir[3]; ASSERT(htrdr && rng && pos && dir && range); - /* Find the first intersection with a surface */ - f3_set_d3(ray_pos, pos); - f3_set_d3(ray_dir, dir); - f2_set_d2(rctx.range, range); - rctx.hit_prev = hit_prev ? *hit_prev : S3D_HIT_NULL; - S3D(scene_view_trace_ray(htrdr->s3d_scn_view, ray_pos, ray_dir, rctx.range, - &rctx, &s3d_hit)); - - if(!S3D_HIT_NONE(&s3d_hit)) { - return 0; - } + /* Check that the ray is not occlude along the submitted range */ + HTRDR(ground_trace_ray(htrdr->ground, pos, dir, range, hit_prev, &s3d_hit)); + if(!S3D_HIT_NONE(&s3d_hit)) return 0; transmissivity_ctx.rng = rng; transmissivity_ctx.sky = htrdr->sky; @@ -322,9 +286,6 @@ htrdr_compute_radiance_sw double w = 0; /* MC weight */ double g = 0; /* Asymmetry parameter of the HG phase function */ - float ray_pos[3]; - float ray_dir[3]; - ASSERT(htrdr && rng && pos_in && dir_in && ithread < htrdr->nthreads); CHK(RES_OK == ssf_bsdf_create @@ -366,17 +327,11 @@ htrdr_compute_radiance_sw /* Radiative random walk */ for(;;) { struct scattering_context scattering_ctx = SCATTERING_CONTEXT_NULL; - struct ray_context rctx = RAY_CONTEXT_NULL; - - /* Setup the ray to trace */ - f3_set_d3(ray_pos, pos); - f3_set_d3(ray_dir, dir); - f2(rctx.range, 0, FLT_MAX); - rctx.hit_prev = s3d_hit_prev; /* Find the first intersection with a surface */ - S3D(scene_view_trace_ray(htrdr->s3d_scn_view, ray_pos, ray_dir, rctx.range, - &rctx, &s3d_hit)); + d2(range, 0, DBL_MAX); + HTRDR(ground_trace_ray + (htrdr->ground, pos, dir, range, &s3d_hit_prev, &s3d_hit)); /* Sample an optical thickness */ scattering_ctx.Ts = ssp_ran_exp(rng, 1); @@ -481,28 +436,3 @@ htrdr_compute_radiance_sw return w; } -int -htrdr_ground_filter - (const struct s3d_hit* hit, - const float ray_org[3], - const float ray_dir[3], - void* ray_data, - void* filter_data) -{ - const struct ray_context* ray_ctx = ray_data; - (void)ray_org, (void)ray_dir, (void)filter_data; - - if(!ray_ctx) return 0; - - if(S3D_PRIMITIVE_EQ(&hit->prim, &ray_ctx->hit_prev.prim)) return 1; - - if(!S3D_HIT_NONE(&ray_ctx->hit_prev) && eq_epsf(hit->distance, 0, 1.e-1f)) { - /* If the targeted point is near of the origin, check that it lies on an - * edge/vertex shared by the 2 primitives. */ - return hit_on_edge(&ray_ctx->hit_prev) && hit_on_edge(hit); - } - - return hit->distance <= ray_ctx->range[0] - || hit->distance >= ray_ctx->range[1]; -} - diff --git a/src/htrdr_ground.c b/src/htrdr_ground.c @@ -0,0 +1,240 @@ +/* Copyright (C) 2018 Université Paul Sabatier, |Meso|Star> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "htrdr.h" +#include "htrdr_ground.h" + +#include <rsys/cstr.h> +#include <rsys/float2.h> +#include <rsys/float3.h> + +#include <star/s3d.h> +#include <star/s3daw.h> + +struct ray_context { + float range[2]; + struct s3d_hit hit_prev; +}; +static const struct ray_context RAY_CONTEXT_NULL = { + {0, INF}, S3D_HIT_NULL__ +}; + +struct htrdr_ground { + struct s3d_scene_view* view; + struct htrdr* htrdr; + int repeat; /* Make the ground infinite in X and Y */ + ref_T ref; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +/* Check that `hit' roughly lies on an edge. For triangular primitives, a + * simple but approximative way is to test that its position have at least one + * barycentric coordinate roughly equal to 0 or 1. */ +static FINLINE int +hit_on_edge(const struct s3d_hit* hit) +{ + const float on_edge_eps = 1.e-4f; + float w; + ASSERT(hit && !S3D_HIT_NONE(hit)); + w = 1.f - hit->uv[0] - hit->uv[1]; + return eq_epsf(hit->uv[0], 0.f, on_edge_eps) + || eq_epsf(hit->uv[0], 1.f, on_edge_eps) + || eq_epsf(hit->uv[1], 0.f, on_edge_eps) + || eq_epsf(hit->uv[1], 1.f, on_edge_eps) + || eq_epsf(w, 0.f, on_edge_eps) + || eq_epsf(w, 1.f, on_edge_eps); +} + +static int +ground_filter + (const struct s3d_hit* hit, + const float ray_org[3], + const float ray_dir[3], + void* ray_data, + void* filter_data) +{ + const struct ray_context* ray_ctx = ray_data; + (void)ray_org, (void)ray_dir, (void)filter_data; + + if(!ray_ctx) return 0; + + if(S3D_PRIMITIVE_EQ(&hit->prim, &ray_ctx->hit_prev.prim)) return 1; + + if(!S3D_HIT_NONE(&ray_ctx->hit_prev) && eq_epsf(hit->distance, 0, 1.e-1f)) { + /* If the targeted point is near of the origin, check that it lies on an + * edge/vertex shared by the 2 primitives. */ + return hit_on_edge(&ray_ctx->hit_prev) && hit_on_edge(hit); + } + + return hit->distance <= ray_ctx->range[0] + || hit->distance >= ray_ctx->range[1]; +} + +static void +release_ground(ref_T* ref) +{ + struct htrdr_ground* ground; + ASSERT(ref); + ground = CONTAINER_OF(ref, struct htrdr_ground, ref); + if(ground->view) S3D(scene_view_ref_put(ground->view)); + MEM_RM(ground->htrdr->allocator, ground); +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +htrdr_ground_create + (struct htrdr* htrdr, + const char* obj_filename, + const int repeat_ground, /* Infinitely repeat the ground in X and Y */ + struct htrdr_ground** out_ground) +{ + struct s3d_scene* scn = NULL; + struct s3daw* s3daw = NULL; + struct htrdr_ground* ground = NULL; + size_t ishape; + size_t nshapes; + res_T res = RES_OK; + ASSERT(htrdr && obj_filename && out_ground); + + ground = MEM_CALLOC(htrdr->allocator, 1, sizeof(*ground)); + if(!ground) { + res = RES_MEM_ERR; + htrdr_log_err(htrdr, + "%s: could not allocate the ground data structure -- %s.\n", + FUNC_NAME, res_to_cstr(res)); + goto error; + } + ref_init(&ground->ref); + ground->htrdr = htrdr; + ground->repeat = repeat_ground; + + res = s3daw_create(&htrdr->logger, htrdr->allocator, NULL, NULL, htrdr->s3d, + htrdr->verbose, &s3daw); + if(res != RES_OK) { + htrdr_log_err(htrdr, + "%s: could not create the Star-3DAW device -- %s.\n", + FUNC_NAME, res_to_cstr(res)); + goto error; + } + + res = s3daw_load(s3daw, obj_filename); + if(res != RES_OK) { + htrdr_log_err(htrdr, "%s: could not load the obj file `%s' -- %s.\n", + FUNC_NAME, obj_filename, res_to_cstr(res)); + goto error; + } + + res = s3d_scene_create(htrdr->s3d, &scn); + if(res != RES_OK) { + htrdr_log_err(htrdr, + "%s: could not create the Star-3D scene of the ground -- %s.\n", + FUNC_NAME, res_to_cstr(res)); + goto error; + } + + S3DAW(get_shapes_count(s3daw, &nshapes)); + FOR_EACH(ishape, 0, nshapes) { + struct s3d_shape* shape; + S3DAW(get_shape(s3daw, ishape, &shape)); + res = s3d_mesh_set_hit_filter_function(shape, ground_filter, NULL); + if(res != RES_OK) { + htrdr_log_err(htrdr, + "%s: could not setup the hit filter function of the ground geometry " + "-- %s.\n", FUNC_NAME, res_to_cstr(res)); + goto error; + } + res = s3d_scene_attach_shape(scn, shape); + if(res != RES_OK) { + htrdr_log_err(htrdr, + "%s: could not attach the ground geometry to its Star-3D scene -- %s.\n", + FUNC_NAME, res_to_cstr(res)); + goto error; + } + } + + res = s3d_scene_view_create(scn, S3D_TRACE, &ground->view); + if(res != RES_OK) { + htrdr_log_err(htrdr, + "%s: could not create the Star-3D scene view of the ground geometry " + "-- %s.\n", FUNC_NAME, res_to_cstr(res)); + goto error; + } + +exit: + if(s3daw) S3DAW(ref_put(s3daw)); + if(scn) S3D(scene_ref_put(scn)); + *out_ground = ground; + return res; +error: + if(ground) { + htrdr_ground_ref_put(ground); + ground = NULL; + } + goto exit; +} + +void +htrdr_ground_ref_get(struct htrdr_ground* ground) +{ + ASSERT(ground); + ref_get(&ground->ref); +} + +void +htrdr_ground_ref_put(struct htrdr_ground* ground) +{ + ASSERT(ground); + ref_put(&ground->ref, release_ground); +} + +res_T +htrdr_ground_trace_ray + (struct htrdr_ground* ground, + const double org[3], + const double dir[3], /* Must be normalized */ + const double range[2], + const struct s3d_hit* prev_hit, + struct s3d_hit* hit) +{ + struct ray_context ctx = RAY_CONTEXT_NULL; + float ray_org[3]; + float ray_dir[3]; + res_T res = RES_OK; + ASSERT(ground && org && dir && range && hit); + + f3_set_d3(ray_org, org); + f3_set_d3(ray_dir, dir); + f2_set_d2(ctx.range, range); + ctx.hit_prev = prev_hit ? *prev_hit : S3D_HIT_NULL; + + res = s3d_scene_view_trace_ray + (ground->view, ray_org, ray_dir, ctx.range, &ctx, hit); + if(res != RES_OK) { + htrdr_log_err(ground->htrdr, + "%s: could not trace the ray against the ground geometry -- %s.\n", + FUNC_NAME, res_to_cstr(res)); + goto error; + } + +exit: + return res; +error: + goto exit; +} + diff --git a/src/htrdr_ground.h b/src/htrdr_ground.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2018 Université Paul Sabatier, |Meso|Star> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef HTRDR_GROUND_H +#define HTRDR_GROUND_H + +#include <rsys/rsys.h> + +/* Forward declarations */ +struct htrdr; +struct htrdr_ground; +struct s3d_hit; + +extern LOCAL_SYM res_T +htrdr_ground_create + (struct htrdr* htrdr, + const char* obj_filename, + const int repeat_ground, /* Infinitely repeat the ground in X and Y */ + struct htrdr_ground** ground); + +extern LOCAL_SYM void +htrdr_ground_ref_get + (struct htrdr_ground* ground); + +extern LOCAL_SYM void +htrdr_ground_ref_put + (struct htrdr_ground* ground); + +extern LOCAL_SYM res_T +htrdr_ground_trace_ray + (struct htrdr_ground* ground, + const double ray_origin[3], + const double ray_direction[3], /* Must be normalized */ + const double ray_range[2], + const struct s3d_hit* prev_hit,/* Previous hit. Avoid self hit. May be NULL*/ + struct s3d_hit* hit); + +#endif /* HTRDR_GROUND_H */ + diff --git a/src/htrdr_sky.h b/src/htrdr_sky.h @@ -64,7 +64,7 @@ htrdr_sky_create const char* htgop_filename, const char* htmie_filename, const double optical_thickness, /* Threshold used during octree building */ - const int repeat_clouds, /* Infinitly repeat the clouds in X and Y */ + const int repeat_clouds, /* Infinitely repeat the clouds in X and Y */ struct htrdr_sky** sky); extern LOCAL_SYM void