htrdr

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

commit 5cd3f32da1fa95c40e87922e9c47cde14e49c271
parent 47eabcc66a3a515515e474ccd60c624bb2e9eb88
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 28 Jul 2021 14:13:17 +0200

Add the thin-lens camera model

Add the lens-radius, focal-dst, and focal-length options to the '-C'
option that defines a camera. By default the camera is a pinhole until
the 'lens-radius' is set to a value greater than 0. With a thin-lens
camera, the 'focal-dst' control the distance to focus and 'focal-length'
is another way to define its field of view.

Diffstat:
Mcmake/core/CMakeLists.txt | 6+++++-
Msrc/atmosphere/htrdr_atmosphere.c | 2++
Msrc/combustion/htrdr_combustion.c | 2++
Msrc/core/htrdr_args.c | 138++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/core/htrdr_args.h.in | 8+++++++-
5 files changed, 149 insertions(+), 7 deletions(-)

diff --git a/cmake/core/CMakeLists.txt b/cmake/core/CMakeLists.txt @@ -26,6 +26,7 @@ find_package(MruMtl 0.0 REQUIRED) find_package(RCMake 0.3 REQUIRED) find_package(RSys 0.11 REQUIRED) find_package(Star3D 0.8 REQUIRED) +find_package(StarCamera 0.0 REQUIRED) find_package(StarSF 0.6 REQUIRED) find_package(StarSP 0.10 REQUIRED) find_package(OpenMP 1.2 REQUIRED) @@ -42,6 +43,7 @@ include_directories( ${MruMtl_INCLUDE_DIR} ${RSys_INCLUDE_DIR} ${Star3D_INCLUDE_DIR} + ${StarCamera_INCLUDE_DIR} ${StarSF_INCLUDE_DIR} ${StarSP_INCLUDE_DIR} ${StarVX_INCLUDE_DIR} @@ -57,6 +59,8 @@ set(HTRDR_ARGS_DEFAULT_CAMERA_POS "0,0,0" CACHE INTERNAL "") set(HTRDR_ARGS_DEFAULT_CAMERA_TGT "0,1,0" CACHE INTERNAL "") set(HTRDR_ARGS_DEFAULT_CAMERA_UP "0,0,1" CACHE INTERNAL "") set(HTRDR_ARGS_DEFAULT_CAMERA_FOV "70" CACHE INTERNAL "") +set(HTRDR_ARGS_DEFAULT_CAMERA_LENS_RADIUS "0" CACHE INTERNAL "") +set(HTRDR_ARGS_DEFAULT_CAMERA_FOCAL_DST "1" CACHE INTERNAL "") set(HTRDR_ARGS_DEFAULT_RECTANGLE_POS "0,0,0" CACHE INTERNAL "") set(HTRDR_ARGS_DEFAULT_RECTANGLE_TGT "0,0,1" CACHE INTERNAL "") set(HTRDR_ARGS_DEFAULT_RECTANGLE_UP "0,1,0" CACHE INTERNAL "") @@ -116,7 +120,7 @@ add_library(htrdr-core SHARED ${HTRDR_CORE_FILES_SRC} ${HTRDR_CORE_FILES_INC} ${HTRDR_CORE_FILES_INC2}) -target_link_libraries(htrdr-core AW MruMtl RSys Star3D StarSF StarSP) +target_link_libraries(htrdr-core AW MruMtl RSys Star3D StarCamera StarSF StarSP) if(CMAKE_COMPILER_IS_GNUCC) target_link_libraries(htrdr-core m) diff --git a/src/atmosphere/htrdr_atmosphere.c b/src/atmosphere/htrdr_atmosphere.c @@ -179,6 +179,8 @@ setup_sensor d3_set(cam_args.up, args->sensor.camera.up); cam_args.aspect_ratio = proj_ratio; cam_args.field_of_view = MDEG2RAD(args->sensor.camera.fov_y); + cam_args.lens_radius = args->sensor.camera.lens_radius; + cam_args.focal_distance = args->sensor.camera.focal_dst; res = scam_create_perspective (htrdr_get_logger(cmd->htrdr), htrdr_get_allocator(cmd->htrdr), diff --git a/src/combustion/htrdr_combustion.c b/src/combustion/htrdr_combustion.c @@ -176,6 +176,8 @@ setup_camera (double)args->image.definition[0] / (double)args->image.definition[1]; cam_args.field_of_view = MDEG2RAD(args->camera.fov_y); + cam_args.lens_radius = args->camera.lens_radius; + cam_args.focal_distance = args->camera.focal_dst; return scam_create_perspective (htrdr_get_logger(cmd->htrdr), diff --git a/src/core/htrdr_args.c b/src/core/htrdr_args.c @@ -21,12 +21,17 @@ #include "core/htrdr_args.h" #include "core/htrdr_version.h" +#include <star/scam.h> + #include <rsys/cstr.h> #include <rsys/double3.h> #include <rsys/str.h> #include <string.h> +#define FOV_EXCLUSIVE_MIN 0.0 /* In degrees */ +#define FOV_EXCLUSIVE_MAX 180.0 /* In degrees */ + /******************************************************************************* * Helper functions ******************************************************************************/ @@ -66,8 +71,9 @@ parse_fov(const char* str, double* out_fov) fprintf(stderr, "Invalid field of view `%s'.\n", str); return RES_BAD_ARG; } - if(fov <= 0 || fov >= 180) { - fprintf(stderr, "The field of view %g is not in [30, 120].\n", fov); + if(fov <= FOV_EXCLUSIVE_MIN || fov >= FOV_EXCLUSIVE_MAX) { + fprintf(stderr, "The field of view %g is not in ]%g, %g[.\n", + fov, FOV_EXCLUSIVE_MIN, FOV_EXCLUSIVE_MAX); return RES_BAD_ARG; } *out_fov = fov; @@ -75,6 +81,66 @@ parse_fov(const char* str, double* out_fov) } static res_T +parse_focal_length(const char* str, double* out_length) +{ + double length; + res_T res = RES_OK; + ASSERT(str && out_length); + + res = cstr_to_double(str, &length); + if(res != RES_OK) { + fprintf(stderr, "Invalid focal length `%s'.\n", str); + return RES_BAD_ARG; + } + if(length <= 0) { + fprintf(stderr, "Invalid negative or null focal length %g.\n", length); + return RES_BAD_ARG; + } + *out_length = length; + return RES_OK; +} + +static res_T +parse_lens_radius(const char* str, double* out_radius) +{ + double radius; + res_T res = RES_OK; + ASSERT(str && out_radius); + + res = cstr_to_double(str, &radius); + if(res != RES_OK) { + fprintf(stderr, "Invalid lens radius `%s'.\n", str); + return RES_BAD_ARG; + } + if(radius < 0) { + fprintf(stderr, "Invalid negative lens radius %g.\n", radius); + return RES_BAD_ARG; + } + *out_radius = radius; + return RES_OK; +} + +static res_T +parse_focal_dst(const char* str, double* out_dst) +{ + double dst; + res_T res = RES_OK; + ASSERT(str && out_dst); + + res = cstr_to_double(str, &dst); + if(res != RES_OK) { + fprintf(stderr, "Invalid focal distance `%s'.\n", str); + return RES_BAD_ARG; + } + if(dst <= 0) { + fprintf(stderr, "Invalid negative or null focal disrtance %g.\n", dst); + return RES_BAD_ARG; + } + *out_dst = dst; + return RES_OK; +} + +static res_T parse_image_parameter(const char* str, void* args) { char buf[128]; @@ -178,6 +244,14 @@ parse_camera_parameter(const char* str, void* args) PARSE("up vector", parse_doubleX(val, cam->up, 3)); } else if(!strcmp(key, "fov")) { PARSE("field-of-view", parse_fov(val, &cam->fov_y)); + cam->focal_length = -1; /* Overwrite the focal_length */ + } else if(!strcmp(key, "focal-length")) { + PARSE("focal-length", parse_focal_length(val, &cam->focal_length)); + cam->fov_y = -1; /* Overwrite the fov */ + } else if(!strcmp(key, "lens-radius")) { + PARSE("lens radius", parse_lens_radius(val, &cam->lens_radius)); + } else if(!strcmp(key, "focal-dst")) { + PARSE("focal distance", parse_focal_dst(val, &cam->focal_dst)); } else { fprintf(stderr, "Invalid camera parameter `%s'.\n", key); res = RES_BAD_ARG; @@ -394,9 +468,63 @@ error: res_T htrdr_args_camera_parse(struct htrdr_args_camera* cam, const char* str) { - if(!cam || !str) return RES_BAD_ARG; - return cstr_parse_list(str, ':', parse_camera_parameter, cam); -} + res_T res = RES_OK; + + if(!cam || !str) { + res = RES_BAD_ARG; + goto error; + } + + res = cstr_parse_list(str, ':', parse_camera_parameter, cam); + if(res != RES_OK) goto error; + + if(cam->focal_length < 0) { + ASSERT(cam->fov_y > 0); + res = scam_field_of_view_to_focal_length + (cam->lens_radius, MDEG2RAD(cam->fov_y), &cam->focal_length); + if(res != RES_OK) { + fprintf(stderr, + "Cannot compute the focal length from the lens radius %g " + "and the field of view %g -- %s.\n", + cam->lens_radius, + cam->fov_y, + res_to_cstr(res)); + goto error; + } + + } else if(cam->fov_y < 0) { + ASSERT(cam->focal_length > 0); + res = scam_focal_length_to_field_of_view + (cam->lens_radius, cam->focal_length, &cam->fov_y); + if(res != RES_OK) { + fprintf(stderr, + "Cannot compute the field of view from the lens radius %g " + "and the focal length %g -- %s.\n", + cam->lens_radius, + cam->focal_length, + res_to_cstr(res)); + goto error; + } + cam->fov_y = MRAD2DEG(cam->fov_y); + if(cam->fov_y <= FOV_EXCLUSIVE_MIN || cam->fov_y >= FOV_EXCLUSIVE_MAX) { + fprintf(stderr, + "Invalid focal length %g regarding the lens radius %g. " + "The corresponding field of view %g is not in ]%g, %g[ degrees.\n", + cam->focal_length, + cam->lens_radius, + cam->fov_y, + FOV_EXCLUSIVE_MIN, + FOV_EXCLUSIVE_MAX); + res = RES_BAD_ARG; + goto error; + } + } + +exit: + return res; +error: + goto exit; +} res_T htrdr_args_rectangle_parse(struct htrdr_args_rectangle* rect, const char* str) diff --git a/src/core/htrdr_args.h.in b/src/core/htrdr_args.h.in @@ -25,16 +25,22 @@ /* Arguments of a pinhole camera sensor */ struct htrdr_args_camera { - double position[3]; /* Focal point */ + double position[3]; /* Lens position */ double target[3]; /* Targeted position */ double up[3]; /* Up vector of the camera */ double fov_y; /* Vertical field of view of the camera, in degrees */ + double lens_radius; /* Radius of the lens. 0 means for pinhole */ + double focal_dst; /* Distance to focus on */ + double focal_length; /* Computed from fov_y and lens_radius. <0 => not used */ }; #define HTRDR_ARGS_CAMERA_DEFAULT__ { \ {@HTRDR_ARGS_DEFAULT_CAMERA_POS@}, /* position */ \ {@HTRDR_ARGS_DEFAULT_CAMERA_TGT@}, /* target */ \ {@HTRDR_ARGS_DEFAULT_CAMERA_UP@}, /* Camera up */ \ @HTRDR_ARGS_DEFAULT_CAMERA_FOV@, /* Vertical field of view */ \ + @HTRDR_ARGS_DEFAULT_CAMERA_LENS_RADIUS@, /* Radius of the lens */ \ + @HTRDR_ARGS_DEFAULT_CAMERA_FOCAL_DST@, /* Distance to focus on */ \ + -1 /* Focal length. <0 <=> not used */ \ } static const struct htrdr_args_camera HTRDR_ARGS_CAMERA_DEFAULT = HTRDR_ARGS_CAMERA_DEFAULT__;