star-camera

Camera models
git clone git://git.meso-star.fr/star-camera.git
Log | Files | Refs | README | LICENSE

commit c91dba27d066e9bb411b9d36af7db68cf7a5c82c
parent 8cca97983601296a007b151131168ea2e9e66563
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 22 Nov 2022 18:11:48 +0100

Add and test the scam_perspective_get_solid_angle function

Diffstat:
Msrc/scam.h | 5+++++
Msrc/scam_c.h | 2++
Msrc/scam_perspective.c | 79++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/test_scam_orthographic.c | 2++
Msrc/test_scam_perspective_pinhole.c | 18+++++++++++++++++-
5 files changed, 78 insertions(+), 28 deletions(-)

diff --git a/src/scam.h b/src/scam.h @@ -161,6 +161,11 @@ scam_field_of_view_to_focal_length const double field_of_view, double* focal_length); +SCAM_API res_T +scam_perspective_get_solid_angle + (const struct scam* camera, + double* solid_angle); /* In sr */ + END_DECLS #endif /* SCAM_H */ diff --git a/src/scam_c.h b/src/scam_c.h @@ -27,6 +27,7 @@ struct perspective { double position[3]; /* Lens position */ + double solid_angle; /* In sr */ double rcp_tan_half_fov; /* 1 / tan(vertical_fov / 2) */ double aspect_ratio; /* width / height */ double lens_radius; /* 0 <=> pinhole camera */ @@ -36,6 +37,7 @@ struct perspective { {1,0,0, 0,1,0, 0,0,1}, /* Screen to world transformation */ \ {1,0,0, 0,1,0, 0,0,1}, /* Camera to world transformation */ \ {0,0,0}, /* Lens position */ \ + 0.60111772988434627069, /* horizontal_fov * 2*sin(vertical_fov/2) */ \ 1.0, /* 1/tan(vertical_fov/2) */ \ 1.0, /* Aspect ratio */ \ 0.0, /* Lens radius */ \ diff --git a/src/scam_perspective.c b/src/scam_perspective.c @@ -26,48 +26,55 @@ * Helper functions ******************************************************************************/ static res_T -setup_perspective(struct scam* cam, const struct scam_perspective_args* args) +check_perspective_args + (struct scam* cam, + const struct scam_perspective_args* args) { - double x[3], y[3], z[3]; - int pinhole = 0; - res_T res = RES_OK; - ASSERT(cam && args && cam->type == SCAM_PERSPECTIVE); - - cam->param.persp = PERSPECTIVE_DEFAULT; - pinhole = args->lens_radius == 0; + if(!args) return RES_BAD_ARG; + /* Invalid aspect ratio */ if(args->aspect_ratio <= 0) { - log_err(cam, - "perspective camera: invalid aspect ratio: %g\n", + log_err(cam,"perspective camera: invalid aspect ratio: %g\n", args->aspect_ratio); - res = RES_BAD_ARG; - goto error; + return RES_BAD_ARG; } + /* Invalid lens radius */ if(args->lens_radius < 0) { - log_err(cam, - "perspective camera: invalid negative lens radius: %g\n", + log_err(cam,"perspective camera: invalid negative lens radius: %g\n", args->lens_radius); - res = RES_BAD_ARG; - goto error; + return RES_BAD_ARG; } - if(!pinhole && args->focal_distance < 0) { - log_err(cam, - "perspective camera: invalid negative focal distance: %g\n", + /* Invalid focal distance */ + if(args->lens_radius > 0 && args->focal_distance < 0) { + log_err(cam, "perspective camera: invalid negative focal distance: %g\n", args->focal_distance); - res = RES_BAD_ARG; - goto error; + return RES_BAD_ARG; } + /* Invalid field of view */ if(args->field_of_view <= 0 || args->field_of_view >= PI) { - log_err(cam, - "perspective camera: invalid vertical field of view: %g\n", + log_err(cam, "perspective camera: invalid vertical field of view: %g\n", args->field_of_view); - res = RES_BAD_ARG; - goto error; + return RES_BAD_ARG; } + return RES_OK; +} + +static res_T +setup_perspective(struct scam* cam, const struct scam_perspective_args* args) +{ + double hfov; /* Horizotal field of view */ + double half_vfov; /* (Vertical vield of view) / 2 */ + double tan_half_vfov; + double x[3], y[3], z[3]; + res_T res = RES_OK; + ASSERT(cam && args && cam->type == SCAM_PERSPECTIVE); + + cam->param.persp = PERSPECTIVE_DEFAULT; + if(d3_normalize(z, d3_sub(z, args->target, args->position)) <= 0 || d3_normalize(x, d3_cross(x, z, args->up)) <= 0 || d3_normalize(y, d3_cross(y, z, x)) <= 0) { @@ -81,7 +88,10 @@ setup_perspective(struct scam* cam, const struct scam_perspective_args* args) goto error; } - cam->param.persp.rcp_tan_half_fov = 1.0/tan(args->field_of_view*0.5); + half_vfov = args->field_of_view*0.5; + tan_half_vfov = tan(half_vfov); + + cam->param.persp.rcp_tan_half_fov = 1.0/tan_half_vfov; cam->param.persp.aspect_ratio = args->aspect_ratio; cam->param.persp.lens_radius = args->lens_radius; cam->param.persp.focal_distance = args->focal_distance; @@ -96,6 +106,10 @@ setup_perspective(struct scam* cam, const struct scam_perspective_args* args) d3_set(cam->param.persp.camera2world+3, y); d3_set(cam->param.persp.camera2world+6, z); + /* Compute the solid angle of the camera */ + hfov = 2*atan(args->aspect_ratio * tan_half_vfov); + cam->param.persp.solid_angle = hfov * 2*sin(half_vfov); + exit: return res; error: @@ -215,9 +229,10 @@ scam_create_perspective res = RES_BAD_ARG; goto error; } - res = camera_create(logger, allocator, verbose, SCAM_PERSPECTIVE, &cam); if(res != RES_OK) goto error; + res = check_perspective_args(cam, args); + if(res != RES_OK) goto error; res = setup_perspective(cam, args); if(res != RES_OK) goto error; @@ -233,6 +248,16 @@ error: } res_T +scam_perspective_get_solid_angle(const struct scam* camera, double* solid_angle) +{ + if(!camera || camera->type != SCAM_PERSPECTIVE || !solid_angle) + return RES_BAD_ARG; + + *solid_angle = camera->param.persp.solid_angle; + return RES_OK; +} + +res_T scam_focal_length_to_field_of_view (const double lens_radius, const double focal_length, diff --git a/src/test_scam_orthographic.c b/src/test_scam_orthographic.c @@ -40,6 +40,7 @@ main(int argc, char** argv) double axis_x[3]; double axis_y[3]; double axis_z[3]; + double solid_angle; size_t i; enum scam_type type = SCAM_NONE; (void)argc, (void)argv; @@ -92,6 +93,7 @@ main(int argc, char** argv) args.aspect_ratio = 16.0/9.0; CHK(scam_create_orthographic(NULL, NULL, 1, &args, &cam) == RES_OK); + CHK(scam_perspective_get_solid_angle(cam, &solid_angle) == RES_BAD_ARG); /* Precompute camera parameters */ d3_normalize(axis_z, d3_sub(axis_z, args.target, args.position)); diff --git a/src/test_scam_perspective_pinhole.c b/src/test_scam_perspective_pinhole.c @@ -48,6 +48,8 @@ main(int argc, char** argv) double sin_hori_hfov; /* Sinus of the horizontal half field of view */ double sin_vert_hfov; /* Sinos of the vertical half field of view */ double img_depth; + double solid_angle; + double ref; size_t i = 0; enum scam_type type = SCAM_NONE; (void)argc, (void)argv; @@ -112,9 +114,23 @@ main(int argc, char** argv) args.up[1] = rand_canonical(); args.up[2] = rand_canonical(); args.field_of_view = PI/2.0; - args.aspect_ratio = 4.0/3.0; + args.aspect_ratio = 1.0; CHK(scam_create_perspective(NULL, NULL, 1, &args, &cam) == RES_OK); + CHK(scam_perspective_get_solid_angle(NULL, &solid_angle) == RES_BAD_ARG); + CHK(scam_perspective_get_solid_angle(cam, NULL) == RES_BAD_ARG); + CHK(scam_perspective_get_solid_angle(cam, &solid_angle) == RES_OK); + + ref = args.field_of_view * 2*sin(args.field_of_view/2); + CHK(eq_eps(solid_angle, ref, 1.e-6)); + CHK(scam_ref_put(cam) == RES_OK); + + args.aspect_ratio = 4.0/3.0; + CHK(scam_create_perspective(NULL, NULL, 1, &args, &cam) == RES_OK); + + CHK(scam_perspective_get_solid_angle(cam, &solid_angle) == RES_OK); + ref = 2.6227869472431911; + CHK(eq_eps(solid_angle, ref, 1.e-6)); /* Precompute some view frustum constants */ d3_normalize(axis_z, d3_sub(axis_z, args.target, args.position));