htrdr

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

commit c9f3e540a0fd586e809b06ca0f92d5119403d67b
parent e1bac4ab9dae78d16590fbf31201c25215843ba5
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 24 Aug 2021 15:47:13 +0200

Merge branch 'feature_camera_thin_lens' into develop

Diffstat:
Mcmake/atmosphere/CMakeLists.txt | 7+++++--
Mcmake/combustion/CMakeLists.txt | 5++++-
Mcmake/core/CMakeLists.txt | 12++++++++----
Mdoc/htrdr-atmosphere.1.txt.in | 31++++++++++++++++++++++++-------
Mdoc/htrdr-combustion.1.txt.in | 27++++++++++++++++++++++-----
Msrc/atmosphere/htrdr_atmosphere.c | 26+++++++++++++++++---------
Msrc/atmosphere/htrdr_atmosphere_draw_map.c | 48++++++++++++++++++++++++------------------------
Msrc/combustion/htrdr_combustion.c | 27++++++++++++++++-----------
Msrc/combustion/htrdr_combustion_c.h | 4++--
Msrc/combustion/htrdr_combustion_draw_map.c | 24++++++++++++------------
Msrc/core/htrdr_args.c | 137++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/core/htrdr_args.h.in | 12+++++++++++-
Dsrc/core/htrdr_camera.c | 157-------------------------------------------------------------------------------
Dsrc/core/htrdr_camera.h | 58----------------------------------------------------------
Msrc/core/htrdr_draw_map.c | 2+-
Msrc/core/htrdr_sensor.h | 4++--
16 files changed, 280 insertions(+), 301 deletions(-)

diff --git a/cmake/atmosphere/CMakeLists.txt b/cmake/atmosphere/CMakeLists.txt @@ -25,8 +25,9 @@ find_package(HTSky 0.2 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.9 REQUIRED) +find_package(StarSP 0.10 REQUIRED) find_package(StarVX 0.1 REQUIRED) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) @@ -36,6 +37,7 @@ include(rcmake_runtime) include_directories( ${HTSky_INCLUDE_DIR} ${RSys_INCLUDE_DIR} + ${StarCamera_INCLUDE_DIR} ${Star3D_INCLUDE_DIR} ${StarSF_INCLUDE_DIR} ${StarSP_INCLUDE_DIR} @@ -84,7 +86,8 @@ add_library(htrdr-atmosphere SHARED ${HTRDR_ATMOSPHERE_FILES_SRC} ${HTRDR_ATMOSPHERE_FILES_INC} ${HTRDR_ATMOSPHERE_FILES_INC2}) -target_link_libraries(htrdr-atmosphere htrdr-core HTSky RSys Star3D StarSF StarSP) +target_link_libraries(htrdr-atmosphere + htrdr-core HTSky RSys Star3D StarCamera StarSF StarSP) if(CMAKE_COMPILER_IS_GNUCC) target_link_libraries(htrdr-atmosphere m) diff --git a/cmake/combustion/CMakeLists.txt b/cmake/combustion/CMakeLists.txt @@ -25,6 +25,7 @@ find_package(AtrSTM 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(StarVX 0.1 REQUIRED) @@ -37,6 +38,7 @@ include_directories( ${AtrSTM_INCLUDE_DIR} ${RSys_INCLUDE_DIR} ${Star3D_INCLUDE_DIR} + ${StarCamera_INCLUDE_DIR} ${StarSF_INCLUDE_DIR} ${StarSP_INCLUDE_DIR} ${StarVX_INCLUDE_DIR} @@ -84,7 +86,8 @@ rcmake_prepend_path(HTRDR_COMBUSTION_FILES_INC ${HTRDR_SOURCE_DIR}/combustion) add_library(htrdr-combustion SHARED ${HTRDR_COMBUSTION_FILES_SRC} ${HTRDR_COMBUSTION_FILES_INC}) -target_link_libraries(htrdr-combustion htrdr-core AtrSTM RSys Star3D StarSF StarSP) +target_link_libraries(htrdr-combustion + htrdr-core AtrSTM RSys Star3D StarCamera StarSF StarSP) set_target_properties(htrdr-combustion PROPERTIES DEFINE_SYMBOL HTRDR_SHARED_BUILD diff --git a/cmake/core/CMakeLists.txt b/cmake/core/CMakeLists.txt @@ -26,8 +26,9 @@ 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.9 REQUIRED) +find_package(StarSP 0.10 REQUIRED) find_package(OpenMP 1.2 REQUIRED) find_package(MPI 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} @@ -53,10 +55,14 @@ include_directories( ################################################################################ # Generate files ################################################################################ +set(HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MIN "0.0" CACHE INTERNAL "") +set(HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MAX "180.0" CACHE INTERNAL "") 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 "") @@ -77,7 +83,6 @@ set(HTRDR_CORE_FILES_SRC htrdr.c htrdr_args.c htrdr_buffer.c - htrdr_camera.c htrdr_cie_xyz.c htrdr_draw_map.c htrdr_geometry.c @@ -91,7 +96,6 @@ set(HTRDR_CORE_FILES_INC htrdr.h htrdr_accum.h htrdr_buffer.h - htrdr_camera.h htrdr_c.h htrdr_cie_xyz.h htrdr_draw_map.h @@ -118,7 +122,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/doc/htrdr-atmosphere.1.txt.in b/doc/htrdr-atmosphere.1.txt.in @@ -82,7 +82,7 @@ W/sr/m^2 excepted for monochromatic computations where the computed spectral radiance is defined in W/sr/m^2/nm. The flux densities are saved in W/m^2. The results are written to the output file if the *-o* option is defined and the standard output otherwise. The output image is a list of raw ASCII data -formatted with respect to the *htrdr-image*(5) file format. +formatted with respect to the *htrdr-image*(5) file format. *htrdr-atmosphere* supports shared memory parallelism and relies on the Message Passing Interface specification [4] to parallelise its computations in a @@ -101,14 +101,31 @@ OPTIONS are taken into account. *-C* <__camera-parameter__:...>:: - Define the rendering point of view. Available camera parameters are: + Define the camera. Available parameters are: + + **focal-dst**=**_dst_**;; + Distance to focus on with a thin lens camera, that is, a camera whose + *lens-radius* is not zero. The default focal distance is + @HTRDR_ARGS_DEFAULT_CAMERA_FOCAL_DST@ meter. + + **focal-length**=**_length_**;; + Focal length of a camera lens. It is another way to control the field of + view of a thin lens camera. Be default, the field of view is directly set + through the **fov** parameter. **fov**=**_angle_**;; - Vertical field of view of the camera in [30, 120] degrees. By default - _angle_ is set to @HTRDR_ARGS_DEFAULT_CAMERA_FOV@ degrees. + Vertical field of view of the camera in + ]@HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MIN@, + @HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MAX@[ degrees. By default _angle_ is set to + @HTRDR_ARGS_DEFAULT_CAMERA_FOV@ degrees. + + **lens-radius**=**_radius_**;; + Radius of the camera lens. A non-zero radius means that the camera is a + thin lens camera while a zero radius defines a pinhole camera. By default + the lens radius is @HTRDR_ARGS_DEFAULT_CAMERA_LENS_RADIUS@. **pos**=**_x_**,**_y_**,**_z_**;; - Position of the camera. By default it is set to + Camera lens position. By default it is set to {@HTRDR_ARGS_DEFAULT_CAMERA_POS@}. **tgt**=**_x_**,**_y_**,**_z_**;; @@ -290,7 +307,7 @@ integrated radiance in W/sr/m^2 for the X, Y, and Z components of the CIE 1931 XYZ color space. The first value of each pair is the expected value of the average radiance of the pixel. The second value is its associated standard deviation. The fourth and final pair records the microsecond estimate of the -computation time per radiative path and its standard error. +computation time per radiative path and its standard error. Longwave image ~~~~~~~~~~~~~~ @@ -304,7 +321,7 @@ spectral radiance in W/sr/m^2/nm depending on whether this radiance was calculated for a spectral range or at a single wavelength. The fifth and sixth pixel components are not used. Finally, the last 2 components of the pixel record the estimate in microseconds of the computation time per radiative path -and its standard error. +and its standard error. Shortwave image ~~~~~~~~~~~~~~~ diff --git a/doc/htrdr-combustion.1.txt.in b/doc/htrdr-combustion.1.txt.in @@ -79,14 +79,31 @@ OPTIONS ------- *-C* <__camera-parameter__:...>:: - Define the rendering point of view. Available camera parameters are: + Define the camera. Available parameters are: + + **focal-dst**=**_dst_**;; + Distance to focus on with a thin lens camera, that is, a camera whose + *lens-radius* is not zero. The default focal distance is + @HTRDR_ARGS_DEFAULT_CAMERA_FOCAL_DST@ meter. + + **focal-length**=**_length_**;; + Focal length of a camera lens. It is another way to control the field of + view of a thin lens camera. Be default, the field of view is directly set + through the **fov** parameter. **fov**=**_angle_**;; - Vertical field of view of the camera in [30, 120] degrees. By default - _angle_ is set to @HTRDR_ARGS_DEFAULT_CAMERA_FOV@ degrees. + Vertical field of view of the camera in + ]@HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MIN@, + @HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MAX@[ degrees. By default _angle_ is set to + @HTRDR_ARGS_DEFAULT_CAMERA_FOV@ degrees. + + **lens-radius**=**_radius_**;; + Radius of the camera lens. A non-zero radius means that the camera is a + thin lens camera while a zero radius defines a pinhole camera. By default + the lens radius is @HTRDR_ARGS_DEFAULT_CAMERA_LENS_RADIUS@. **pos**=**_x_**,**_y_**,**_z_**;; - Position of the camera. By default it is set to + Camera lens position. By default it is set to {@HTRDR_ARGS_DEFAULT_CAMERA_POS@}. **tgt**=**_x_**,**_y_**,**_z_**;; @@ -306,7 +323,7 @@ EXAMPLES Make htrdr-combustion verbose (option *-v*) and render an image of a combustion medium whose tetrahedral mesh is stored in *tetra.sth* and its associated -thermodynamic properties are saved in *thermprops.atrtp*. The spectrally +thermodynamic properties are saved in *thermprops.atrtp*. The spectrally varying indices of the medium are listed in the *refract_ids.atrri* file. The center of the laser surface emission is positioned at the origin and its direction is aligned to the Y axis. The definition of the rendered image is diff --git a/src/atmosphere/htrdr_atmosphere.c b/src/atmosphere/htrdr_atmosphere.c @@ -24,7 +24,6 @@ #include "atmosphere/htrdr_atmosphere_sun.h" #include "core/htrdr_buffer.h" -#include "core/htrdr_camera.h" #include "core/htrdr_cie_xyz.h" #include "core/htrdr_log.h" #include "core/htrdr_materials.h" @@ -33,7 +32,10 @@ #include <high_tune/htsky.h> +#include <star/scam.h> + #include <rsys/cstr.h> +#include <rsys/double3.h> #include <math.h> @@ -153,6 +155,7 @@ setup_sensor const struct htrdr_atmosphere_args* args) { double proj_ratio; + struct scam_perspective_args cam_args = SCAM_PERSPECTIVE_ARGS_DEFAULT; res_T res = RES_OK; ASSERT(cmd && args); @@ -171,13 +174,18 @@ setup_sensor proj_ratio = (double)args->image.definition[0] / (double)args->image.definition[1]; - res = htrdr_camera_create - (cmd->htrdr, - args->sensor.camera.position, - args->sensor.camera.target, - args->sensor.camera.up, - proj_ratio, - MDEG2RAD(args->sensor.camera.fov_y), + d3_set(cam_args.position, args->sensor.camera.position); + d3_set(cam_args.target, args->sensor.camera.target); + 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), + htrdr_get_verbosity_level(cmd->htrdr), + &cam_args, &cmd->sensor.camera); break; case HTRDR_SENSOR_RECTANGLE: @@ -243,7 +251,7 @@ atmosphere_release(ref_T* ref) if(cmd->sun) htrdr_atmosphere_sun_ref_put(cmd->sun); if(cmd->cie) htrdr_cie_xyz_ref_put(cmd->cie); if(cmd->ran_wlen) htrdr_ran_wlen_ref_put(cmd->ran_wlen); - if(cmd->sensor.camera) htrdr_camera_ref_put(cmd->sensor.camera); + if(cmd->sensor.camera) SCAM(ref_put(cmd->sensor.camera)); if(cmd->sensor.rectangle) htrdr_rectangle_ref_put(cmd->sensor.rectangle); if(cmd->buf) htrdr_buffer_ref_put(cmd->buf); if(cmd->sky) HTSKY(ref_put(cmd->sky)); diff --git a/src/atmosphere/htrdr_atmosphere_draw_map.c b/src/atmosphere/htrdr_atmosphere_draw_map.c @@ -21,7 +21,6 @@ #include "core/htrdr.h" #include "core/htrdr_buffer.h" -#include "core/htrdr_camera.h" #include "core/htrdr_cie_xyz.h" #include "core/htrdr_draw_map.h" #include "core/htrdr_interface.h" @@ -32,6 +31,7 @@ #include <high_tune/htsky.h> #include <star/s3d.h> +#include <star/scam.h> #include <star/ssp.h> #include <rsys/clock_time.h> @@ -130,9 +130,8 @@ draw_pixel_image FOR_EACH(isamp, 0, args->spp) { struct time t0, t1; - double pix_samp[2]; - double ray_org[3]; - double ray_dir[3]; + struct scam_sample sample = SCAM_SAMPLE_NULL; + struct scam_ray ray = SCAM_RAY_NULL; double weight; double r0, r1, r2; double wlen; /* Sampled wavelength into the spectral band */ @@ -145,14 +144,15 @@ draw_pixel_image time_current(&t0); /* Sample a position into the pixel, in the normalized image plane */ - pix_samp[0] = (double)args->pixel_coord[0] + ssp_rng_canonical(args->rng); - pix_samp[1] = (double)args->pixel_coord[1] + ssp_rng_canonical(args->rng); - pix_samp[0] *= args->pixel_normalized_size[0]; - pix_samp[1] *= args->pixel_normalized_size[1]; + sample.film[0] = (double)args->pixel_coord[0]+ssp_rng_canonical(args->rng); + sample.film[1] = (double)args->pixel_coord[1]+ssp_rng_canonical(args->rng); + sample.film[0] *= args->pixel_normalized_size[0]; + sample.film[1] *= args->pixel_normalized_size[1]; + sample.lens[0] = ssp_rng_canonical(args->rng); + sample.lens[1] = ssp_rng_canonical(args->rng); - /* Generate a ray starting from the pinhole camera and passing through the - * pixel sample */ - htrdr_camera_ray(cmd->sensor.camera, pix_samp, ray_org, ray_dir); + /* Generate a camera ray */ + scam_generate_ray(cmd->sensor.camera, &sample, &ray); r0 = ssp_rng_canonical(args->rng); r1 = ssp_rng_canonical(args->rng); @@ -172,7 +172,7 @@ draw_pixel_image /* Compute the radiance in W/m^2/sr/m */ weight = atmosphere_compute_radiance_sw(cmd, args->ithread, args->rng, - ATMOSPHERE_RADIANCE_ALL, ray_org, ray_dir, wlen, iband, iquad); + ATMOSPHERE_RADIANCE_ALL, ray.org, ray.dir, wlen, iband, iquad); ASSERT(weight >= 0); weight /= pdf; /* In W/m^2/sr */ @@ -341,9 +341,8 @@ draw_pixel_xwave FOR_EACH(isamp, 0, args->spp) { struct time t0, t1; - double pix_samp[2]; - double ray_org[3]; - double ray_dir[3]; + struct scam_sample sample = SCAM_SAMPLE_NULL; + struct scam_ray ray = SCAM_RAY_NULL; double weight; double r0, r1, r2; double wlen; @@ -356,14 +355,15 @@ draw_pixel_xwave time_current(&t0); /* Sample a position into the pixel, in the normalized image plane */ - pix_samp[0] = (double)args->pixel_coord[0] + ssp_rng_canonical(args->rng); - pix_samp[1] = (double)args->pixel_coord[1] + ssp_rng_canonical(args->rng); - pix_samp[0] *= args->pixel_normalized_size[0]; - pix_samp[1] *= args->pixel_normalized_size[1]; + sample.film[0] = (double)args->pixel_coord[0]+ssp_rng_canonical(args->rng); + sample.film[1] = (double)args->pixel_coord[1]+ssp_rng_canonical(args->rng); + sample.film[0] *= args->pixel_normalized_size[0]; + sample.film[1] *= args->pixel_normalized_size[1]; + sample.lens[0] = ssp_rng_canonical(args->rng); + sample.lens[1] = ssp_rng_canonical(args->rng); - /* Generate a ray starting from the pinhole camera and passing through the - * pixel sample */ - htrdr_camera_ray(cmd->sensor.camera, pix_samp, ray_org, ray_dir); + /* Generate a camera ray */ + scam_generate_ray(cmd->sensor.camera, &sample, &ray); r0 = ssp_rng_canonical(args->rng); r1 = ssp_rng_canonical(args->rng); @@ -381,11 +381,11 @@ draw_pixel_xwave switch(cmd->spectral_type) { case HTRDR_SPECTRAL_LW: weight = atmosphere_compute_radiance_lw(cmd, args->ithread, args->rng, - ray_org, ray_dir, wlen, iband, iquad); + ray.org, ray.dir, wlen, iband, iquad); break; case HTRDR_SPECTRAL_SW: weight = atmosphere_compute_radiance_sw(cmd, args->ithread, args->rng, - ATMOSPHERE_RADIANCE_ALL, ray_org, ray_dir, wlen, iband, iquad); + ATMOSPHERE_RADIANCE_ALL, ray.org, ray.dir, wlen, iband, iquad); break; default: FATAL("Unreachable code.\n"); break; } diff --git a/src/combustion/htrdr_combustion.c b/src/combustion/htrdr_combustion.c @@ -21,7 +21,6 @@ #include "combustion/htrdr_combustion_laser.h" #include "core/htrdr.h" -#include "core/htrdr_camera.h" #include "core/htrdr_log.h" #include "core/htrdr_geometry.h" #include "core/htrdr_materials.h" @@ -29,9 +28,11 @@ #include <astoria/atrstm.h> +#include <star/scam.h> #include <star/ssf.h> #include <rsys/cstr.h> +#include <rsys/double3.h> #include <rsys/mem_allocator.h> /******************************************************************************* @@ -164,21 +165,25 @@ setup_camera (struct htrdr_combustion* cmd, const struct htrdr_combustion_args* args) { - double proj_ratio = 0; + struct scam_perspective_args cam_args = SCAM_PERSPECTIVE_ARGS_DEFAULT; ASSERT(cmd && args && args->image.definition[0] && args->image.definition[1]); ASSERT(cmd->output_type == HTRDR_COMBUSTION_ARGS_OUTPUT_IMAGE); - proj_ratio = + d3_set(cam_args.position, args->camera.position); + d3_set(cam_args.target, args->camera.target); + d3_set(cam_args.up, args->camera.up); + cam_args.aspect_ratio = (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 htrdr_camera_create - (cmd->htrdr, - args->camera.position, - args->camera.target, - args->camera.up, - proj_ratio, - MDEG2RAD(args->camera.fov_y), + return scam_create_perspective + (htrdr_get_logger(cmd->htrdr), + htrdr_get_allocator(cmd->htrdr), + htrdr_get_verbosity_level(cmd->htrdr), + &cam_args, &cmd->camera); } @@ -509,7 +514,7 @@ combustion_release(ref_T* ref) if(cmd->geom) htrdr_geometry_ref_put(cmd->geom); if(cmd->mats) htrdr_materials_ref_put(cmd->mats); if(cmd->medium) ATRSTM(ref_put(cmd->medium)); - if(cmd->camera) htrdr_camera_ref_put(cmd->camera); + if(cmd->camera) SCAM(ref_put(cmd->camera)); if(cmd->flux_map) htrdr_rectangle_ref_put(cmd->flux_map); if(cmd->laser) htrdr_combustion_laser_ref_put(cmd->laser); if(cmd->buf) htrdr_buffer_ref_put(cmd->buf); diff --git a/src/combustion/htrdr_combustion_c.h b/src/combustion/htrdr_combustion_c.h @@ -32,11 +32,11 @@ /* Forward declarations */ struct atrstm; struct htrdr; -struct htrdr_camera; struct htrdr_combustion_laser; struct htrdr_geometry; struct htrdr_materials; struct htrdr_rectangle; +struct scam; struct ssf_phase; struct ssp_rng; struct suvm_primitive; @@ -68,7 +68,7 @@ struct htrdr_combustion { struct htrdr_materials* mats; /* Materials of the combustion chamber */ struct atrstm* medium; /* Semi transparent medium */ - struct htrdr_camera* camera; /* Pinhole camera */ + struct scam* camera; /* Camera */ struct htrdr_rectangle* flux_map; /* Flux map */ struct htrdr_combustion_laser* laser; /* Laser sheet */ double wavelength; /* Wavelength of the laser in nanometer */ diff --git a/src/combustion/htrdr_combustion_draw_map.c b/src/combustion/htrdr_combustion_draw_map.c @@ -18,11 +18,11 @@ #include "combustion/htrdr_combustion_c.h" #include "core/htrdr_accum.h" -#include "core/htrdr_camera.h" #include "core/htrdr_draw_map.h" #include "core/htrdr_log.h" #include "core/htrdr_rectangle.h" +#include <star/scam.h> #include <star/ssp.h> #include <rsys/clock_time.h> @@ -50,9 +50,8 @@ draw_pixel_image FOR_EACH(isamp, 0, args->spp) { struct time t0, t1; - double pix_samp[2]; - double ray_org[3]; - double ray_dir[3]; + struct scam_sample sample = SCAM_SAMPLE_NULL; + struct scam_ray ray = SCAM_RAY_NULL; double weight; double usec; @@ -60,18 +59,19 @@ draw_pixel_image time_current(&t0); /* Sample a position into the pixel, in the normalized image plane */ - pix_samp[0] = (double)args->pixel_coord[0] + ssp_rng_canonical(args->rng); - pix_samp[1] = (double)args->pixel_coord[1] + ssp_rng_canonical(args->rng); - pix_samp[0] *= args->pixel_normalized_size[0]; - pix_samp[1] *= args->pixel_normalized_size[1]; + sample.film[0] = (double)args->pixel_coord[0]+ssp_rng_canonical(args->rng); + sample.film[1] = (double)args->pixel_coord[1]+ssp_rng_canonical(args->rng); + sample.film[0] *= args->pixel_normalized_size[0]; + sample.film[1] *= args->pixel_normalized_size[1]; + sample.lens[0] = ssp_rng_canonical(args->rng); + sample.lens[1] = ssp_rng_canonical(args->rng); - /* Generate a ray starting from the pinhole camera and passing through the - * pixel sample */ - htrdr_camera_ray(cmd->camera, pix_samp, ray_org, ray_dir); + /* Generate a camera ray */ + scam_generate_ray(cmd->camera, &sample, &ray); /* Backward trace the path */ res = combustion_compute_radiance_sw(cmd, args->ithread, args->rng, - ray_org, ray_dir, &weight); + ray.org, ray.dir, &weight); if(res != RES_OK) continue; /* Reject the path */ /* End the registration of the per realisation time */ diff --git a/src/core/htrdr_args.c b/src/core/htrdr_args.c @@ -21,6 +21,8 @@ #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> @@ -66,8 +68,10 @@ 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 <= HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MIN + || fov >= HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MAX) { + fprintf(stderr, "The field of view %g is not in ]%g, %g[.\n", fov, + HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MIN, HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MAX); return RES_BAD_ARG; } *out_fov = fov; @@ -75,6 +79,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 +242,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 +466,64 @@ 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 <= HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MIN + || cam->fov_y >= HTRDR_ARGS_CAMERA_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, + HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MIN, + HTRDR_ARGS_CAMERA_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 @@ -23,18 +23,28 @@ #include <rsys/rsys.h> +/* Exclusive bounds of the camera field of view (degrees) */ +#define HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MIN @HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MIN@ +#define HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MAX @HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MAX@ + /* 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__; diff --git a/src/core/htrdr_camera.c b/src/core/htrdr_camera.c @@ -1,157 +0,0 @@ -/* 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 "core/htrdr.h" -#include "core/htrdr_camera.h" -#include "core/htrdr_log.h" - -#include <rsys/double3.h> -#include <rsys/mem_allocator.h> -#include <rsys/ref_count.h> - -struct htrdr_camera { - /* Orthogonal basis of the camera */ - double axis_x[3]; - double axis_y[3]; - double axis_z[3]; - - double position[3]; - - ref_T ref; - struct htrdr* htrdr; -}; - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static void -camera_release(ref_T* ref) -{ - struct htrdr_camera* cam; - struct htrdr* htrdr; - ASSERT(ref); - cam = CONTAINER_OF(ref, struct htrdr_camera, ref); - htrdr = cam->htrdr; - MEM_RM(htrdr_get_allocator(htrdr), cam); - htrdr_ref_put(htrdr); -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ -res_T -htrdr_camera_create - (struct htrdr* htrdr, - const double position[3], - const double target[3], - const double up[3], - const double proj_ratio, - const double fov, /* In radian */ - struct htrdr_camera** out_cam) -{ - double x[3], y[3], z[3]; - double img_plane_depth; - struct htrdr_camera* cam = NULL; - res_T res = RES_OK; - ASSERT(htrdr && position && target && up && out_cam); - - cam = MEM_CALLOC(htrdr_get_allocator(htrdr), 1, sizeof(*cam)); - if(!cam) { - htrdr_log_err(htrdr, "could not allocate the camera data structure.\n"); - res = RES_MEM_ERR; - goto error; - } - ref_init(&cam->ref); - htrdr_ref_get(htrdr); - cam->htrdr = htrdr; - - if(fov <= 0 || fov >= PI) { - htrdr_log_err(htrdr, "invalid horizontal camera field of view `%g'\n", fov); - res = RES_BAD_ARG; - goto error; - } - - if(proj_ratio <= 0) { - htrdr_log_err(htrdr, "invalid projection ratio `%g'\n", proj_ratio); - res = RES_BAD_ARG; - goto error; - } - - if(d3_normalize(z, d3_sub(z, target, position)) <= 0 - || d3_normalize(x, d3_cross(x, z, up)) <= 0 - || d3_normalize(y, d3_cross(y, z, x)) <= 0) { - htrdr_log_err(htrdr, - "invalid camera point of view:\n" - " position = %g %g %g\n" - " target = %g %g %g\n" - " up = %g %g %g\n", - SPLIT3(position), SPLIT3(target), SPLIT3(up)); - res = RES_BAD_ARG; - goto error; - } - - img_plane_depth = 1.0/tan(fov*0.5); - d3_muld(cam->axis_x, x, proj_ratio); - d3_set(cam->axis_y, y); - d3_muld(cam->axis_z, z, img_plane_depth); - d3_set(cam->position, position); - -exit: - *out_cam = cam; - return res; -error: - if(cam) { - htrdr_camera_ref_put(cam); - cam = NULL; - } - goto exit; -} - -void -htrdr_camera_ref_get(struct htrdr_camera* cam) -{ - ASSERT(cam); - ref_get(&cam->ref); -} - -void -htrdr_camera_ref_put(struct htrdr_camera* cam) -{ - ASSERT(cam); - ref_put(&cam->ref, camera_release); -} - -void -htrdr_camera_ray - (const struct htrdr_camera* cam, - const double sample[2], - double ray_org[3], - double ray_dir[3]) -{ - double x[3], y[3], len; - (void)len; - ASSERT(cam && sample && ray_org && ray_dir); - ASSERT(sample[0] >= 0 || sample[0] < 1); - ASSERT(sample[1] >= 0 || sample[1] < 1); - d3_muld(x, cam->axis_x, sample[0]*2-1); - d3_muld(y, cam->axis_y, sample[1]*2-1); - d3_add(ray_dir, d3_add(ray_dir, x, y), cam->axis_z); - len = d3_normalize(ray_dir, ray_dir); - ASSERT(len >= 1.e-6); - d3_set(ray_org, cam->position); -} - diff --git a/src/core/htrdr_camera.h b/src/core/htrdr_camera.h @@ -1,58 +0,0 @@ -/* 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_CAMERA_H -#define HTRDR_CAMERA_H - -#include "core/htrdr.h" -#include <rsys/rsys.h> - -/* Forward declarations */ -struct htrdr; -struct htrdr_camera; - -BEGIN_DECLS - -HTRDR_CORE_API res_T -htrdr_camera_create - (struct htrdr* htrdr, - const double position[3], - const double target[3], - const double up[3], - const double proj_ratio, /* Width / Height */ - const double fov, /* In radian */ - struct htrdr_camera** cam); - -HTRDR_CORE_API void -htrdr_camera_ref_get - (struct htrdr_camera* cam); - -HTRDR_CORE_API void -htrdr_camera_ref_put - (struct htrdr_camera* cam); - -HTRDR_CORE_API void -htrdr_camera_ray - (const struct htrdr_camera* cam, - const double sample[2], /* In [0, 1[ */ - double ray_org[3], - double ray_dir[3]); - -END_DECLS - -#endif /* HTRDR_CAMERA_H */ - diff --git a/src/core/htrdr_draw_map.c b/src/core/htrdr_draw_map.c @@ -42,7 +42,7 @@ #define RNG_SEQUENCE_SIZE 10000 #define TILE_MCODE_NULL UINT32_MAX -#define TILE_SIZE 32 /* Definition in X & Y of a tile */ +#define TILE_SIZE 8 /* Definition in X & Y of a tile */ STATIC_ASSERT(IS_POW2(TILE_SIZE), TILE_SIZE_must_be_a_power_of_2); /* Tile of row ordered image pixels */ diff --git a/src/core/htrdr_sensor.h b/src/core/htrdr_sensor.h @@ -20,7 +20,7 @@ /* Forward declarations */ struct htrdr; -struct htrdr_camera; +struct scam; struct htrdr_rectangle; struct ssp_rng; @@ -30,7 +30,7 @@ enum htrdr_sensor_type { }; struct htrdr_sensor { - struct htrdr_camera* camera; + struct scam* camera; struct htrdr_rectangle* rectangle; enum htrdr_sensor_type type; };