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:
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 */