htrdr

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

commit 37560fc4845676aff50bd7b05006526854dbf3db
parent 83d0846ffa960ef792899254f0870b7474d745f2
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 27 Oct 2020 16:24:28 +0100

Rename the data structure and upd the material data

The ground geometry can not have use an undefined material anymore.
Consequently, semi-transparent materials must be listed in the submitted
htrdr-materials file. But since no mrumtl can be associated to such
materials in the htrdr-materials file, the new keyword "none" must be
used in place of the mrumtl filename.

Diffstat:
Mcmake/CMakeLists.txt | 6+++---
Msrc/htrdr.c | 6+++---
Msrc/htrdr.h | 3++-
Msrc/htrdr_ground.c | 44++++++++++++++++++++++++++++++--------------
Msrc/htrdr_interface.c | 25++++++++++++++-----------
Msrc/htrdr_interface.h | 7++++---
Asrc/htrdr_materials.c | 296+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/htrdr_materials.h | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/htrdr_mtl.c | 281-------------------------------------------------------------------------------
Dsrc/htrdr_mtl.h | 44--------------------------------------------
Msrc/htrdr_sensor.c | 11+++++------
11 files changed, 410 insertions(+), 366 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -28,7 +28,7 @@ find_package(AW 2.0 REQUIRED) find_package(HTSky 0.2 REQUIRED) find_package(MruMtl 0.0 REQUIRED) find_package(RCMake 0.3 REQUIRED) -find_package(RSys 0.7 REQUIRED) +find_package(RSys 0.11 REQUIRED) find_package(Star3D 0.7.1 REQUIRED) find_package(StarSF 0.6 REQUIRED) find_package(StarSP 0.8 REQUIRED) @@ -103,7 +103,7 @@ set(HTRDR_FILES_SRC htrdr_ground.c htrdr_interface.c htrdr_main.c - htrdr_mtl.c + htrdr_materials.c htrdr_ran_wlen.c htrdr_rectangle.c htrdr_sensor.c @@ -119,7 +119,7 @@ set(HTRDR_FILES_INC htrdr_grid.h htrdr_ground.h htrdr_interface.h - htrdr_mtl.h + htrdr_materials.h htrdr_ran_wlen.h htrdr_rectangle.h htrdr_sensor.h diff --git a/src/htrdr.c b/src/htrdr.c @@ -23,7 +23,7 @@ #include "htrdr_cie_xyz.h" #include "htrdr_camera.h" #include "htrdr_ground.h" -#include "htrdr_mtl.h" +#include "htrdr_materials.h" #include "htrdr_ran_wlen.h" #include "htrdr_rectangle.h" #include "htrdr_sun.h" @@ -532,7 +532,7 @@ htrdr_init /* Materials are necessary only if a ground geometry is defined */ if(args->filename_obj) { - res = htrdr_mtl_create(htrdr, args->filename_mtl, &htrdr->mtl); + res = htrdr_materials_create(htrdr, args->filename_mtl, &htrdr->mats); if(res != RES_OK) goto error; } @@ -661,7 +661,7 @@ htrdr_release(struct htrdr* htrdr) if(htrdr->sensor.camera) htrdr_camera_ref_put(htrdr->sensor.camera); if(htrdr->sensor.rectangle) htrdr_rectangle_ref_put(htrdr->sensor.rectangle); if(htrdr->buf) htrdr_buffer_ref_put(htrdr->buf); - if(htrdr->mtl) htrdr_mtl_ref_put(htrdr->mtl); + if(htrdr->mats) htrdr_materials_ref_put(htrdr->mats); if(htrdr->cie) htrdr_cie_xyz_ref_put(htrdr->cie); if(htrdr->ran_wlen) htrdr_ran_wlen_ref_put(htrdr->ran_wlen); if(htrdr->output && htrdr->output != stdout) fclose(htrdr->output); diff --git a/src/htrdr.h b/src/htrdr.h @@ -38,6 +38,7 @@ struct htsky; struct htrdr_args; struct htrdr_buffer; struct htrdr_cie_xyz; +struct htrdr_materials; struct htrdr_rectangle; struct mem_allocator; struct mutext; @@ -50,7 +51,7 @@ struct htrdr { struct s3d_device* s3d; struct htrdr_ground* ground; - struct htrdr_mtl* mtl; + struct htrdr_materials* mats; struct htrdr_sun* sun; struct htrdr_cie_xyz* cie; struct htrdr_ran_wlen* ran_wlen; diff --git a/src/htrdr_ground.c b/src/htrdr_ground.c @@ -17,7 +17,7 @@ #include "htrdr.h" #include "htrdr_interface.h" #include "htrdr_ground.h" -#include "htrdr_mtl.h" +#include "htrdr_materials.h" #include "htrdr_slab.h" #include <aw.h> @@ -168,6 +168,9 @@ parse_shape_interface char* mtl_name_thin = NULL; char* mtl_name_back = NULL; char* tk_ctx = NULL; + int has_front = 0; + int has_thin = 0; + int has_back = 0; res_T res = RES_OK; ASSERT(htrdr && name && interf); @@ -201,29 +204,42 @@ parse_shape_interface if(!mtl_name_back) { htrdr_log_err(htrdr, - "The material name of the shape back faces are missing `%s'.\n", name); + "The back material name is missing `%s'.\n", name); res = RES_BAD_ARG; goto error; } - /* Fetch the interface material */ + /* Fetch the interface material if any */ if(mtl_name_thin) { - interf->mtl_thin = htrdr_mtl_get(htrdr->mtl, mtl_name_thin); - if(!interf->mtl_thin) { + has_thin = htrdr_materials_find_mtl + (htrdr->mats, mtl_name_thin, &interf->mtl_thin); + if(!has_thin) { htrdr_log_err(htrdr, - "Invalid interface `%s:%s:%s'. " - "The material of the interface is unknown.\n", - mtl_name_front, mtl_name_thin, mtl_name_back); + "Invalid interface `%s'. The interface material `%s' is unknown.\n", + name, mtl_name_thin); res = RES_BAD_ARG; goto error; } } - /* Fetch the front/back materials */ - interf->mtl_front = htrdr_mtl_get(htrdr->mtl, mtl_name_front); - interf->mtl_back = htrdr_mtl_get(htrdr->mtl, mtl_name_back); - if(!interf->mtl_front && !interf->mtl_back && !interf->mtl_thin) { - htrdr_log_err(htrdr, "Invalid interface `%s'.\n", name); + /* Fetch the front material */ + has_front = htrdr_materials_find_mtl + (htrdr->mats, mtl_name_front, &interf->mtl_front); + if(!has_front) { + htrdr_log_err(htrdr, + "Invalid interface `%s'. The front material `%s' is unknown.\n", + name, mtl_name_front); + res = RES_BAD_ARG; + goto error; + } + + /* Fetch the back material */ + has_back = htrdr_materials_find_mtl + (htrdr->mats, mtl_name_back, &interf->mtl_back); + if(!has_back) { + htrdr_log_err(htrdr, + "Invalid interface `%s'. The back material `%s' is unknown.\n", + name, mtl_name_back); res = RES_BAD_ARG; goto error; } @@ -232,7 +248,7 @@ exit: str_release(&str); return res; error: - interf->mtl_front = interf->mtl_back = NULL; + *interf = HTRDR_INTERFACE_NULL; goto exit; } diff --git a/src/htrdr_interface.c b/src/htrdr_interface.c @@ -116,47 +116,50 @@ htrdr_interface_create_bsdf enum { FRONT, BACK }; struct ssf_bsdf* bsdf = NULL; const struct mrumtl_brdf* brdf = NULL; - const struct mrumtl* mat = NULL; + const struct htrdr_mtl* mtl = NULL; double N[3]; double r; int hit_side; res_T res = RES_OK; (void)pos; ASSERT(htrdr && pos && hit && out_bsdf); - ASSERT(interf && (interf->mtl_front || interf->mtl_back || interf->mtl_thin)); + ASSERT(interf && + ( interf->mtl_front.mrumtl + || interf->mtl_back.mrumtl + || interf->mtl_thin.mrumtl)); ASSERT(htrdr && interf && pos && dir && hit && out_bsdf); ASSERT(d3_is_normalized(dir)); - if(interf->mtl_thin) { - mat = interf->mtl_thin; + if(interf->mtl_thin.mrumtl) { + mtl = &interf->mtl_thin; } else { d3_normalize(N, d3_set_f3(N, hit->normal)); hit_side = d3_dot(N, dir) < 0 ? FRONT : BACK; /* Retrieve the brdf of the material on the other side of the hit side */ switch(hit_side) { - case BACK: mat = interf->mtl_front; break; - case FRONT: mat = interf->mtl_back; break; + case BACK: mtl = &interf->mtl_front; break; + case FRONT: mtl = &interf->mtl_back; break; default: FATAL("Unreachable code.\n"); break; } /* Due to numerical issue the hit side might be wrong and thus the fetched * material might be undefined (e.g. semi-transparent materials). Handle this * issue by fetching the other material. */ - if(!mat) { + if(!mtl->mrumtl) { switch(hit_side) { - case BACK: mat = interf->mtl_back; break; - case FRONT: mat = interf->mtl_front; break; + case BACK: mtl = &interf->mtl_back; break; + case FRONT: mtl = &interf->mtl_front; break; default: FATAL("Unreachable code.\n"); break; } } - ASSERT(mat); + ASSERT(mtl->mrumtl); } r = ssp_rng_canonical(rng); - res = mrumtl_fetch_brdf2(mat, wavelength, r, &brdf); + res = mrumtl_fetch_brdf2(mtl->mrumtl, wavelength, r, &brdf); if(res != RES_OK) { htrdr_log_err(htrdr, "%s: error retrieving the MruMtl BRDF for the wavelength %g.\n", diff --git a/src/htrdr_interface.h b/src/htrdr_interface.h @@ -17,6 +17,7 @@ #ifndef HTRDR_INTERFACE_H #define HTRDR_INTERFACE_H +#include "htrdr_materials.h" #include <star/ssf.h> /* Forward declaration of external data type */ @@ -26,9 +27,9 @@ struct ssf_bsdf; struct ssp_rng; struct htrdr_interface { - const struct mrumtl* mtl_front; - const struct mrumtl* mtl_back; - const struct mrumtl* mtl_thin; /* != NULL <=> thin material */ + struct htrdr_mtl mtl_front; + struct htrdr_mtl mtl_back; + struct htrdr_mtl mtl_thin; /* != NULL <=> thin material */ }; static const struct htrdr_interface HTRDR_INTERFACE_NULL; diff --git a/src/htrdr_materials.c b/src/htrdr_materials.c @@ -0,0 +1,296 @@ +/* Copyright (C) 2018, 2019 CNRS, Université Paul Sabatier + * Copyright (C) 2018, 2019, 2020 |Meso|Star> (contact@meso-star.com) + * + * 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/>. */ + +#define _POSIX_C_SOURCE 200112L /* strtok_r and wordexp support */ + +#include "htrdr.h" +#include "htrdr_materials.h" + +#include <modradurb/mrumtl.h> + +#include <rsys/cstr.h> +#include <rsys/hash_table.h> +#include <rsys/mem_allocator.h> +#include <rsys/ref_count.h> +#include <rsys/str.h> +#include <rsys/text_reader.h> + +#include <string.h> +#include <wordexp.h> + +/* Generate the hash table that maps a material name to its data */ +#define HTABLE_NAME name2mtl +#define HTABLE_DATA struct mrumtl* +#define HTABLE_KEY struct str +#define HTABLE_KEY_FUNCTOR_INIT str_init +#define HTABLE_KEY_FUNCTOR_RELEASE str_release +#define HTABLE_KEY_FUNCTOR_COPY str_copy +#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release +#define HTABLE_KEY_FUNCTOR_HASH str_hash +#define HTABLE_KEY_FUNCTOR_EQ str_eq +#include <rsys/hash_table.h> + +struct htrdr_materials { + struct htable_name2mtl name2mtl; + struct htrdr* htrdr; + ref_T ref; +}; + +/******************************************************************************* + * Local functions + ******************************************************************************/ +static res_T +parse_material + (struct htrdr_materials* mats, + struct txtrdr* txtrdr, + struct str* str) /* Scratch string */ +{ + wordexp_t wexp; + char* tk = NULL; + char* tk_ctx = NULL; + struct mrumtl* mrumtl = NULL; + int err = 0; + int wexp_is_allocated = 0; + res_T res = RES_OK; + ASSERT(mats && txtrdr); + + tk = strtok_r(txtrdr_get_line(txtrdr), " \t", &tk_ctx); + ASSERT(tk); + + res = str_set(str, tk); + if(res != RES_OK) { + htrdr_log_err(mats->htrdr, + "%s:%lu: could not copy the material name `%s' -- %s.\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk, + res_to_cstr(res)); + goto error; + } + + tk = strtok_r(NULL, "", &tk_ctx); + if(!tk) { + htrdr_log_err(mats->htrdr, + "%s:%lu: missing the MruMtl file for the material `%s'.\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), + str_cget(str)); + res = RES_BAD_ARG; + goto error; + } + + err = wordexp(tk, &wexp, 0); + if(err) { + htrdr_log_err(mats->htrdr, + "%s:%lu: error in word expension of the mrumtl path.\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr)); + res = RES_BAD_ARG; + goto error; + } + wexp_is_allocated = 1; + + if(wexp.we_wordc < 1) { + htrdr_log_err(mats->htrdr, + "%s:%lu: missing the MruMtl file for the material `%s'.\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), + str_cget(str)); + res = RES_BAD_ARG; + goto error; + } + + /* Parse the mrumtl file if any */ + if(strcmp(wexp.we_wordv[0], "none")) { + res = mrumtl_create(&mats->htrdr->logger, mats->htrdr->allocator, + mats->htrdr->verbose, &mrumtl); + if(res != RES_OK) { + htrdr_log_err(mats->htrdr, + "%s:%lu: error creating the MruMtl loader for the material `%s'-- %s.\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), + str_cget(str), res_to_cstr(res)); + goto error; + } + + res = mrumtl_load(mrumtl, wexp.we_wordv[0]); + if(res != RES_OK) goto error; + } + + /* Register the material */ + res = htable_name2mtl_set(&mats->name2mtl, str, &mrumtl); + if(res != RES_OK) { + htrdr_log_err(mats->htrdr, + "%s:%lu: could not register the material `%s' -- %s.\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), + str_cget(str), res_to_cstr(res)); + goto error; + } + + if(wexp.we_wordc > 1) { + htrdr_log_warn(mats->htrdr, "%s:%lu: unexpected text `%s'.\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), + wexp.we_wordv[1]); + } + +exit: + if(wexp_is_allocated) wordfree(&wexp); + return res; +error: + if(mrumtl) MRUMTL(ref_put(mrumtl)); + goto exit; +} + +static res_T +parse_materials_list + (struct htrdr_materials* mats, + const char* filename, + const char* func_name) +{ + struct txtrdr* txtrdr = NULL; + struct str str; + res_T res = RES_OK; + ASSERT(mats && filename && func_name); + + str_init(mats->htrdr->allocator, &str); + + res = txtrdr_file(mats->htrdr->allocator, filename, '#', &txtrdr); + if(res != RES_OK) { + htrdr_log_err(mats->htrdr, + "%s: could not create the text reader for the material file `%s' -- %s.\n", + func_name, filename, res_to_cstr(res)); + goto error; + } + + for(;;) { + res = txtrdr_read_line(txtrdr); + if(res != RES_OK) { + htrdr_log_err(mats->htrdr, + "%s: error reading a line in the material file `%s' -- %s.\n", + func_name, filename, res_to_cstr(res)); + goto error; + } + + if(!txtrdr_get_cline(txtrdr)) break; + + res = parse_material(mats, txtrdr, &str); + if(res != RES_OK) goto error; + } + +exit: + str_release(&str); + if(txtrdr) txtrdr_ref_put(txtrdr); + return res; +error: + goto exit; +} + +static void +mtl_release(ref_T* ref) +{ + struct htable_name2mtl_iterator it, it_end; + struct htrdr_materials* mats; + ASSERT(ref); + mats = CONTAINER_OF(ref, struct htrdr_materials, ref); + + htable_name2mtl_begin(&mats->name2mtl, &it); + htable_name2mtl_end(&mats->name2mtl, &it_end); + while(!htable_name2mtl_iterator_eq(&it, &it_end)) { + struct mrumtl* mrumtl = *htable_name2mtl_iterator_data_get(&it); + /* The mrumtl can be NULL for semi transparent materials */ + if(mrumtl) MRUMTL(ref_put(mrumtl)); + htable_name2mtl_iterator_next(&it); + } + htable_name2mtl_release(&mats->name2mtl); + MEM_RM(mats->htrdr->allocator, mats); +} + +/******************************************************************************* + * Local symbol + ******************************************************************************/ +res_T +htrdr_materials_create + (struct htrdr* htrdr, + const char* filename, + struct htrdr_materials** out_mtl) +{ + struct htrdr_materials* mats = NULL; + res_T res = RES_OK; + ASSERT(htrdr && filename && out_mtl); + + mats = MEM_CALLOC(htrdr->allocator, 1, sizeof(*mats)); + if(!mats) { + res = RES_MEM_ERR; + htrdr_log_err(htrdr, + "%s: could not allocate the mats data structure -- %s.\n", + FUNC_NAME, res_to_cstr(res)); + goto error; + } + ref_init(&mats->ref); + mats->htrdr = htrdr; + htable_name2mtl_init(htrdr->allocator, &mats->name2mtl); + + res = parse_materials_list(mats, filename, FUNC_NAME); + if(res != RES_OK) goto error; + +exit: + if(out_mtl) *out_mtl = mats; + return res; +error: + if(mats) { + htrdr_materials_ref_put(mats); + mats = NULL; + } + goto exit; +} + +void +htrdr_materials_ref_get(struct htrdr_materials* mats) +{ + ASSERT(mats); + ref_get(&mats->ref); +} + +void +htrdr_materials_ref_put(struct htrdr_materials* mats) +{ + ASSERT(mats); + ref_put(&mats->ref, mtl_release); +} + +int +htrdr_materials_find_mtl + (struct htrdr_materials* mats, + const char* name, + struct htrdr_mtl* mtl) +{ + struct str str; + struct htable_name2mtl_iterator it, it_end; + int found = 0; + ASSERT(mats && name && mtl); + + str_init(mats->htrdr->allocator, &str); + CHK(str_set(&str, name) == RES_OK); + + htable_name2mtl_find_iterator(&mats->name2mtl, &str, &it); + htable_name2mtl_end(&mats->name2mtl, &it_end); + if(htable_name2mtl_iterator_eq(&it, &it_end)) { /* No material found */ + *mtl = HTRDR_MTL_NULL; + found = 0; + } else { + mtl->name = str_cget(htable_name2mtl_iterator_key_get(&it)); + mtl->mrumtl = *htable_name2mtl_iterator_data_get(&it); + found = 1; + } + str_release(&str); + + return found; +} + diff --git a/src/htrdr_materials.h b/src/htrdr_materials.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2018, 2019 CNRS, Université Paul Sabatier + * Copyright (C) 2018, 2019, 2020 |Meso|Star> (contact@meso-star.com) + * + * 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_MATERIALS_H +#define HTRDR_MATERIALS_H + +#include <rsys/rsys.h> + +struct htrdr_materials; +struct mrumtl; + +struct htrdr_mtl { + const char* name; + const struct mrumtl* mrumtl; +}; +static const struct htrdr_mtl HTRDR_MTL_NULL; + +extern LOCAL_SYM res_T +htrdr_materials_create + (struct htrdr* htrdr, + const char* filename, + struct htrdr_materials** mats); + +extern LOCAL_SYM void +htrdr_materials_ref_get + (struct htrdr_materials* mats); + +extern LOCAL_SYM void +htrdr_materials_ref_put + (struct htrdr_materials* mats); + +/* Return 1 if the material exist and 0 otherwise */ +extern LOCAL_SYM int +htrdr_materials_find_mtl + (struct htrdr_materials* mats, + const char* mtl_name, + struct htrdr_mtl* mtl); + +#endif /* HTRDR_MATERIALS_H */ + diff --git a/src/htrdr_mtl.c b/src/htrdr_mtl.c @@ -1,281 +0,0 @@ -/* Copyright (C) 2018, 2019 CNRS, Université Paul Sabatier - * Copyright (C) 2018, 2019, 2020 |Meso|Star> (contact@meso-star.com) - * - * 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/>. */ - -#define _POSIX_C_SOURCE 200112L /* strtok_r and wordexp support */ - -#include "htrdr.h" -#include "htrdr_mtl.h" - -#include <modradurb/mrumtl.h> - -#include <rsys/cstr.h> -#include <rsys/hash_table.h> -#include <rsys/mem_allocator.h> -#include <rsys/ref_count.h> -#include <rsys/str.h> -#include <rsys/text_reader.h> - -#include <string.h> -#include <wordexp.h> - -/* Generate the hash table that maps a material name to its data */ -#define HTABLE_NAME name2mtl -#define HTABLE_DATA struct mrumtl* -#define HTABLE_KEY struct str -#define HTABLE_KEY_FUNCTOR_INIT str_init -#define HTABLE_KEY_FUNCTOR_RELEASE str_release -#define HTABLE_KEY_FUNCTOR_COPY str_copy -#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release -#define HTABLE_KEY_FUNCTOR_HASH str_hash -#define HTABLE_KEY_FUNCTOR_EQ str_eq -#include <rsys/hash_table.h> - -struct htrdr_mtl { - struct htable_name2mtl name2mtl; - struct htrdr* htrdr; - ref_T ref; -}; - -/******************************************************************************* - * Local functions - ******************************************************************************/ -static res_T -parse_material - (struct htrdr_mtl* mtl, - struct txtrdr* txtrdr, - struct str* str) /* Scratch string */ -{ - wordexp_t wexp; - char* tk = NULL; - char* tk_ctx = NULL; - struct mrumtl* mrumtl = NULL; - int err = 0; - int wexp_is_allocated = 0; - res_T res = RES_OK; - ASSERT(mtl && txtrdr); - - tk = strtok_r(txtrdr_get_line(txtrdr), " \t", &tk_ctx); - ASSERT(tk); - - res = str_set(str, tk); - if(res != RES_OK) { - htrdr_log_err(mtl->htrdr, - "%s:%lu: could not copy the material name `%s' -- %s.\n", - txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk, - res_to_cstr(res)); - goto error; - } - - tk = strtok_r(NULL, "", &tk_ctx); - if(!tk) { - htrdr_log_err(mtl->htrdr, - "%s:%lu: missing the MruMtl file for the material `%s'.\n", - txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), - str_cget(str)); - res = RES_BAD_ARG; - goto error; - } - - err = wordexp(tk, &wexp, 0); - if(err) { - htrdr_log_err(mtl->htrdr, - "%s:%lu: error in word expension of the mrumtl path.\n", - txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr)); - res = RES_BAD_ARG; - goto error; - } - wexp_is_allocated = 1; - - if(wexp.we_wordc < 1) { - htrdr_log_err(mtl->htrdr, - "%s:%lu: missing the MruMtl file for the material `%s'.\n", - txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), - str_cget(str)); - res = RES_BAD_ARG; - goto error; - } - - res = mrumtl_create - (&mtl->htrdr->logger, mtl->htrdr->allocator, mtl->htrdr->verbose, &mrumtl); - if(res != RES_OK) { - htrdr_log_err(mtl->htrdr, - "%s:%lu: error creating the MruMtl loader for the material `%s'-- %s.\n", - txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), - str_cget(str), res_to_cstr(res)); - goto error; - } - - res = mrumtl_load(mrumtl, wexp.we_wordv[0]); - if(res != RES_OK) goto error; - - /* Register the material */ - res = htable_name2mtl_set(&mtl->name2mtl, str, &mrumtl); - if(res != RES_OK) { - htrdr_log_err(mtl->htrdr, - "%s:%lu: could not register the material `%s' -- %s.\n", - txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), - str_cget(str), res_to_cstr(res)); - goto error; - } - - if(wexp.we_wordc > 1) { - htrdr_log_warn(mtl->htrdr, "%s:%lu: unexpected text `%s'.\n", - txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), - wexp.we_wordv[1]); - } - -exit: - if(wexp_is_allocated) wordfree(&wexp); - return res; -error: - if(mrumtl) MRUMTL(ref_put(mrumtl)); - goto exit; -} - -static res_T -parse_materials_list - (struct htrdr_mtl* mtl, - const char* filename, - const char* func_name) -{ - struct txtrdr* txtrdr = NULL; - struct str str; - res_T res = RES_OK; - ASSERT(mtl && filename && func_name); - - str_init(mtl->htrdr->allocator, &str); - - res = txtrdr_file(mtl->htrdr->allocator, filename, '#', &txtrdr); - if(res != RES_OK) { - htrdr_log_err(mtl->htrdr, - "%s: could not create the text reader for the material file `%s' -- %s.\n", - func_name, filename, res_to_cstr(res)); - goto error; - } - - for(;;) { - res = txtrdr_read_line(txtrdr); - if(res != RES_OK) { - htrdr_log_err(mtl->htrdr, - "%s: error reading a line in the material file `%s' -- %s.\n", - func_name, filename, res_to_cstr(res)); - goto error; - } - - if(!txtrdr_get_cline(txtrdr)) break; - - res = parse_material(mtl, txtrdr, &str); - if(res != RES_OK) goto error; - } - -exit: - str_release(&str); - if(txtrdr) txtrdr_ref_put(txtrdr); - return res; -error: - goto exit; -} - -static void -mtl_release(ref_T* ref) -{ - struct htable_name2mtl_iterator it, it_end; - struct htrdr_mtl* mtl; - ASSERT(ref); - mtl = CONTAINER_OF(ref, struct htrdr_mtl, ref); - - htable_name2mtl_begin(&mtl->name2mtl, &it); - htable_name2mtl_end(&mtl->name2mtl, &it_end); - while(!htable_name2mtl_iterator_eq(&it, &it_end)) { - struct mrumtl* mrumtl = *htable_name2mtl_iterator_data_get(&it); - MRUMTL(ref_put(mrumtl)); - htable_name2mtl_iterator_next(&it); - } - htable_name2mtl_release(&mtl->name2mtl); - MEM_RM(mtl->htrdr->allocator, mtl); -} - -/******************************************************************************* - * Local symbol - ******************************************************************************/ -res_T -htrdr_mtl_create - (struct htrdr* htrdr, - const char* filename, - struct htrdr_mtl** out_mtl) -{ - struct htrdr_mtl* mtl = NULL; - res_T res = RES_OK; - ASSERT(htrdr && filename && out_mtl); - - mtl = MEM_CALLOC(htrdr->allocator, 1, sizeof(*mtl)); - if(!mtl) { - res = RES_MEM_ERR; - htrdr_log_err(htrdr, - "%s: could not allocate the mtl data structure -- %s.\n", - FUNC_NAME, res_to_cstr(res)); - goto error; - } - ref_init(&mtl->ref); - mtl->htrdr = htrdr; - htable_name2mtl_init(htrdr->allocator, &mtl->name2mtl); - - res = parse_materials_list(mtl, filename, FUNC_NAME); - if(res != RES_OK) goto error; - -exit: - if(out_mtl) *out_mtl = mtl; - return res; -error: - if(mtl) { - htrdr_mtl_ref_put(mtl); - mtl = NULL; - } - goto exit; -} - -void -htrdr_mtl_ref_get(struct htrdr_mtl* mtl) -{ - ASSERT(mtl); - ref_get(&mtl->ref); -} - -void -htrdr_mtl_ref_put(struct htrdr_mtl* mtl) -{ - ASSERT(mtl); - ref_put(&mtl->ref, mtl_release); -} - -const struct mrumtl* -htrdr_mtl_get(struct htrdr_mtl* mtl, const char* name) -{ - struct str str; - struct mrumtl** pmrumtl = NULL; - struct mrumtl* mrumtl = NULL; - ASSERT(mtl && name); - - str_init(mtl->htrdr->allocator, &str); - CHK(str_set(&str, name) == RES_OK); - - pmrumtl = htable_name2mtl_find(&mtl->name2mtl, &str); - if(pmrumtl) mrumtl = *pmrumtl; - - str_release(&str); - return mrumtl; -} - diff --git a/src/htrdr_mtl.h b/src/htrdr_mtl.h @@ -1,44 +0,0 @@ -/* Copyright (C) 2018, 2019 CNRS, Université Paul Sabatier - * Copyright (C) 2018, 2019, 2020 |Meso|Star> (contact@meso-star.com) - * - * 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_MTL_H -#define HTRDR_MTL_H - -struct htrdr_mtl; -struct mrumtl; - -extern LOCAL_SYM res_T -htrdr_mtl_create - (struct htrdr* htrdr, - const char* filename, - struct htrdr_mtl** mtl); - -extern LOCAL_SYM void -htrdr_mtl_ref_get - (struct htrdr_mtl* mtl); - -extern LOCAL_SYM void -htrdr_mtl_ref_put - (struct htrdr_mtl* mtl); - -/* Return NULL if the material name does not exist */ -extern const struct mrumtl* -htrdr_mtl_get - (struct htrdr_mtl* mtl, - const char* mtl_name); - -#endif /* HTRDR_MTL_H */ - diff --git a/src/htrdr_sensor.c b/src/htrdr_sensor.c @@ -81,7 +81,7 @@ sample_rectangle_ray * lies inside a geometry? */ if(!S3D_HIT_NONE(&hit)) { struct htrdr_interface interf = HTRDR_INTERFACE_NULL; - const struct mrumtl* mat = NULL; + const struct htrdr_mtl* mtl = NULL; float N[3]; /* Normalized normal of the hit */ float wi[3]; float cos_wi_N; @@ -94,12 +94,11 @@ sample_rectangle_ray /* Fetch the hit interface and retrieve the material into which the ray was * traced */ htrdr_ground_get_interface(ground, &hit, &interf); - mat = cos_wi_N < 0 ? interf.mtl_front : interf.mtl_back; + mtl = cos_wi_N < 0 ? &interf.mtl_front : &interf.mtl_back; - /* Reject the sample if the material is not null, i.e. the incident - * direction do not travel into the external air and thus the challenged - * position is not outside */ - if(mat != NULL) return RES_BAD_OP; + /* Reject the sample if the incident direction do not travel into the + * external air */ + if(strcmp("air", mtl->name)) return RES_BAD_OP; } /* Sample a ray direction */