htrdr

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

commit b2a30edb703380fad482fbdb2ce4afe5c51c389c
parent fd044578209ab87690dda06123dbe06652e73dc1
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 25 Aug 2021 13:52:06 +0200

Adds orthographic camera support

Adds orthographic camera support for both atmosphere mode and combustion
mode. The new '-P' option is used to define the parameters of the
orthographic camera.

Diffstat:
Mcmake/core/CMakeLists.txt | 11++++++-----
Mdoc/htrdr-atmosphere.1.txt.in | 2+-
Msrc/atmosphere/htrdr_atmosphere.c | 176+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/atmosphere/htrdr_atmosphere_args.c | 42+++++++++++++++++++++++++++---------------
Msrc/atmosphere/htrdr_atmosphere_args.h.in | 29+++++++++++++++++++----------
Msrc/atmosphere/htrdr_atmosphere_c.h | 9++++++---
Msrc/atmosphere/htrdr_atmosphere_draw_map.c | 30++++++++++++++++--------------
Msrc/atmosphere/htrdr_atmosphere_main.c | 4++--
Msrc/combustion/htrdr_combustion.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/combustion/htrdr_combustion_args.c | 19+++++++++++++++----
Msrc/combustion/htrdr_combustion_args.h.in | 10++++++++--
Msrc/core/htrdr.h | 7++++---
Msrc/core/htrdr_args.c | 123++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Msrc/core/htrdr_args.h.in | 51+++++++++++++++++++++++++++++++++++++++------------
14 files changed, 419 insertions(+), 156 deletions(-)

diff --git a/cmake/core/CMakeLists.txt b/cmake/core/CMakeLists.txt @@ -55,14 +55,15 @@ 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_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN "0.0" CACHE INTERNAL "") +set(HTRDR_ARGS_CAMERA_PERSPECTIVE_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_CAMERA_ORTHOGRAPHIC_HEIGHT "1" CACHE INTERNAL "") +set(HTRDR_ARGS_DEFAULT_CAMERA_PERSPECTIVE_FOV "70" CACHE INTERNAL "") +set(HTRDR_ARGS_DEFAULT_CAMERA_PERSPECTIVE_LENS_RADIUS "0" CACHE INTERNAL "") +set(HTRDR_ARGS_DEFAULT_CAMERA_PERSPECTIVE_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 "") diff --git a/doc/htrdr-atmosphere.1.txt.in b/doc/htrdr-atmosphere.1.txt.in @@ -101,7 +101,7 @@ OPTIONS are taken into account. *-C* <__camera-parameter__:...>:: - Define the camera. Available parameters are: + Define a perspective camera. Available parameters are: **focal-dst**=**_dst_**;; Distance to focus on with a thin lens camera, that is, a camera whose diff --git a/src/atmosphere/htrdr_atmosphere.c b/src/atmosphere/htrdr_atmosphere.c @@ -150,61 +150,118 @@ spherical_to_cartesian_dir } static res_T -setup_sensor +setup_camera_orthographic + (struct htrdr_atmosphere* cmd, + const struct htrdr_atmosphere_args* args) +{ + struct scam_orthographic_args cam_args = SCAM_ORTHOGRAPHIC_ARGS_DEFAULT; + ASSERT(cmd && args && args->image.definition[0] && args->image.definition[1]); + ASSERT(cmd->output_type == HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE); + ASSERT(args->cam_type == HTRDR_ARGS_CAMERA_ORTHOGRAPHIC); + + d3_set(cam_args.position, args->cam_ortho.position); + d3_set(cam_args.target, args->cam_ortho.target); + d3_set(cam_args.up, args->cam_ortho.up); + cam_args.height = args->cam_ortho.height; + cam_args.aspect_ratio = + (double)args->image.definition[0] + / (double)args->image.definition[1]; + + return scam_create_orthographic + (htrdr_get_logger(cmd->htrdr), + htrdr_get_allocator(cmd->htrdr), + htrdr_get_verbosity_level(cmd->htrdr), + &cam_args, + &cmd->camera); +} + +static res_T +setup_camera_perspective (struct htrdr_atmosphere* cmd, const struct htrdr_atmosphere_args* args) { - double proj_ratio; 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_ATMOSPHERE_ARGS_OUTPUT_IMAGE); + ASSERT(args->cam_type == HTRDR_ARGS_CAMERA_PERSPECTIVE); + + d3_set(cam_args.position, args->cam_persp.position); + d3_set(cam_args.target, args->cam_persp.target); + d3_set(cam_args.up, args->cam_persp.up); + cam_args.aspect_ratio = + (double)args->image.definition[0] + / (double)args->image.definition[1]; + cam_args.field_of_view = MDEG2RAD(args->cam_persp.fov_y); + cam_args.lens_radius = args->cam_persp.lens_radius; + cam_args.focal_distance = args->cam_persp.focal_dst; + + return scam_create_perspective + (htrdr_get_logger(cmd->htrdr), + htrdr_get_allocator(cmd->htrdr), + htrdr_get_verbosity_level(cmd->htrdr), + &cam_args, + &cmd->camera); +} + +static res_T +setup_camera + (struct htrdr_atmosphere* cmd, + const struct htrdr_atmosphere_args* args) +{ res_T res = RES_OK; - ASSERT(cmd && args); + ASSERT(cmd->output_type == HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE); + switch(args->cam_type) { + case HTRDR_ARGS_CAMERA_ORTHOGRAPHIC: + res = setup_camera_orthographic(cmd, args); + break; + case HTRDR_ARGS_CAMERA_PERSPECTIVE: + res = setup_camera_perspective(cmd, args); + break; + default: FATAL("Unreachable code.\n"); break; + } + return res; +} - cmd->sensor.type = args->sensor_type; +static res_T +setup_flux_map + (struct htrdr_atmosphere* cmd, + const struct htrdr_atmosphere_args* args) +{ + ASSERT(cmd && args); + ASSERT(cmd->output_type == HTRDR_ATMOSPHERE_ARGS_OUTPUT_FLUX_MAP); - if(args->spectral.spectral_type == HTRDR_SPECTRAL_SW_CIE_XYZ - && args->sensor_type != HTRDR_SENSOR_CAMERA) { - htrdr_log_err(cmd->htrdr, "the CIE 1931 XYZ spectral integration can be used " - "only with a camera sensor.\n"); - res = RES_BAD_ARG; - goto error; + if(args->spectral.spectral_type == HTRDR_SPECTRAL_SW_CIE_XYZ) { + htrdr_log_err(cmd->htrdr, + "the CIE 1931 XYZ spectral integration can be used only with a camera" + "sensor.\n"); + return RES_BAD_ARG; } - switch(args->sensor_type) { - case HTRDR_SENSOR_CAMERA: - proj_ratio = - (double)args->image.definition[0] - / (double)args->image.definition[1]; - 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); + return htrdr_rectangle_create + (cmd->htrdr, + args->flux_map.size, + args->flux_map.position, + args->flux_map.target, + args->flux_map.up, + &cmd->flux_map); +} + +static res_T +setup_sensor + (struct htrdr_atmosphere* cmd, + const struct htrdr_atmosphere_args* args) +{ + res_T res = RES_OK; + switch(cmd->output_type) { + case HTRDR_ATMOSPHERE_ARGS_OUTPUT_FLUX_MAP: + res = setup_flux_map(cmd, args); break; - case HTRDR_SENSOR_RECTANGLE: - res = htrdr_rectangle_create - (cmd->htrdr, - args->sensor.rectangle.size, - args->sensor.rectangle.position, - args->sensor.rectangle.target, - args->sensor.rectangle.up, - &cmd->sensor.rectangle); + case HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE: + res = setup_camera(cmd, args); break; - default: FATAL("Unreachable code.\n"); break; + default: /* Nothing to do */ break; } - if(res != RES_OK) goto error; - -exit: return res; -error: - goto exit; } static res_T @@ -251,8 +308,8 @@ 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) SCAM(ref_put(cmd->sensor.camera)); - if(cmd->sensor.rectangle) htrdr_rectangle_ref_put(cmd->sensor.rectangle); + if(cmd->camera) SCAM(ref_put(cmd->camera)); + if(cmd->flux_map) htrdr_rectangle_ref_put(cmd->flux_map); if(cmd->buf) htrdr_buffer_ref_put(cmd->buf); if(cmd->sky) HTSKY(ref_put(cmd->sky)); if(cmd->output && cmd->output != stdout) fclose(cmd->output); @@ -290,8 +347,7 @@ htrdr_atmosphere_create } ref_init(&cmd->ref); str_init(htrdr_get_allocator(htrdr), &cmd->output_name); - cmd->dump_volumetric_acceleration_structure = - args->dump_volumetric_acceleration_structure; + cmd->output_type = args->output_type; cmd->verbose = args->verbose; cmd->spp = args->image.spp; cmd->width = args->image.definition[0]; @@ -398,7 +454,7 @@ htrdr_atmosphere_create } - if(!cmd->dump_volumetric_acceleration_structure) { + if(cmd->output_type != HTRDR_ATMOSPHERE_ARGS_OUTPUT_OCTREES) { struct htrdr_pixel_format pixfmt = HTRDR_PIXEL_FORMAT_NULL; atmosphere_get_pixel_format(cmd, &pixfmt); @@ -446,19 +502,17 @@ res_T htrdr_atmosphere_run(struct htrdr_atmosphere* cmd) { res_T res = RES_OK; - - if(cmd->dump_volumetric_acceleration_structure) { - res = dump_volumetric_acceleration_structure(cmd); - if(res != RES_OK) goto error; - } else { - res = atmosphere_draw_map(cmd); - if(res != RES_OK) goto error; + switch(cmd->output_type) { + case HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE: + case HTRDR_ATMOSPHERE_ARGS_OUTPUT_FLUX_MAP: + res = atmosphere_draw_map(cmd); + break; + case HTRDR_ATMOSPHERE_ARGS_OUTPUT_OCTREES: + res = dump_volumetric_acceleration_structure(cmd); + break; + default: FATAL("Unreachable code.\n"); break; } - -exit: return res; -error: - goto exit; } /******************************************************************************* @@ -470,12 +524,12 @@ atmosphere_get_pixel_format struct htrdr_pixel_format* fmt) { ASSERT(cmd && fmt); - switch(cmd->sensor.type) { - case HTRDR_SENSOR_RECTANGLE: + switch(cmd->output_type) { + case HTRDR_ATMOSPHERE_ARGS_OUTPUT_FLUX_MAP: fmt->size = sizeof(struct atmosphere_pixel_flux); fmt->alignment = ALIGNOF(struct atmosphere_pixel_flux); break; - case HTRDR_SENSOR_CAMERA: + case HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE: switch(cmd->spectral_type) { case HTRDR_SPECTRAL_LW: case HTRDR_SPECTRAL_SW: diff --git a/src/atmosphere/htrdr_atmosphere_args.c b/src/atmosphere/htrdr_atmosphere_args.c @@ -36,10 +36,10 @@ print_help(const char* cmd) printf( " -a GAS filename of the gas optical properties.\n"); - printf( -" -C <camera> define the rendering point of view. Refer to the\n" -" %s man page for the list of camera options.\n", cmd); +" -C <perspective-camera>\n" +" define the perspective camera. Refer to the man page\n" +" for the list of camera options.\n"); printf( " -c CLOUDS filename of the clouds properties.\n"); printf( @@ -58,8 +58,8 @@ print_help(const char* cmd) printf( " -h display this help and exit.\n"); printf( -" -i <image> define the image to compute. Refer to the %s man\n" -" page for the list of image options\n", cmd); +" -i <image> define the image to compute. Refer to the man\n" +" page for the list of image options\n"); printf( " -M MATERIALS filename of the ground materials.\n"); printf( @@ -77,15 +77,19 @@ print_help(const char* cmd) printf( " -p <rectangle> switch in flux computation by defining the rectangular\n" " sensor onto which the flux is computed. Refer to the\n" -" %s man page for the list of rectangle options.\n", cmd); +" man page for the list of rectangle options.\n"); + printf( +" -P <orthoraphic-camera>\n" +" define the orthoraphic camera. Refer to the man page\n" +" for the list of orthographic camera options.\n"); printf( " -R infinitely repeat the ground along the X and Y axis.\n"); printf( " -r infinitely repeat the clouds along the X and Y axis.\n"); printf( " -s <spectral> define the type and range of the spectral\n" -" integration. Refer to the %s man page for the list\n" -" of spectral options\n", cmd); +" integration. Refer to the man page for the list\n" +" of spectral options\n"); printf( " -T THRESHOLD optical thickness used as threshold during the\n" " building of the volumetric acceleration structure.\n" @@ -193,16 +197,19 @@ htrdr_atmosphere_args_init *args = HTRDR_ATMOSPHERE_ARGS_DEFAULT; - while((opt = getopt(argc, argv, "a:C:c:D:dfg:hi:M:m:n:O:o:p:Rrs:T:t:V:v")) != -1) { + while((opt = getopt(argc, argv, "a:C:c:D:dfg:hi:M:m:n:O:o:P:p:Rrs:T:t:V:v")) != -1) { switch(opt) { case 'a': args->filename_gas = optarg; break; - case 'C': - args->sensor_type = HTRDR_SENSOR_CAMERA; - res = htrdr_args_camera_parse(&args->sensor.camera, optarg); + case 'C': + args->output_type = HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE; + args->cam_type = HTRDR_ARGS_CAMERA_PERSPECTIVE; + res = htrdr_args_camera_perspective_parse(&args->cam_persp, optarg); break; case 'c': args->filename_les = optarg; break; case 'D': res = parse_sun_dir(args, optarg); break; - case 'd': args->dump_volumetric_acceleration_structure = 1; break; + case 'd': + args->output_type = HTRDR_ATMOSPHERE_ARGS_OUTPUT_OCTREES; + break; case 'f': args->force_overwriting = 1; break; case 'g': args->filename_obj = optarg; break; case 'h': @@ -219,8 +226,13 @@ htrdr_atmosphere_args_init case 'O': args->filename_cache = optarg; break; case 'o': args->filename_output = optarg; break; case 'p': - args->sensor_type = HTRDR_SENSOR_RECTANGLE; - res = htrdr_args_rectangle_parse(&args->sensor.rectangle, optarg); + args->output_type = HTRDR_ATMOSPHERE_ARGS_OUTPUT_FLUX_MAP;; + res = htrdr_args_rectangle_parse(&args->flux_map, optarg); + break; + case 'P': + args->output_type = HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE; + args->cam_type = HTRDR_ARGS_CAMERA_ORTHOGRAPHIC; + res = htrdr_args_camera_orthographic_parse(&args->cam_ortho, optarg); break; case 'r': args->repeat_clouds = 1; break; case 'R': args->repeat_ground = 1; break; diff --git a/src/atmosphere/htrdr_atmosphere_args.h.in b/src/atmosphere/htrdr_atmosphere_args.h.in @@ -19,12 +19,18 @@ #define HTRDR_ATMOSPHERE_ARGS_H #include "core/htrdr_args.h" -#include "core/htrdr_sensor.h" #include <rsys/rsys.h> #include <limits.h> /* UINT_MAX support */ +enum htrdr_atmosphere_args_output_type { + HTRDR_ATMOSPHERE_ARGS_OUTPUT_FLUX_MAP, + HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE, + HTRDR_ATMOSPHERE_ARGS_OUTPUT_OCTREES, + HTRDR_ATMOSPHERE_ARGS_OUTPUT_TYPES_COUNT__ +}; + struct htrdr_atmosphere_args { const char* filename_gas; /* Path of the gas file */ const char* filename_les; /* Path of the HTCP file */ @@ -37,11 +43,11 @@ struct htrdr_atmosphere_args { const char* sky_mtl_name; /* Name of the sky material */ - union { - struct htrdr_args_camera camera; /* Pinhole Camera */ - struct htrdr_args_rectangle rectangle; /* Flux map */ - } sensor; - enum htrdr_sensor_type sensor_type; + struct htrdr_args_camera_perspective cam_persp; /* Perspective camera */ + struct htrdr_args_camera_orthographic cam_ortho; /* Orthographic camera */ + enum htrdr_args_camera_type cam_type; + + struct htrdr_args_rectangle flux_map; /* Flux map */ struct htrdr_args_image image; /* Output Image */ struct htrdr_args_spectral spectral; /* Spectral domain */ @@ -58,8 +64,8 @@ struct htrdr_atmosphere_args { /* Miscellaneous parameters */ unsigned nthreads; /* Hint on the number of threads to use */ + enum htrdr_atmosphere_args_output_type output_type; int force_overwriting; - int dump_volumetric_acceleration_structure; int verbose; /* Verbosity level */ int quit; /* Stop the command */ }; @@ -76,8 +82,11 @@ struct htrdr_atmosphere_args { \ @HTRDR_ATMOSPHERE_ARGS_DEFAULT_SKY_MTL_NAME@, /* Sky mtl name */ \ \ - {HTRDR_ARGS_CAMERA_DEFAULT__}, /* Sensor */ \ - HTRDR_SENSOR_CAMERA, /* Sensor type */ \ + HTRDR_ARGS_CAMERA_PERSPECTIVE_DEFAULT__, /* Perspective camera */ \ + HTRDR_ARGS_CAMERA_ORTHOGRAPHIC_DEFAULT__, /* Orthographic camera */ \ + HTRDR_ARGS_CAMERA_PERSPECTIVE, \ + \ + HTRDR_ARGS_RECTANGLE_DEFAULT__, /* Flux map */ \ \ HTRDR_ARGS_IMAGE_DEFAULT__, /* Image */ \ HTRDR_ARGS_SPECTRAL_DEFAULT__, /* Spectral */ \ @@ -92,8 +101,8 @@ struct htrdr_atmosphere_args { 0, /* Repeat ground */ \ \ UINT_MAX, /* #threads */ \ + HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE, /* Output type */ \ 0, /* Force overwriting */ \ - 0, /* dump volumetric acceleration structure */ \ 0, /* Verbose flag */ \ 0 /* Stop the command */ \ } diff --git a/src/atmosphere/htrdr_atmosphere_c.h b/src/atmosphere/htrdr_atmosphere_c.h @@ -18,9 +18,10 @@ #ifndef HTRDR_ATMOSPHERE_C_H #define HTRDR_ATMOSPHERE_C_H +#include "atmosphere/htrdr_atmosphere_args.h" + #include "core/htrdr_accum.h" #include "core/htrdr_buffer.h" -#include "core/htrdr_sensor.h" #include "core/htrdr_spectral.h" #include <rsys/ref_count.h> @@ -83,6 +84,7 @@ struct htrdr_buffer; struct htrdr_cie_xyz; struct htrdr_materials; struct htrdr_ran_wlen; +struct ssp_rng; struct htrdr_atmosphere { struct htrdr_atmosphere_ground* ground; @@ -91,7 +93,8 @@ struct htrdr_atmosphere { struct htrdr_cie_xyz* cie; struct htrdr_ran_wlen* ran_wlen; - struct htrdr_sensor sensor; + struct scam* camera; /* Camera */ + struct htrdr_rectangle* flux_map; /* Flux map */ struct htrdr_buffer_layout buf_layout; struct htrdr_buffer* buf; /* NULL on non master processes */ @@ -111,7 +114,7 @@ struct htrdr_atmosphere { unsigned grid_max_definition[3]; /* Max definition of the acceleration grids */ unsigned nthreads; /* #threads of the process */ - int dump_volumetric_acceleration_structure; /* Dump octrees */ + enum htrdr_atmosphere_args_output_type output_type; int verbose; /* Verbosity level */ ref_T ref; diff --git a/src/atmosphere/htrdr_atmosphere_draw_map.c b/src/atmosphere/htrdr_atmosphere_draw_map.c @@ -117,7 +117,7 @@ draw_pixel_image cmd = args->context; ASSERT(cmd); ASSERT(cmd->spectral_type == HTRDR_SPECTRAL_SW_CIE_XYZ); - ASSERT(cmd->sensor.type == HTRDR_SENSOR_CAMERA); + ASSERT(cmd->output_type == HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE); /* Reset accumulators */ XYZ[0] = HTRDR_ACCUM_NULL; @@ -152,7 +152,7 @@ draw_pixel_image sample.lens[1] = ssp_rng_canonical(args->rng); /* Generate a camera ray */ - scam_generate_ray(cmd->sensor.camera, &sample, &ray); + scam_generate_ray(cmd->camera, &sample, &ray); r0 = ssp_rng_canonical(args->rng); r1 = ssp_rng_canonical(args->rng); @@ -216,7 +216,7 @@ draw_pixel_flux cmd = args->context; ASSERT(cmd); - ASSERT(cmd->sensor.type == HTRDR_SENSOR_RECTANGLE); + ASSERT(cmd->output_type == HTRDR_ATMOSPHERE_ARGS_OUTPUT_FLUX_MAP); ASSERT(cmd->spectral_type == HTRDR_SPECTRAL_LW || cmd->spectral_type == HTRDR_SPECTRAL_SW); @@ -240,7 +240,7 @@ draw_pixel_flux /* Begin the registration of the time spent in the realisation */ time_current(&t0); - res = sample_rectangle_ray(cmd, cmd->sensor.rectangle, args->pixel_coord, + res = sample_rectangle_ray(cmd, cmd->flux_map, args->pixel_coord, args->pixel_normalized_size, args->rng, ray_org, ray_dir); if(res != RES_OK) continue; /* Reject the current sample */ @@ -271,7 +271,7 @@ draw_pixel_flux /* Compute direct contribution if necessary */ htrdr_atmosphere_sun_sample_direction(cmd->sun, args->rng, sun_dir); - htrdr_rectangle_get_normal(cmd->sensor.rectangle, N); + htrdr_rectangle_get_normal(cmd->flux_map, N); cos_N_sun_dir = d3_dot(N, sun_dir); if(cos_N_sun_dir <= 0) { @@ -331,7 +331,7 @@ draw_pixel_xwave (void)htrdr; cmd = args->context; - ASSERT(cmd->sensor.type == HTRDR_SENSOR_CAMERA); + ASSERT(cmd->output_type == HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE); ASSERT(cmd->spectral_type == HTRDR_SPECTRAL_LW || cmd->spectral_type == HTRDR_SPECTRAL_SW); @@ -363,7 +363,7 @@ draw_pixel_xwave sample.lens[1] = ssp_rng_canonical(args->rng); /* Generate a camera ray */ - scam_generate_ray(cmd->sensor.camera, &sample, &ray); + scam_generate_ray(cmd->camera, &sample, &ray); r0 = ssp_rng_canonical(args->rng); r1 = ssp_rng_canonical(args->rng); @@ -434,7 +434,8 @@ setup_draw_map_args_rectangle (struct htrdr_atmosphere* cmd, struct htrdr_draw_map_args* args) { - ASSERT(cmd && cmd->sensor.type == HTRDR_SENSOR_RECTANGLE && args); + ASSERT(cmd && args); + ASSERT(cmd->output_type == HTRDR_ATMOSPHERE_ARGS_OUTPUT_FLUX_MAP); *args = HTRDR_DRAW_MAP_ARGS_NULL; args->draw_pixel = draw_pixel_flux; args->buffer_layout = cmd->buf_layout; @@ -447,7 +448,8 @@ setup_draw_map_args_camera (struct htrdr_atmosphere* cmd, struct htrdr_draw_map_args* args) { - ASSERT(cmd && cmd->sensor.type == HTRDR_SENSOR_CAMERA && args); + ASSERT(cmd && args); + ASSERT(cmd->output_type == HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE); *args = HTRDR_DRAW_MAP_ARGS_NULL; args->buffer_layout = cmd->buf_layout; @@ -561,7 +563,7 @@ dump_buffer void* pix_raw = htrdr_buffer_at(buf, x, y); ASSERT(IS_ALIGNED(pix_raw, pixfmt.alignment)); - if(cmd->sensor.type == HTRDR_SENSOR_RECTANGLE) { + if(cmd->output_type == HTRDR_ATMOSPHERE_ARGS_OUTPUT_FLUX_MAP) { const struct atmosphere_pixel_flux* pix = pix_raw; dump_pixel_flux(pix, time_acc, flux_acc, stream); } else if(cmd->spectral_type == HTRDR_SPECTRAL_SW_CIE_XYZ) { @@ -594,11 +596,11 @@ atmosphere_draw_map(struct htrdr_atmosphere* cmd) args.spp = cmd->spp; - switch(cmd->sensor.type) { - case HTRDR_SENSOR_RECTANGLE: + switch(cmd->output_type) { + case HTRDR_ATMOSPHERE_ARGS_OUTPUT_FLUX_MAP: setup_draw_map_args_rectangle(cmd, &args); break; - case HTRDR_SENSOR_CAMERA: + case HTRDR_ATMOSPHERE_ARGS_OUTPUT_IMAGE: setup_draw_map_args_camera(cmd, &args); break; default: FATAL("Unreachable code.\n"); break; @@ -619,7 +621,7 @@ atmosphere_draw_map(struct htrdr_atmosphere* cmd) "Time per radiative path (in micro seconds): %g +/- %g\n", path_time.E, path_time.SE); - if(cmd->sensor.type == HTRDR_SENSOR_RECTANGLE) { + if(cmd->output_type == HTRDR_ATMOSPHERE_ARGS_OUTPUT_FLUX_MAP) { htrdr_accum_get_estimation(&flux_acc, &flux); htrdr_log(cmd->htrdr, "Radiative flux density (in W/(external m^2)): %g +/- %g\n", diff --git a/src/atmosphere/htrdr_atmosphere_main.c b/src/atmosphere/htrdr_atmosphere_main.c @@ -53,7 +53,7 @@ htrdr_atmosphere_main(int argc, char** argv) res = htrdr_create(&mem_default_allocator, &htrdr_args, &htrdr); if(res != RES_OK) goto error; - if(cmd_args.dump_volumetric_acceleration_structure + if(cmd_args.output_type == HTRDR_ATMOSPHERE_ARGS_OUTPUT_OCTREES && htrdr_get_mpi_rank(htrdr) != 0) { goto exit; /* Nothing to do except for the master process */ } @@ -74,7 +74,7 @@ exit: memsz_end = MEM_ALLOCATED_SIZE(&mem_default_allocator); if(memsz_begin != memsz_end) { ASSERT(memsz_end >= memsz_begin); - fprintf(stderr, HTRDR_LOG_WARNING_PREFIX"Memory leaks: %lu Bytes\n", + fprintf(stderr, HTRDR_LOG_WARNING_PREFIX"Memory leaks: %lu Bytes\n", (unsigned long)(memsz_end - memsz_begin)); err = -1; } diff --git a/src/combustion/htrdr_combustion.c b/src/combustion/htrdr_combustion.c @@ -161,23 +161,50 @@ error: } static res_T -setup_camera +setup_camera_orthographic + (struct htrdr_combustion* cmd, + const struct htrdr_combustion_args* args) +{ + struct scam_orthographic_args cam_args = SCAM_ORTHOGRAPHIC_ARGS_DEFAULT; + ASSERT(cmd && args && args->image.definition[0] && args->image.definition[1]); + ASSERT(cmd->output_type == HTRDR_COMBUSTION_ARGS_OUTPUT_IMAGE); + ASSERT(args->cam_type == HTRDR_ARGS_CAMERA_ORTHOGRAPHIC); + + d3_set(cam_args.position, args->cam_ortho.position); + d3_set(cam_args.target, args->cam_ortho.target); + d3_set(cam_args.up, args->cam_ortho.up); + cam_args.height = args->cam_ortho.height; + cam_args.aspect_ratio = + (double)args->image.definition[0] + / (double)args->image.definition[1]; + + return scam_create_orthographic + (htrdr_get_logger(cmd->htrdr), + htrdr_get_allocator(cmd->htrdr), + htrdr_get_verbosity_level(cmd->htrdr), + &cam_args, + &cmd->camera); +} + +static res_T +setup_camera_perspective (struct htrdr_combustion* cmd, const struct htrdr_combustion_args* args) { 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); + ASSERT(args->cam_type == HTRDR_ARGS_CAMERA_PERSPECTIVE); - 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 = + d3_set(cam_args.position, args->cam_persp.position); + d3_set(cam_args.target, args->cam_persp.target); + d3_set(cam_args.up, args->cam_persp.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; + cam_args.field_of_view = MDEG2RAD(args->cam_persp.fov_y); + cam_args.lens_radius = args->cam_persp.lens_radius; + cam_args.focal_distance = args->cam_persp.focal_dst; return scam_create_perspective (htrdr_get_logger(cmd->htrdr), @@ -188,6 +215,25 @@ setup_camera } static res_T +setup_camera + (struct htrdr_combustion* cmd, + const struct htrdr_combustion_args* args) +{ + res_T res = RES_OK; + ASSERT(cmd->output_type == HTRDR_COMBUSTION_ARGS_OUTPUT_IMAGE); + switch(args->cam_type) { + case HTRDR_ARGS_CAMERA_ORTHOGRAPHIC: + res = setup_camera_orthographic(cmd, args); + break; + case HTRDR_ARGS_CAMERA_PERSPECTIVE: + res = setup_camera_perspective(cmd, args); + break; + default: FATAL("Unreachable code.\n"); break; + } + return res; +} + +static res_T setup_flux_map (struct htrdr_combustion* cmd, const struct htrdr_combustion_args* args) diff --git a/src/combustion/htrdr_combustion_args.c b/src/combustion/htrdr_combustion_args.c @@ -39,8 +39,9 @@ print_help(const char* cmd) "to the RDG-FA theory and lightened by a laser source.\n\n"); printf( -" -C <camera> define the rendering point of view. Refer to the\n" -" man page for the list of camera options.\n"); +" -C <perspective-camera>\n" +" define the perspective camera. Refer to the man page\n" +" for the list of camera options.\n"); printf( " -D FLUX_DENSITY\n" " flux density of the laser in W/m^2\n" @@ -92,6 +93,10 @@ print_help(const char* cmd) printf( " -p THERMOPROPS path toward the thermodynamic properties.\n"); printf( +" -P <orthoraphic-camera>\n" +" define the orthoraphic camera. Refer to the man page\n" +" for the list of orthographic camera options.\n"); + printf( " -r REFRACT_ID path toward the per wavelength refractive\n" " indices.\n"); printf( @@ -246,11 +251,12 @@ htrdr_combustion_args_init *args = HTRDR_COMBUSTION_ARGS_DEFAULT; - while((opt = getopt(argc, argv, "C:D:d:F:fg:hIi:l:m:NO:o:p:R:r:sT:t:V:vw:")) != -1) { + while((opt = getopt(argc, argv, "C:D:d:F:fg:hIi:l:m:NO:o:P:p:R:r:sT:t:V:vw:")) != -1) { switch(opt) { case 'C': args->output_type = HTRDR_COMBUSTION_ARGS_OUTPUT_IMAGE; - res = htrdr_args_camera_parse(&args->camera, optarg); + args->cam_type = HTRDR_ARGS_CAMERA_PERSPECTIVE; + res = htrdr_args_camera_perspective_parse(&args->cam_persp, optarg); break; case 'D': res = cstr_to_double(optarg, &args->laser_flux_density); @@ -286,6 +292,11 @@ htrdr_combustion_args_init case 'O': args->path_cache = optarg; break; case 'o': args->path_output = optarg; break; case 'p': args->path_therm_props = optarg; break; + case 'P': + args->output_type = HTRDR_COMBUSTION_ARGS_OUTPUT_IMAGE; + args->cam_type = HTRDR_ARGS_CAMERA_ORTHOGRAPHIC; + res = htrdr_args_camera_orthographic_parse(&args->cam_ortho, optarg); + break; case 'r': args->path_refract_ids = optarg; break; case 'R': args->output_type = HTRDR_COMBUSTION_ARGS_OUTPUT_FLUX_MAP; diff --git a/src/combustion/htrdr_combustion_args.h.in b/src/combustion/htrdr_combustion_args.h.in @@ -68,7 +68,10 @@ struct htrdr_combustion_args { const char* path_cache; /* Path of the file to store/restore cached data */ const char* path_output; /* Name of the output file */ - struct htrdr_args_camera camera; /* Pinhole Camera */ + struct htrdr_args_camera_perspective cam_persp; /* Perspective camera */ + struct htrdr_args_camera_orthographic cam_ortho; /* Ortographic camera */ + enum htrdr_args_camera_type cam_type; + struct htrdr_args_rectangle flux_map; /* Flux map */ struct htrdr_args_rectangle laser; /* Laser surface emission */ @@ -106,7 +109,10 @@ struct htrdr_combustion_args { NULL, /* Cache path */ \ NULL, /* Output path */ \ \ - HTRDR_ARGS_CAMERA_DEFAULT__, /* Pinhole camera */ \ + HTRDR_ARGS_CAMERA_PERSPECTIVE_DEFAULT__, /* Perspective camera */ \ + HTRDR_ARGS_CAMERA_ORTHOGRAPHIC_DEFAULT__, /* Orthographic camera */ \ + HTRDR_ARGS_CAMERA_PERSPECTIVE, \ + \ HTRDR_ARGS_RECTANGLE_DEFAULT__, /* Flux map */ \ \ HTRDR_ARGS_RECTANGLE_DEFAULT__, /* Laser surface emission */ \ diff --git a/src/core/htrdr.h b/src/core/htrdr.h @@ -77,9 +77,10 @@ htrdr_fprint_license(const char* cmd, FILE* stream) { ASSERT(cmd); fprintf(stream, -"%s is free software released under the GNU GPL license, version\n" -"3 or later. You are free to change or redistribute it under certain\n" -"conditions <http://gnu.org/licenses/gpl.html>.\n", cmd); +"%s is free software released under the GNU GPL license,\n" +"version 3 or later. You are free to change or redistribute it\n" +"under certain conditions <http://gnu.org/licenses/gpl.html>.\n", + cmd); } BEGIN_DECLS diff --git a/src/core/htrdr_args.c b/src/core/htrdr_args.c @@ -68,10 +68,11 @@ parse_fov(const char* str, double* out_fov) fprintf(stderr, "Invalid field of view `%s'.\n", str); return RES_BAD_ARG; } - if(fov <= HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MIN - || fov >= HTRDR_ARGS_CAMERA_FOV_EXCLUSIVE_MAX) { + if(fov <= HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN + || fov >= HTRDR_ARGS_CAMERA_PERSPECTIVE_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); + HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN, + HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MAX); return RES_BAD_ARG; } *out_fov = fov; @@ -139,6 +140,30 @@ parse_focal_dst(const char* str, double* out_dst) } static res_T +parse_image_plane_height(const char* str, double* out_height) +{ + double height; + res_T res = RES_OK; + ASSERT(str && out_height); + + res = cstr_to_double(str, &height); + if(res != RES_OK) { + fprintf(stderr, + "Invalid height `%s' of the image plane of the orthographic camera.\n", + str); + return RES_BAD_ARG; + } + if(height <= 0) { + fprintf(stderr, + "Invalid negative or null height of the image plane " + "of the orthographic camera.\n"); + return RES_BAD_ARG; + } + *out_height = height; + return RES_OK; +} + +static res_T parse_image_parameter(const char* str, void* args) { char buf[128]; @@ -201,10 +226,10 @@ error: } static res_T -parse_camera_parameter(const char* str, void* args) +parse_camera_perspective_parameter(const char* str, void* args) { char buf[128]; - struct htrdr_args_camera* cam = args; + struct htrdr_args_camera_perspective* cam = args; char* key; char* val; char* ctx; @@ -213,7 +238,7 @@ parse_camera_parameter(const char* str, void* args) if(strlen(str) >= sizeof(buf) -1/*NULL char*/) { fprintf(stderr, - "Could not duplicate the camera option string `%s'.\n", str); + "Could not duplicate the perspective camera option string `%s'.\n", str); res = RES_MEM_ERR; goto error; } @@ -223,14 +248,15 @@ parse_camera_parameter(const char* str, void* args) val = strtok_r(NULL, "", &ctx); if(!val) { - fprintf(stderr, "Missing value to the camera option `%s'.\n", key); + fprintf(stderr, + "Missing value to the perspective camera parameter `%s'.\n", key); res = RES_BAD_ARG; goto error; } #define PARSE(Name, Func) { \ if(RES_OK != (res = Func)) { \ - fprintf(stderr, "Invalid camera "Name" `%s'.\n", val); \ + fprintf(stderr, "Invalid perspective camera "Name" `%s'.\n", val); \ goto error; \ } \ } (void)0 @@ -251,7 +277,61 @@ parse_camera_parameter(const char* str, void* args) } 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); + fprintf(stderr, "Invalid perspective camera parameter `%s'.\n", key); + res = RES_BAD_ARG; + goto error; + } + #undef PARSE +exit: + return res; +error: + goto exit; +} + +static res_T +parse_camera_orthographic_parameter(const char* str, void* args) +{ + char buf[128]; + struct htrdr_args_camera_orthographic* cam = args; + char* key; + char* val; + char* ctx; + res_T res = RES_OK; + ASSERT(cam && str); + + if(strlen(str) >= sizeof(buf) - 1/*NULL char*/) { + fprintf(stderr, + "Could not duplicate the orthographic camera option string `%s'.\n", str); + res = RES_MEM_ERR; + goto error; + } + strncpy(buf, str, sizeof(buf)); + + key = strtok_r(buf, "=", &ctx); + val = strtok_r(NULL, "", &ctx); + + if(!val) { + fprintf(stderr, + "Missing value to the orthographic camera parameter `%s'.\n", key); + res = RES_BAD_ARG; + goto error; + } + #define PARSE(Name, Func) { \ + if(RES_OK != (res = Func)) { \ + fprintf(stderr, "Invalid orthographic camera "Name" `%s'.\n", val); \ + goto error; \ + } \ + } (void)0 + if(!strcmp(key, "pos")) { + PARSE("position", parse_doubleX(val, cam->position, 3)); + } else if(!strcmp(key, "tgt")) { + PARSE("target", parse_doubleX(val, cam->target, 3)); + } else if(!strcmp(key, "up")) { + PARSE("up vector", parse_doubleX(val, cam->up, 3)); + } else if(!strcmp(key, "height")) { + PARSE("image plane height", parse_image_plane_height(val, &cam->height)); + } else { + fprintf(stderr, "Invalid orthographic camera parameter `%s'.\n", key); res = RES_BAD_ARG; goto error; } @@ -464,7 +544,9 @@ error: * Exported functions ******************************************************************************/ res_T -htrdr_args_camera_parse(struct htrdr_args_camera* cam, const char* str) +htrdr_args_camera_perspective_parse + (struct htrdr_args_camera_perspective* cam, + const char* str) { res_T res = RES_OK; @@ -473,7 +555,7 @@ htrdr_args_camera_parse(struct htrdr_args_camera* cam, const char* str) goto error; } - res = cstr_parse_list(str, ':', parse_camera_parameter, cam); + res = cstr_parse_list(str, ':', parse_camera_perspective_parameter, cam); if(res != RES_OK) goto error; if(cam->focal_length < 0) { @@ -504,16 +586,16 @@ htrdr_args_camera_parse(struct htrdr_args_camera* cam, const char* str) 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) { + if(cam->fov_y <= HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN + || cam->fov_y >= HTRDR_ARGS_CAMERA_PERSPECTIVE_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); + HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN, + HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MAX); res = RES_BAD_ARG; goto error; } @@ -523,7 +605,16 @@ exit: return res; error: goto exit; -} +} + +res_T +htrdr_args_camera_orthographic_parse + (struct htrdr_args_camera_orthographic* cam, + const char* str) +{ + if(!cam || !str) return RES_BAD_ARG; + return cstr_parse_list(str, ':', parse_camera_orthographic_parameter, cam); +} 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 @@ -24,11 +24,18 @@ #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@ +#define HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN \ + @HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN@ +#define HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MAX \ + @HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MAX@ + +enum htrdr_args_camera_type { + HTRDR_ARGS_CAMERA_PERSPECTIVE, + HTRDR_ARGS_CAMERA_ORTHOGRAPHIC, + HTRDR_ARGS_CAMERA_TYPES_COUNT__ +}; -/* Arguments of a pinhole camera sensor */ -struct htrdr_args_camera { +struct htrdr_args_camera_perspective { double position[3]; /* Lens position */ double target[3]; /* Targeted position */ double up[3]; /* Up vector of the camera */ @@ -37,17 +44,32 @@ struct htrdr_args_camera { 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__ { \ +#define HTRDR_ARGS_CAMERA_PERSPECTIVE_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 */ \ + @HTRDR_ARGS_DEFAULT_CAMERA_PERSPECTIVE_FOV@, /* Vertical field of view */ \ + @HTRDR_ARGS_DEFAULT_CAMERA_PERSPECTIVE_LENS_RADIUS@, /* Radius of the lens */\ + @HTRDR_ARGS_DEFAULT_CAMERA_PERSPECTIVE_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__; +static const struct htrdr_args_camera_perspective +HTRDR_ARGS_CAMERA_PERSPECTIVE_DEFAULT = HTRDR_ARGS_CAMERA_PERSPECTIVE_DEFAULT__; + +struct htrdr_args_camera_orthographic { + double position[3]; /* Lens position */ + double target[3]; /* Targeted position */ + double up[3]; /* Up vector of the camera */ + double height; /* Height of the image plane */ +}; +#define HTRDR_ARGS_CAMERA_ORTHOGRAPHIC_DEFAULT__ { \ + {@HTRDR_ARGS_DEFAULT_CAMERA_POS@}, /* position */ \ + {@HTRDR_ARGS_DEFAULT_CAMERA_TGT@}, /* target */ \ + {@HTRDR_ARGS_DEFAULT_CAMERA_UP@}, /* Camera up */ \ + @HTRDR_ARGS_DEFAULT_CAMERA_ORTHOGRAPHIC_HEIGHT@ /* Image plane height */ \ +} +static const struct htrdr_args_camera_orthographic +HTRDR_ARGS_CAMERA_ORTHOGRAPHIC_DEFAULT = HTRDR_ARGS_CAMERA_ORTHOGRAPHIC_DEFAULT__; /* Arguments of a rectangular sensor */ struct htrdr_args_rectangle { @@ -106,8 +128,13 @@ static const struct htrdr_args_spectral HTRDR_ARGS_SPECTRAL_DEFAULT = BEGIN_DECLS HTRDR_CORE_API res_T -htrdr_args_camera_parse - (struct htrdr_args_camera* cam, +htrdr_args_camera_perspective_parse + (struct htrdr_args_camera_perspective* cam, + const char* str); + +HTRDR_CORE_API res_T +htrdr_args_camera_orthographic_parse + (struct htrdr_args_camera_orthographic* cam, const char* str); HTRDR_CORE_API res_T