commit db820201ae9a8f31d402e242938b4fa4aeccd353
parent 3ae3162665bbe7bcec40722f7e5490386a44d6cb
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date: Tue, 24 Feb 2026 18:17:08 +0100
Update BRDF parsing accordingly to the new config file specification
Take the new BRDF reflectivity options into account when parsing a
configuration file. This commit also simplifies the sphin API for BRDFs
by decoupling the energetic component (i.e., the
directional–hemispherical reflectivity) from the reflection direction
distribution PDF, following a similar approach to that used for surface
sources.
The public sphin API introduces a new enum,
sphin_brdf_reflectivity_type, to represent the different reflectivity
options now supported in the configuration file. Additionally,
sphin_brdf_type has been renamed to the more appropriate
sphin_brdf_direction_distribution.
Reflectivity, previously represented as a real value, is now treated as
a spectral property (although it may be spectral-directional).
Tests have been updated accordingly.
Diffstat:
3 files changed, 103 insertions(+), 92 deletions(-)
diff --git a/src/sphin.h b/src/sphin.h
@@ -50,10 +50,17 @@ enum sphin_side {
SPHIN_SIDE_NONE__ /* 2 */
};
-enum sphin_brdf_type {
- SPHIN_BRDF_LAMBERT, /* 0 */
- SPHIN_BRDF_SPECULAR, /* 1 */
- SPHIN_BRDF_NONE__ /* 2 */
+enum sphin_brdf_direction_distribution {
+ SPHIN_BRDF_DIRECTION_LAMBERT, /* 0 */
+ SPHIN_BRDF_DIRECTION_SPECULAR, /* 1 */
+ SPHIN_BRDF_DIRECTION_NONE__ /* 2 */
+};
+
+enum sphin_brdf_reflectivity_type {
+ SPHIN_BRDF_REFLECTIVITY_TABULATED,
+ SPHIN_BRDF_REFLECTIVITY_FRESNEL_DIELECTRIC,
+ SPHIN_BRDF_REFLECTIVITY_FRESNEL_DIELECTRIC_CONDUCTOR,
+ SPHIN_BRDF_REFLECTIVITY_NONE__
};
enum sphin_photon_unit {
@@ -95,26 +102,6 @@ struct sphin_create_args {
static const struct sphin_create_args SPHIN_CREATE_ARGS_DEFAULT =
SPHIN_CREATE_ARGS_DEFAULT__;
-struct sphin_brdf_lambertian {
- double reflectivity;
-};
-#define SPHIN_BRDF_LAMBERTIAN_NULL__ {0}
-static const struct sphin_brdf_lambertian SPHIN_BRDF_LAMBERTIAN_NULL =
- SPHIN_BRDF_LAMBERTIAN_NULL__;
-
-struct sphin_brdf_specular {
- double reflectivity;
-};
-#define SPHIN_BRDF_SPECULAR_NULL__ {0}
-static const struct sphin_brdf_specular SPHIN_BRDF_SPECULAR_NULL =
- SPHIN_BRDF_SPECULAR_NULL__;
-
-#define SPHIN_BRDF_NULL__ { \
- SPHIN_BRDF_NONE__, \
- SPHIN_BRDF_LAMBERTIAN_NULL__, \
- SPHIN_BRDF_SPECULAR_NULL__ \
-}
-
struct sphin_source_surface_flux_density {
double flux_density; /* either [umol/m^2/s] or [W/m^2] */
struct sphin_spectral_property* emission_spectrum; /* Normalized */
@@ -502,19 +489,19 @@ sphin_brdf_ref_put
(struct sphin_brdf* brdf);
SPHIN_API res_T
-sphin_brdf_get_type
- (struct sphin_brdf* brdf,
- enum sphin_brdf_type* type);
+sphin_brdf_get_direction_distribution
+(struct sphin_brdf* brdf,
+ enum sphin_brdf_direction_distribution* direction_distribution);
SPHIN_API res_T
-sphin_brdf_lambertian_get_reflectivity
+sphin_brdf_get_reflectivity_type
(struct sphin_brdf* brdf,
- double* reflectivity);
+ enum sphin_brdf_reflectivity_type* reflectivity_type);
SPHIN_API res_T
-sphin_brdf_specular_get_reflectivity
- (struct sphin_brdf* brdf,
- double* reflectivity);
+sphin_brdf_get_reflectivity_value
+ (struct sphin_brdf* brdf, /* Only for SPHIN_BRDF_REFLECTIVITY_CONSTANT */
+ struct sphin_spectral_property** reflectivity);
/*******************************************************************************
* API of the sensor_volume
diff --git a/src/sphin_brdf.c b/src/sphin_brdf.c
@@ -27,6 +27,8 @@
#include "sphin.h"
#include "sphin_c.h"
#include "sphin_brdf.h"
+#include "sphin_config.h"
+#include "sphin_spectral_property.h"
#include <rsys/cstr.h>
#include <rsys/mem_allocator.h>
@@ -35,9 +37,10 @@
#include <rsys/text_reader.h>
struct sphin_brdf {
- enum sphin_brdf_type type;
- struct sphin_brdf_lambertian lambertian;
- struct sphin_brdf_specular specular;
+ enum sphin_brdf_direction_distribution direction_distribution;
+ enum sphin_brdf_reflectivity_type reflectivity_type; /* Constant, Frensel */
+ struct sphin_spectral_property* reflectivity; /* Only used if reflectivity is
+ * a constant */
struct sphin* sphin;
ref_T ref;
};
@@ -61,8 +64,9 @@ brdf_create
ref_init(&brdf->ref);
SPHIN(ref_get(sphin));
brdf->sphin = sphin;
- brdf->lambertian = SPHIN_BRDF_LAMBERTIAN_NULL;
- brdf->specular = SPHIN_BRDF_SPECULAR_NULL;
+ brdf->reflectivity_type = SPHIN_BRDF_REFLECTIVITY_NONE__;
+ brdf->direction_distribution = SPHIN_BRDF_DIRECTION_NONE__;
+ brdf->reflectivity = NULL;
exit:
*out_brdf = brdf;
@@ -86,6 +90,9 @@ release_brdf
brdf = CONTAINER_OF(address, struct sphin_brdf, ref);
sphin = brdf->sphin;
+ if (NULL != brdf->reflectivity) {
+ SPHIN(spectral_property_ref_put(brdf->reflectivity));
+ }
MEM_RM(sphin->allocator, brdf);
SPHIN(ref_put(sphin));
}
@@ -103,7 +110,7 @@ parse_brdf
char* brdf_type = NULL;
char* str_reflectivity = NULL;
char* token_ptr = NULL;
- double reflectivity;
+ char* filename = NULL;
struct sphin_brdf* brdf = NULL;
res_T res = RES_OK;
@@ -119,27 +126,32 @@ parse_brdf
brdf_type = strtok_r(value, " \t", &token_ptr);
if (NULL == brdf_type){ res = RES_BAD_ARG; goto error; }
if (0 == strcmp(brdf_type, "LAMBERT")) {
- brdf->type = SPHIN_BRDF_LAMBERT;
+ brdf->direction_distribution = SPHIN_BRDF_DIRECTION_LAMBERT;
}
else if (0 == strcmp(brdf_type, "SPECULAR")) {
- brdf->type = SPHIN_BRDF_SPECULAR;
+ brdf->direction_distribution = SPHIN_BRDF_DIRECTION_SPECULAR;
}
else { res = RES_BAD_ARG; goto error; }
/* Parse reflectivity value */
str_reflectivity = strtok_r(NULL, " \t", &token_ptr);
- res = cstr_to_double(str_reflectivity, &reflectivity);
- if (RES_OK != res) { goto error; }
- if (reflectivity < 0 || reflectivity >1 ) { res = RES_BAD_ARG; goto error; }
-
- switch(brdf->type) {
- case SPHIN_BRDF_LAMBERT:
- brdf->lambertian.reflectivity = reflectivity;
- break;
- case SPHIN_BRDF_SPECULAR:
- brdf->specular.reflectivity = reflectivity;
- break;
- default: FATAL("Unreachable code\n"); break;
+ if (NULL == str_reflectivity){ res = RES_BAD_ARG; goto error; }
+
+ if (0 == strcmp(str_reflectivity, "FRESNEL_DIELECTRIC")) {
+ brdf->reflectivity_type = SPHIN_BRDF_REFLECTIVITY_FRESNEL_DIELECTRIC;
+ }
+ else if (0 == strcmp(str_reflectivity, "FRESNEL_DIELECTRIC_CONDUCTOR")) {
+ brdf->reflectivity_type
+ = SPHIN_BRDF_REFLECTIVITY_FRESNEL_DIELECTRIC_CONDUCTOR;
+ }
+ else {
+ filename = trim_keyword(str_reflectivity);
+ if (NULL == filename) { res = RES_BAD_ARG; goto error; }
+
+ res = parse_spectral_property(sphin, filename, &brdf->reflectivity);
+ if (RES_OK != res) { goto error; }
+
+ brdf->reflectivity_type = SPHIN_BRDF_REFLECTIVITY_TABULATED;
}
res = txtrdr_read_line(txtrdr);
@@ -182,50 +194,52 @@ sphin_brdf_ref_put
}
res_T
-sphin_brdf_get_type
+sphin_brdf_get_direction_distribution
(struct sphin_brdf* brdf,
- enum sphin_brdf_type* type)
+ enum sphin_brdf_direction_distribution* direction_distribution)
{
res_T res = RES_OK;
- if (NULL == brdf || NULL == type) {
+ if (NULL == brdf || NULL == direction_distribution) {
return RES_BAD_ARG;
}
- *type = brdf->type;
+ *direction_distribution = brdf->direction_distribution;
return res;
}
res_T
-sphin_brdf_lambertian_get_reflectivity
+sphin_brdf_get_reflectivity_type
(struct sphin_brdf* brdf,
- double* reflectivity)
+ enum sphin_brdf_reflectivity_type* reflectivity_type)
{
res_T res = RES_OK;
- if (NULL == brdf || NULL == reflectivity) {
- return RES_BAD_ARG;
- }
- if (SPHIN_BRDF_SPECULAR == brdf->type) {
+ if (NULL == brdf || NULL == reflectivity_type) {
return RES_BAD_ARG;
}
- *reflectivity = brdf->lambertian.reflectivity;
+
+ *reflectivity_type= brdf->reflectivity_type;
return res;
}
res_T
-sphin_brdf_specular_get_reflectivity
+sphin_brdf_get_reflectivity_value
(struct sphin_brdf* brdf,
- double* reflectivity)
+ struct sphin_spectral_property** reflectivity)
{
res_T res = RES_OK;
if (NULL == brdf || NULL == reflectivity) {
return RES_BAD_ARG;
}
- if (SPHIN_BRDF_LAMBERT == brdf->type) {
+
+ /* Not defined for Fresnel reflectivities types */
+ if (SPHIN_BRDF_REFLECTIVITY_TABULATED != brdf->reflectivity_type) {
return RES_BAD_ARG;
}
- *reflectivity = brdf->specular.reflectivity;
+
+ *reflectivity = brdf->reflectivity;
+
return res;
}
diff --git a/src/test_sphin_load_surface.c b/src/test_sphin_load_surface.c
@@ -92,13 +92,32 @@ write_stl_test_files
}
static void
+write_spec_rad_test_files
+ (void)
+{
+ FILE* file;
+ static const char* test0 =
+ "100 1\n"
+ "200 2\n"
+ "300 3\n"
+ "400 4\n";
+ file = fopen("spectral_property.txt", "w");
+ CHK(file != NULL);
+ fwrite(test0, sizeof(char), strlen(test0), file);
+ fclose(file);
+}
+
+static void
test_surface_api
(struct sphin* sphin)
{
char* name = NULL;
const char* path = "file.txt";
- double area, power, reflectivity, response_function;
- enum sphin_brdf_type brdf_type = SPHIN_BRDF_NONE__;
+ double area, power, response_function;
+ enum sphin_brdf_direction_distribution dir_dist
+ = SPHIN_BRDF_DIRECTION_NONE__;
+ enum sphin_brdf_reflectivity_type reflectivity_type
+ = SPHIN_BRDF_REFLECTIVITY_NONE__;
size_t nsurfaces;
struct sphin_brdf* brdf = NULL;
struct sphin_config* config = NULL;
@@ -109,7 +128,7 @@ test_surface_api
CHK(fp = fopen(path, "w+"));
fprintf(fp, "#Mot Clé Nom\n");
fprintf(fp, "\t\t surface : \"tube walls\"\n");
- fprintf(fp, "\tbrdf: LAMBERT 0.1935 # my comment\n");
+ fprintf(fp, "\tbrdf: LAMBERT spectral_property.txt # my comment\n");
fprintf(fp, "\tgeometry: FRONT test_0.stl\n");
fprintf(fp, "\tgeometry: BACK test_3.stl\n");
fprintf(fp, " \n");
@@ -117,7 +136,7 @@ test_surface_api
fprintf(fp, " \n");
fprintf(fp, "surface: \"other_tube walls\"\n");
fprintf(fp, "\tgeometry: FRONT test_0.stl\n");
- fprintf(fp, "\tbrdf\t : SPECULAR 0.1935 \n");
+ fprintf(fp, "\tbrdf\t : SPECULAR spectral_property.txt \n");
fprintf(fp, "\tsensor: \n");
fprintf(fp, "\t\tresponse_function: 1\n");
fclose(fp);
@@ -144,32 +163,22 @@ test_surface_api
CHK(sphin_surface_get_brdf(surface, NULL) == RES_BAD_ARG);
CHK(sphin_surface_get_brdf(NULL, &brdf) == RES_BAD_ARG);
CHK(sphin_surface_get_brdf(surface, &brdf) == RES_OK);
- CHK(sphin_brdf_get_type(brdf, &brdf_type) == RES_OK);
- CHK(brdf_type == SPHIN_BRDF_LAMBERT);
- CHK(sphin_brdf_lambertian_get_reflectivity(NULL, NULL) == RES_BAD_ARG);
- CHK(sphin_brdf_lambertian_get_reflectivity
- (NULL, &reflectivity) == RES_BAD_ARG);
- CHK(sphin_brdf_specular_get_reflectivity(brdf, &reflectivity) == RES_BAD_ARG);
- CHK(sphin_brdf_lambertian_get_reflectivity(NULL, NULL) == RES_BAD_ARG);
- CHK(sphin_brdf_lambertian_get_reflectivity
- (NULL, &reflectivity) == RES_BAD_ARG);
- CHK(sphin_brdf_lambertian_get_reflectivity(brdf, NULL) == RES_BAD_ARG);
- CHK(sphin_brdf_lambertian_get_reflectivity(brdf, &reflectivity) == RES_OK);
- CHK(eq_eps(reflectivity, 0.1935, 1e-15));
+ CHK(sphin_brdf_get_direction_distribution(NULL, NULL) == RES_BAD_ARG);
+ CHK(sphin_brdf_get_direction_distribution(NULL, &dir_dist) == RES_BAD_ARG);
+ CHK(sphin_brdf_get_direction_distribution(brdf, NULL) == RES_BAD_ARG);
+ CHK(sphin_brdf_get_direction_distribution(brdf, &dir_dist) == RES_OK);
+ CHK(dir_dist == SPHIN_BRDF_DIRECTION_LAMBERT);
+ CHK(sphin_brdf_get_reflectivity_type(NULL, NULL) == RES_BAD_ARG);
+ CHK(sphin_brdf_get_reflectivity_type(NULL, &reflectivity_type) == RES_BAD_ARG);
+ CHK(sphin_brdf_get_reflectivity_type(brdf, NULL) == RES_BAD_ARG);
+ CHK(sphin_brdf_get_reflectivity_type(brdf, &reflectivity_type) == RES_OK);
/* Test surface 1 */
CHK(sphin_config_get_surface(config, 1, &surface) == RES_OK);
CHK(sphin_surface_get_brdf(surface, &brdf) == RES_OK);
- CHK(sphin_brdf_get_type(brdf, &brdf_type) == RES_OK);
- CHK(brdf_type == SPHIN_BRDF_SPECULAR);
- CHK(sphin_brdf_lambertian_get_reflectivity
- (brdf, &reflectivity) == RES_BAD_ARG);
- CHK(sphin_brdf_specular_get_reflectivity(NULL, NULL) == RES_BAD_ARG);
- CHK(sphin_brdf_specular_get_reflectivity(brdf, NULL) == RES_BAD_ARG);
- CHK(sphin_brdf_specular_get_reflectivity(NULL, &reflectivity) == RES_BAD_ARG);
- CHK(sphin_brdf_specular_get_reflectivity(brdf, &reflectivity) == RES_OK);
+ CHK(sphin_brdf_get_direction_distribution(brdf, &dir_dist) == RES_OK);
+ CHK(dir_dist == SPHIN_BRDF_DIRECTION_SPECULAR);
CHK(sphin_surface_source_get_power(surface, &power) == RES_BAD_ARG);
- CHK(eq_eps(reflectivity, 0.1935, 1e-15));
CHK(sphin_surface_compute_total_area(surface, &area) == RES_OK);
CHK(eq_eps(area, 0.5, 1e-15));
CHK(sphin_brdf_ref_get(brdf) == RES_OK);
@@ -275,6 +284,7 @@ main(int argc, char** argv)
sphin_create(&args, &sphin);
write_stl_test_files();
+ write_spec_rad_test_files();
test_surface_api(sphin);
test_surface_api_bad_brdf_key(sphin);
test_surface_api_bad_brdf_value(sphin);