commit 162882802f54460443f96134e4be8a49d90b2f2c
parent 6325d4c369e5535ded7ba03319d2519e6c55699d
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 27 Oct 2022 16:15:17 +0200
htrdr-planeto: implement a source's API
Diffstat:
7 files changed, 275 insertions(+), 25 deletions(-)
diff --git a/cmake/planeto/CMakeLists.txt b/cmake/planeto/CMakeLists.txt
@@ -53,12 +53,14 @@ include_directories(
set(HTRDR_PLANETO_FILES_SRC
htrdr_planeto.c
htrdr_planeto_args.c
- htrdr_planeto_main.c)
+ htrdr_planeto_main.c
+ htrdr_planeto_source.c)
set(HTRDR_PLANETO_FILES_INC
htrdr_planeto.h
htrdr_planeto_c.h
- htrdr_planeto_args.h)
+ htrdr_planeto_args.h
+ htrdr_planeto_source.h)
# Prepend each file in the `HTRDR_FILES_<SRC|INC>' list by `HTRDR_SOURCE_DIR'
rcmake_prepend_path(HTRDR_PLANETO_FILES_SRC ${HTRDR_SOURCE_DIR}/planeto)
diff --git a/src/atmosphere/htrdr_atmosphere_sun.c b/src/atmosphere/htrdr_atmosphere_sun.c
@@ -74,6 +74,7 @@ htrdr_atmosphere_sun_create
goto error;
}
ref_init(&sun->ref);
+
sun->half_angle = 4.6524e-3;
sun->temperature = 5778;
sun->cos_half_angle = cos(sun->half_angle);
diff --git a/src/planeto/htrdr_planeto_args.c b/src/planeto/htrdr_planeto_args.c
@@ -73,27 +73,6 @@ check_ground_args(const struct htrdr_planeto_ground_args* args)
}
static INLINE res_T
-check_source_args(const struct htrdr_planeto_source_args* args)
-{
- if(!args) return RES_BAD_ARG;
-
- /* Invalid position */
- if(args->latitude <-90
- || args->latitude > 90
- || args->longitude <-180
- || args->longitude > 180
- || args->distance < 0)
- return RES_BAD_ARG;
-
- /* Miscellaneous parameters */
- if(args->radius < 0
- || args->temperature < 0)
- return RES_BAD_ARG;
-
- return RES_OK;
-}
-
-static INLINE res_T
check_spectral_args(const struct htrdr_args_spectral* spectral_domain)
{
if(!spectral_domain) return RES_BAD_ARG;
@@ -572,7 +551,7 @@ htrdr_planeto_args_init(struct htrdr_planeto_args* args, int argc, char** argv)
fprintf(stderr, "Missing ground definition -- option '-G'\n");
goto error;
}
- res = check_source_args(&args->source);
+ res = htrdr_planeto_source_args_check(&args->source);
if(res != RES_OK) {
fprintf(stderr, "Missing source definition -- option '-S'\n");
goto error;
@@ -644,7 +623,7 @@ htrdr_planeto_args_check(const struct htrdr_planeto_args* args)
if(res != RES_OK) return res;
/* Check the source */
- res = check_source_args(&args->source);
+ res = htrdr_planeto_source_args_check(&args->source);
if(res != RES_OK) return res;
/* Check miscalleneous parameters */
@@ -654,3 +633,24 @@ htrdr_planeto_args_check(const struct htrdr_planeto_args* args)
return RES_OK;
}
+
+res_T
+htrdr_planeto_source_args_check(const struct htrdr_planeto_source_args* args)
+{
+ if(!args) return RES_BAD_ARG;
+
+ /* Invalid position */
+ if(args->latitude <-90
+ || args->latitude > 90
+ || args->longitude <-180
+ || args->longitude > 180
+ || args->distance < 0)
+ return RES_BAD_ARG;
+
+ /* Miscellaneous parameters */
+ if(args->radius < 0
+ || args->temperature < 0)
+ return RES_BAD_ARG;
+
+ return RES_OK;
+}
diff --git a/src/planeto/htrdr_planeto_args.h b/src/planeto/htrdr_planeto_args.h
@@ -115,4 +115,8 @@ extern LOCAL_SYM res_T
htrdr_planeto_args_check
(const struct htrdr_planeto_args* args);
+extern LOCAL_SYM res_T
+htrdr_planeto_source_args_check
+ (const struct htrdr_planeto_source_args* args);
+
#endif /* HTRDR_PLANETO_ARGS_H */
diff --git a/src/planeto/htrdr_planeto_c.h b/src/planeto/htrdr_planeto_c.h
@@ -18,6 +18,8 @@
#ifndef HTRDR_PLANETO_C_H
#define HTRDR_PLANETO_C_H
+#include "planeto/htrdr_planeto_args.h"
+
#include "core/htrdr_args.h"
#include <rsys/ref_count.h>
diff --git a/src/planeto/htrdr_planeto_source.c b/src/planeto/htrdr_planeto_source.c
@@ -0,0 +1,178 @@
+/* Copyright (C) 2018, 2019, 2020, 2021 |Meso|Star> (contact@meso-star.com)
+ * Copyright (C) 2018, 2019, 2021 CNRS
+ * Copyright (C) 2018, 2019, Université Paul Sabatier
+ *
+ * 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 "planeto/htrdr_planeto_c.h"
+#include "planeto/htrdr_planeto_source.h"
+
+#include "core/htrdr.h"
+#include "core/htrdr_log.h"
+
+#include <star/ssp.h>
+
+#include <rsys/double3.h>
+#include <rsys/ref_count.h>
+
+struct htrdr_planeto_source {
+ double position[3]; /* In m */
+
+ double radius; /* In m */
+ double temperature; /* In Kelvin */
+
+ ref_T ref;
+ struct htrdr* htrdr;
+};
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static void
+release_source(ref_T* ref)
+{
+ struct htrdr_planeto_source* source;
+ struct htrdr* htrdr;
+ ASSERT(ref);
+
+ source = CONTAINER_OF(ref, struct htrdr_planeto_source, ref);
+ htrdr = source->htrdr;
+ MEM_RM(htrdr_get_allocator(htrdr), source);
+ htrdr_ref_put(htrdr);
+}
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+res_T
+htrdr_planeto_source_create
+ (struct htrdr_planeto* cmd,
+ const struct htrdr_planeto_source_args* args,
+ struct htrdr_planeto_source** out_source)
+{
+ struct htrdr_planeto_source* src = NULL;
+ double dst; /* In m */
+ double lat; /* In radians */
+ double lon; /* In radians */
+ res_T res = RES_OK;
+ ASSERT(cmd && out_source);
+ ASSERT(htrdr_planeto_source_args_check(args) == RES_OK);
+
+ src = MEM_CALLOC(htrdr_get_allocator(cmd->htrdr), 1, sizeof(*src));
+ if(!src) {
+ htrdr_log_err(cmd->htrdr, "error allocating source\n");
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ ref_init(&src->ref);
+ htrdr_ref_get(cmd->htrdr);
+ src->htrdr = cmd->htrdr;
+ src->radius = args->radius * 1e3/*From km to m*/;
+ src->temperature = args->temperature;
+
+ /* Convert latitude and longitude to radians and distance in m */
+ lat = MDEG2RAD(args->latitude);
+ lon = MDEG2RAD(args->longitude);
+ dst = args->distance * 1e3/*From km to m*/;
+
+ /* Compute the position of the source */
+ src->position[0] = dst * cos(lat) * cos(lon);
+ src->position[1] = dst * cos(lat) * sin(lon);
+ src->position[2] = dst * sin(lat);
+
+exit:
+ *out_source = src;
+ return res;
+error:
+ if(src) { htrdr_planeto_source_ref_put(src); src = NULL; }
+ goto exit;
+}
+
+void
+htrdr_planeto_source_ref_get(struct htrdr_planeto_source* source)
+{
+ ASSERT(source);
+ ref_get(&source->ref);
+}
+
+void htrdr_planeto_source_ref_put(struct htrdr_planeto_source* source)
+{
+ ASSERT(source);
+ ref_put(&source->ref, release_source);
+}
+
+double
+htrdr_planeto_source_sample_direction
+ (const struct htrdr_planeto_source* source,
+ struct ssp_rng* rng,
+ const double pos[3],
+ double dir[3])
+{
+ double main_dir[3];
+ double half_angle; /* In radians */
+ double cos_half_angle;
+ double dst; /* In m */
+ double pdf;
+ ASSERT(source && rng && pos && dir);
+
+ /* compute the direction of `pos' toward the center of the source */
+ d3_sub(main_dir, source->position, pos);
+
+ /* Normalize the direction and keep the distance from `pos' to the center of
+ * the source */
+ dst = d3_normalize(main_dir, main_dir);
+ CHK(dst > source->radius);
+
+ /* Sample the source according to its solid angle,
+ * i.e. 2*PI*(1 - cos(half_angle)) */
+ half_angle = asin(source->radius/dst);
+ cos_half_angle = cos(half_angle);
+ ssp_ran_sphere_cap_uniform(rng, main_dir, cos_half_angle, dir, &pdf);
+
+ return pdf;
+}
+
+double
+htrdr_planeto_source_get_radiance
+ (const struct htrdr_planeto_source* source,
+ const double wlen)
+{
+ return htrdr_planck_monochromatic
+ (wlen*1e-9/*From nm to m*/, source->temperature);
+}
+
+int
+htrdr_planeto_source_is_targeted
+ (const struct htrdr_planeto_source* source,
+ const double pos[3],
+ const double dir[3])
+{
+ double main_dir[3];
+ double half_angle; /* In radians */
+ double dst; /* In m */
+ ASSERT(source && dir && d3_is_normalized(dir));
+
+ /* compute the direction of `pos' toward the center of the source */
+ d3_sub(main_dir, source->position, pos);
+
+ /* Normalize the direction and keep the distance from `pos' to the center of
+ * the source */
+ dst = d3_normalize(main_dir, main_dir);
+ CHK(dst > source->radius);
+
+ /* Compute the the half angle of the source as seen from pos */
+ half_angle = asin(source->radius/dst);
+
+ return d3_dot(dir, main_dir) >= cos(half_angle);
+}
diff --git a/src/planeto/htrdr_planeto_source.h b/src/planeto/htrdr_planeto_source.h
@@ -0,0 +1,63 @@
+/* Copyright (C) 2018, 2019, 2020, 2021 |Meso|Star> (contact@meso-star.com)
+ * Copyright (C) 2018, 2019, 2021 CNRS
+ * Copyright (C) 2018, 2019, Université Paul Sabatier
+ *
+ * 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_PLANETO_SOURCE_H
+#define HTRDR_PLANETO_SOURCE_H
+
+#include <rsys/rsys.h>
+
+/* Forward declarations */
+struct htrdr_planeto;
+struct htrdr_planeto_source;
+struct htrdr_planeto_source_args;
+struct ssp_rng;
+
+extern LOCAL_SYM res_T
+htrdr_planeto_source_create
+ (struct htrdr_planeto* cmd,
+ const struct htrdr_planeto_source_args* args,
+ struct htrdr_planeto_source** source);
+
+extern LOCAL_SYM void
+htrdr_planeto_source_ref_get
+ (struct htrdr_planeto_source* source);
+
+extern LOCAL_SYM void
+htrdr_planeto_source_ref_put
+ (struct htrdr_planeto_source* source);
+
+/* Return the pdf of the sampled direction */
+extern LOCAL_SYM double
+htrdr_planeto_source_sample_direction
+ (const struct htrdr_planeto_source* source,
+ struct ssp_rng* rng,
+ const double pos[3], /* Position from which direction is sampled */
+ double dir[3]);
+
+extern LOCAL_SYM double /* In W/m²/sr/m */
+htrdr_planeto_source_get_radiance
+ (const struct htrdr_planeto_source* source,
+ const double wlen); /* In nanometers */
+
+/* Return 1 if the source is targeted by the submitted ray and 0 otherwise */
+extern LOCAL_SYM int
+htrdr_planeto_source_is_targeted
+ (const struct htrdr_planeto_source* source,
+ const double pos[3], /* Ray origin */
+ const double dir[3]);/* Ray direction */
+
+#endif /* HTRDR_PLANETO_SOURCE_H */