commit 5ab5050f67bab87e8955aa91a59b3fd7412b9d5c
parent 939fa0923226953c5fef27cceecec4ac2dd87cdc
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 23 Jul 2021 16:33:09 +0200
First (untested) implementation of the thin lens camera
Diffstat:
8 files changed, 317 insertions(+), 177 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -44,7 +44,7 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(SCAM_FILES_SRC
scam.c
scam_log.c
- scam_pinhole.c)
+ scam_perspective.c)
set(SCAM_FILES_INC
scam_c.h
scam_log.h)
diff --git a/src/scam.c b/src/scam.c
@@ -72,8 +72,8 @@ scam_generate_ray
}
switch(cam->type) {
- case SCAM_PINHOLE:
- pinhole_generate_ray(cam, sample, ray);
+ case SCAM_PERSPECTIVE:
+ perspective_generate_ray(cam, sample, ray);
break;
default: FATAL("Unreachable code.\n"); break;
}
diff --git a/src/scam.h b/src/scam.h
@@ -37,7 +37,7 @@
#endif
enum scam_type {
- SCAM_PINHOLE,
+ SCAM_PERSPECTIVE,
SCAM_TYPES_COUNT__,
SCAM_NONE = SCAM_TYPES_COUNT__
};
@@ -57,22 +57,32 @@ struct scam_ray {
#define SCAM_RAY_NULL__ {{0,0,0},{0,0,0}}
static const struct scam_ray SCAM_RAY_NULL = SCAM_RAY_NULL__;
-struct scam_pinhole_args {
- double position[3]; /* Focal point */
+struct scam_perspective_args {
+ double position[3]; /* Lens position */
double target[3]; /* Targeted point. target-position = image plane normal */
double up[3]; /* Vector defining the upward orientation */
double aspect_ratio; /* Image plane aspect ratio (width / height) */
- double field_of_view; /* Vertical field of view in radians */
+ double lens_radius; /* Radius of 0 <=> pinhole */
+
+ /* Vertical field of view in radians. Used when lens_radius == 0 */
+ double field_of_view;
+
+ /* Distance to focus on. Used when lens_radius != 0. Note that the focal
+ * distance is not the focal length that is the distance to the focal point
+ * behind the lens */
+ double focal_distance;
};
-#define SCAM_PINHOLE_ARGS_DEFAULT__ { \
+#define SCAM_PERSPECTIVE_ARGS_DEFAULT__ { \
{0,0,0}, /* Position */ \
{0,1,0}, /* Target */ \
{0,0,1}, /* Up */ \
1.0, /* Aspect ratio */ \
- 1.22173047639603070383, /* ~70 degrees */ \
+ 0.0, /* Lens radius */ \
+ 1.22173047639603070383, /* Fov ~70 degrees */ \
+ 1.0, /* Focal distance. Unused for radius == 0 */ \
}
-static const struct scam_pinhole_args SCAM_PINHOLE_ARGS_DEFAULT =
- SCAM_PINHOLE_ARGS_DEFAULT__;
+static const struct scam_perspective_args SCAM_PERSPECTIVE_ARGS_DEFAULT =
+ SCAM_PERSPECTIVE_ARGS_DEFAULT__;
/* Forward declaration of external data types */
struct logger;
@@ -87,11 +97,11 @@ struct scam;
BEGIN_DECLS
SCAM_API res_T
-scam_create_pinhole
+scam_create_perspective
(struct logger* logger, /* NULL <=> use builtin logger */
struct mem_allocator* allocator, /* NULL <=> use default allocator */
const int verbose, /* Verbosity level */
- struct scam_pinhole_args* args,
+ struct scam_perspective_args* args,
struct scam** camera);
SCAM_API res_T
diff --git a/src/scam_c.h b/src/scam_c.h
@@ -21,20 +21,32 @@
#include <rsys/logger.h>
#include <rsys/ref_count.h>
-struct pinhole {
- /* Orthogonal basis of the camera */
- double axis_x[3];
- double axis_y[3];
- double axis_z[3];
-
- /* Focal point */
- double position[3];
+struct perspective {
+ double screen2world[9];
+ double camera2world[9];
+
+ double position[3]; /* Lens position */
+
+ double rcp_tan_half_fov; /* 1 / tan(vertical_fov / 2) */
+ double aspect_ratio; /* width / height */
+ double lens_radius; /* 0 <=> pinhole camera */
+ double focal_distance; /* Unused when lens_radius == 0 */
};
+#define PERSPECTIVE_DEFAULT__ { \
+ {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 */ \
+ 1.0, /* 1/tan(vertical_fov/2) */ \
+ 1.0, /* Aspect ratio */ \
+ 0.0, /* Lens radius */ \
+ -1.0 /* Focal distance */ \
+}
+static const struct perspective PERSPECTIVE_DEFAULT = PERSPECTIVE_DEFAULT__;
struct scam {
enum scam_type type;
union {
- struct pinhole pinhole;
+ struct perspective persp;
} param;
int verbose;
@@ -54,9 +66,9 @@ camera_create
struct scam** scam);
extern LOCAL_SYM void
-pinhole_generate_ray
+perspective_generate_ray
(const struct scam* cam,
- const struct scam_sample* sample,
+ const struct scam_sample* sample,
struct scam_ray* ray);
#endif /* SCAM_C_H */
diff --git a/src/scam_perspective.c b/src/scam_perspective.c
@@ -0,0 +1,252 @@
+/* Copyright (C) 2021 |Meso|Star> (contact@meso-star.com)
+ *
+ * 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 "scam_c.h"
+#include "scam_log.h"
+
+#include <rsys/double3.h>
+#include <rsys/double33.h>
+#include <rsys/math.h>
+
+#include <math.h>
+
+/*******************************************************************************
+ * Helper function
+ ******************************************************************************/
+static res_T
+setup_perspective(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->aspect_ratio <= 0) {
+ log_err(cam,
+ "perspective camera: invalid aspect ratio: %g\n",
+ args->aspect_ratio);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(args->lens_radius < 0) {
+ log_err(cam,
+ "perspective camera: invalid negative lens radius: %g\n",
+ args->lens_radius);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!pinhole && args->focal_distance < 0) {
+ log_err(cam,
+ "perspective camera: invalid negative focal distance: %g\n",
+ args->focal_distance);
+ }
+
+ if(pinhole && (args->field_of_view <= 0 || args->field_of_view >= PI)) {
+ log_err(cam,
+ "perspective camera: invalid vertical field of view: %g\n",
+ args->field_of_view);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ 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) {
+ log_err(cam,
+ "perspective camera: invalid point of view:\n"
+ " position = %g %g %g\n"
+ " target = %g %g %g\n"
+ " up = %g %g %g\n",
+ SPLIT3(args->position), SPLIT3(args->target), SPLIT3(args->up));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ cam->param.persp.rcp_tan_half_fov = 1.0/tan(args->field_of_view*0.5);
+ cam->param.persp.aspect_ratio = args->aspect_ratio;
+ cam->param.persp.lens_radius = args->lens_radius;
+ cam->param.persp.focal_distance = args->focal_distance;
+
+ d3_set(cam->param.persp.position, args->position);
+
+ d3_muld(cam->param.persp.screen2world+0, x, args->aspect_ratio);
+ d3_set (cam->param.persp.screen2world+3, y);
+ d3_muld(cam->param.persp.screen2world+6, z, cam->param.persp.rcp_tan_half_fov);
+
+ d3_set(cam->param.persp.camera2world+0, x);
+ d3_set(cam->param.persp.camera2world+3, y);
+ d3_set(cam->param.persp.camera2world+6, z);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static INLINE void
+pinhole_generate_ray
+ (const struct scam* cam,
+ const struct scam_sample* sample,
+ struct scam_ray* ray)
+{
+ double x[3], y[3], z[3], len;
+ double pos[3];
+ (void)len;
+
+ ASSERT(cam && sample && ray);
+ ASSERT(cam->param.persp.lens_radius == 0);
+ ASSERT(cam->type == SCAM_PERSPECTIVE);
+ ASSERT(0 <= sample->film[0] && sample->film[0] < 1);
+ ASSERT(0 <= sample->film[1] && sample->film[1] < 1);
+
+ /* Transform the sampled position in screen space */
+ pos[0] = sample->film[0]*2-1;
+ pos[1] = sample->film[1]*2-1;
+ pos[2] = 1;
+
+ /* Transform the sampled position in world space. Note that no translation is
+ * performed to directly obtain the (un-normalized) ray direction. */
+ d3_muld(x, cam->param.persp.screen2world+0, pos[0]);
+ d3_muld(y, cam->param.persp.screen2world+3, pos[1]);
+ d3_set (z, cam->param.persp.screen2world+6);
+ d3_add(ray->dir, x, y);
+ d3_add(ray->dir, ray->dir, z);
+ len = d3_normalize(ray->dir, ray->dir);
+ ASSERT(len >= 1.e-6);
+
+ /* Setup the ray origin */
+ d3_set(ray->org, cam->param.persp.position);
+}
+
+static INLINE void
+thin_lens_generate_ray
+ (const struct scam* cam,
+ const struct scam_sample* sample,
+ struct scam_ray* ray)
+{
+ double focus_pt[3];
+ double dir[3];
+ double theta;
+ double len;
+ double t;
+ double r;
+ (void)len;
+
+ ASSERT(cam && sample && ray);
+ ASSERT(cam->param.persp.lens_radius > 0);
+ ASSERT(cam->type == SCAM_PERSPECTIVE);
+ ASSERT(0 <= sample->film[0] && sample->film[0] < 1);
+ ASSERT(0 <= sample->film[1] && sample->film[1] < 1);
+ ASSERT(0 <= sample->lens[0] && sample->lens[0] < 1);
+ ASSERT(0 <= sample->lens[1] && sample->lens[1] < 1);
+
+ /* Transform the sampled position in screen space and use it as the
+ * (un-normalized) direction starting from the lens center and intersecting
+ * the sample */
+ dir[0] = sample->film[0]*2-1;
+ dir[1] = sample->film[1]*2-1;
+ dir[2] = 1;
+
+ /* Transform the computed direction in camera space */
+ dir[0] = dir[0] * cam->param.persp.aspect_ratio;
+ dir[1] = dir[1];
+ dir[2] = dir[2] * cam->param.persp.rcp_tan_half_fov;
+ len = d3_normalize(dir, dir);
+ ASSERT(len >= 1.e-6);
+
+ /* find the focus point by intersecting dir with the focus plane */
+ t = cam->param.persp.focal_distance / dir[2];
+ focus_pt[0] = /*0 +*/ t*dir[0];
+ focus_pt[1] = /*0 +*/ t*dir[1];
+ focus_pt[2] = /*0 +*/ t*dir[2];
+
+ /* Uniformly sample a position onto the lens in camera space */
+ theta = 2 * PI * sample->lens[0];
+ r = cam->param.persp.lens_radius * sqrt(sample->lens[1]);
+ ray->org[0] = r * cos(theta);
+ ray->org[1] = r * sin(theta);
+ ray->org[2] = 0;
+
+ /* Compute the ray direction in camera space */
+ d3_sub(ray->dir, focus_pt, ray->org);
+ len = d3_normalize(ray->dir, ray->dir);
+ ASSERT(len >= 1.e-6);
+
+ /* Transform the ray from camera space to world space */
+ d33_muld3(ray->dir, cam->param.persp.camera2world, ray->dir);
+ d33_muld3(ray->org, cam->param.persp.camera2world, ray->org);
+ d3_add(ray->org, cam->param.persp.position, ray->org);
+}
+
+/*******************************************************************************
+ * Exported function
+ ******************************************************************************/
+SCAM_API res_T
+scam_create_perspective
+ (struct logger* logger, /* NULL <=> use builtin logger */
+ struct mem_allocator* allocator, /* NULL <=> use default allocator */
+ const int verbose, /* Verbosity level */
+ struct scam_perspective_args* args,
+ struct scam** out_cam)
+{
+ struct scam* cam = NULL;
+ res_T res = RES_OK;
+
+ if(!args || !out_cam) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = camera_create(logger, allocator, verbose, SCAM_PERSPECTIVE, &cam);
+ if(res != RES_OK) goto error;
+ res = setup_perspective(cam, args);
+ if(res != RES_OK) goto error;
+
+ exit:
+ if(out_cam) *out_cam = cam;
+ return res;
+error:
+ if(cam) {
+ SCAM(ref_put(cam));
+ cam = NULL;
+ }
+ goto exit;
+}
+
+/*******************************************************************************
+ * Local function
+ ******************************************************************************/
+void
+perspective_generate_ray
+ (const struct scam* cam,
+ const struct scam_sample* sample,
+ struct scam_ray* ray)
+{
+ ASSERT(cam && sample && ray);
+ ASSERT(cam->type == SCAM_PERSPECTIVE);
+ ASSERT(0 <= sample->film[0] && sample->film[0] < 1);
+ ASSERT(0 <= sample->film[1] && sample->film[1] < 1);
+
+ if(cam->param.persp.lens_radius == 0) {
+ pinhole_generate_ray(cam, sample, ray);
+ } else {
+ thin_lens_generate_ray(cam, sample, ray);
+ }
+}
diff --git a/src/scam_pinhole.c b/src/scam_pinhole.c
@@ -1,134 +0,0 @@
-/* Copyright (C) 2021 |Meso|Star> (contact@meso-star.com)
- *
- * 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 "scam_c.h"
-#include "scam_log.h"
-
-#include <rsys/double3.h>
-#include <rsys/math.h>
-
-#include <math.h>
-
-/*******************************************************************************
- * Helper function
- ******************************************************************************/
-static res_T
-setup_pinhole(struct scam* cam, const struct scam_pinhole_args* args)
-{
- double x[3], y[3], z[3];
- double img_plane_depth;
- res_T res = RES_OK;
- ASSERT(cam && args && cam->type == SCAM_PINHOLE);
-
- if(args->field_of_view <= 0 || args->field_of_view >= PI) {
- log_err(cam,
- "pinhole camera: invalid vertical field of view: %g\n",
- args->field_of_view);
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(args->aspect_ratio <= 0) {
- log_err(cam,
- "pinhole camera: invalid aspect ratio: %g\n",
- args->aspect_ratio);
- res = RES_BAD_ARG;
- goto error;
- }
-
- 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) {
- log_err(cam,
- "pinhole camera: invalid point of view:\n"
- " position = %g %g %g\n"
- " target = %g %g %g\n"
- " up = %g %g %g\n",
- SPLIT3(args->position), SPLIT3(args->target), SPLIT3(args->up));
- res = RES_BAD_ARG;
- goto error;
- }
-
- img_plane_depth = 1.0/tan(args->field_of_view*0.5);
- d3_muld(cam->param.pinhole.axis_x, x, args->aspect_ratio);
- d3_set(cam->param.pinhole.axis_y, y);
- d3_muld(cam->param.pinhole.axis_z, z, img_plane_depth);
- d3_set(cam->param.pinhole.position, args->position);
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-/*******************************************************************************
- * Exported function
- ******************************************************************************/
-SCAM_API res_T
-scam_create_pinhole
- (struct logger* logger, /* NULL <=> use builtin logger */
- struct mem_allocator* allocator, /* NULL <=> use default allocator */
- const int verbose, /* Verbosity level */
- struct scam_pinhole_args* args,
- struct scam** out_cam)
-{
- struct scam* cam = NULL;
- res_T res = RES_OK;
-
- if(!args || !out_cam) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- res = camera_create(logger, allocator, verbose, SCAM_PINHOLE, &cam);
- if(res != RES_OK) goto error;
- res = setup_pinhole(cam, args);
- if(res != RES_OK) goto error;
-
- exit:
- if(out_cam) *out_cam = cam;
- return res;
-error:
- if(cam) {
- SCAM(ref_put(cam));
- cam = NULL;
- }
- goto exit;
-}
-
-/*******************************************************************************
- * Local function
- ******************************************************************************/
-void
-pinhole_generate_ray
- (const struct scam* cam,
- const struct scam_sample* sample,
- struct scam_ray* ray)
-{
- double x[3], y[3], len;
- (void)len;
-
- ASSERT(cam && sample && ray);
- ASSERT(cam->type == SCAM_PINHOLE);
- ASSERT(0 <= sample->film[0] && sample->film[0] < 1);
- ASSERT(0 <= sample->film[1] && sample->film[1] < 1);
-
- d3_muld(x, cam->param.pinhole.axis_x, sample->film[0]*2-1);
- d3_muld(y, cam->param.pinhole.axis_y, sample->film[1]*2-1);
- d3_add(ray->dir, d3_add(ray->dir, x, y), cam->param.pinhole.axis_z);
- len = d3_normalize(ray->dir, ray->dir);
- ASSERT(len >= 1.e-6);
- d3_set(ray->org, cam->param.pinhole.position);
-}
diff --git a/src/test_scam_cbox.c b/src/test_scam_cbox.c
@@ -127,7 +127,7 @@ draw
int
main(int argc, char** argv)
{
- struct scam_pinhole_args args = SCAM_PINHOLE_ARGS_DEFAULT;
+ struct scam_perspective_args args = SCAM_PERSPECTIVE_ARGS_DEFAULT;
struct s3d_scene_view* view = NULL;
struct scam* cam = NULL;
struct image img;
@@ -140,7 +140,7 @@ main(int argc, char** argv)
d3(args.up, 0, 0, 1);
args.aspect_ratio = (double)IMG_WIDTH/(double)IMG_HEIGHT;
args.field_of_view = PI*0.25;
- CHK(scam_create_pinhole(NULL, NULL, 1, &args, &cam) == RES_OK);
+ CHK(scam_create_perspective(NULL, NULL, 1, &args, &cam) == RES_OK);
image_init(NULL, &img);
CHK(image_setup
diff --git a/src/test_scam_pinhole.c b/src/test_scam_pinhole.c
@@ -36,7 +36,7 @@ int
main(int argc, char** argv)
{
struct logger logger;
- struct scam_pinhole_args args = SCAM_PINHOLE_ARGS_DEFAULT;
+ struct scam_perspective_args args = SCAM_PERSPECTIVE_ARGS_DEFAULT;
struct scam_sample sample = SCAM_SAMPLE_NULL;
struct scam_ray ray = SCAM_RAY_NULL;
struct scam* cam = NULL;
@@ -52,14 +52,14 @@ main(int argc, char** argv)
enum scam_type type = SCAM_NONE;
(void)argc, (void)argv;
- CHK(scam_create_pinhole(NULL, NULL, 0, NULL, &cam) == RES_BAD_ARG);
- CHK(scam_create_pinhole(NULL, NULL, 0, &args, NULL) == RES_BAD_ARG);
- CHK(scam_create_pinhole(NULL, NULL, 0, &args, &cam) == RES_OK);
+ CHK(scam_create_perspective(NULL, NULL, 0, NULL, &cam) == RES_BAD_ARG);
+ CHK(scam_create_perspective(NULL, NULL, 0, &args, NULL) == RES_BAD_ARG);
+ CHK(scam_create_perspective(NULL, NULL, 0, &args, &cam) == RES_OK);
CHK(scam_get_type(NULL, &type) == RES_BAD_ARG);
CHK(scam_get_type(cam, NULL) == RES_BAD_ARG);
CHK(scam_get_type(cam, &type) == RES_OK);
- CHK(type == SCAM_PINHOLE);
+ CHK(type == SCAM_PERSPECTIVE);
CHK(scam_ref_get(NULL) == RES_BAD_ARG);
CHK(scam_ref_get(cam) == RES_OK);
@@ -72,34 +72,34 @@ main(int argc, char** argv)
logger_set_stream(&logger, LOG_ERROR, log_stream, NULL);
logger_set_stream(&logger, LOG_WARNING, log_stream, NULL);
- CHK(scam_create_pinhole(&logger, NULL, 0, &args, &cam) == RES_OK);
+ CHK(scam_create_perspective(&logger, NULL, 0, &args, &cam) == RES_OK);
CHK(scam_ref_put(cam) == RES_OK);
- CHK(scam_create_pinhole(NULL, &mem_default_allocator, 0, &args, &cam) == RES_OK);
+ CHK(scam_create_perspective(NULL, &mem_default_allocator, 0, &args, &cam) == RES_OK);
CHK(scam_ref_put(cam) == RES_OK);
d3_set(args.target, args.position);
- CHK(scam_create_pinhole(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG);
+ CHK(scam_create_perspective(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG);
d3(args.position, 0, 0, 0);
d3(args.target, 0, 1, 0);
d3(args.up, 0, 1, 0);
- CHK(scam_create_pinhole(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG);
+ CHK(scam_create_perspective(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG);
- args = SCAM_PINHOLE_ARGS_DEFAULT;
+ args = SCAM_PERSPECTIVE_ARGS_DEFAULT;
args.aspect_ratio = 0;
- CHK(scam_create_pinhole(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG);
+ CHK(scam_create_perspective(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG);
- args = SCAM_PINHOLE_ARGS_DEFAULT;
+ args = SCAM_PERSPECTIVE_ARGS_DEFAULT;
args.field_of_view = 0;
- CHK(scam_create_pinhole(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG);
+ CHK(scam_create_perspective(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG);
args.field_of_view = PI;
- CHK(scam_create_pinhole(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG);
+ CHK(scam_create_perspective(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG);
args.field_of_view = nextafter(0, PI);
- CHK(scam_create_pinhole(NULL, NULL, 1, &args, &cam) == RES_OK);
+ CHK(scam_create_perspective(NULL, NULL, 1, &args, &cam) == RES_OK);
CHK(scam_ref_put(cam) == RES_OK);
args.field_of_view = nextafter(PI, 0);
- CHK(scam_create_pinhole(NULL, NULL, 1, &args, &cam) == RES_OK);
+ CHK(scam_create_perspective(NULL, NULL, 1, &args, &cam) == RES_OK);
CHK(scam_ref_put(cam) == RES_OK);
args.position[0] = rand_canonical();
@@ -114,7 +114,7 @@ main(int argc, char** argv)
args.field_of_view = PI/2.0;
args.aspect_ratio = 4.0/3.0;
- CHK(scam_create_pinhole(NULL, NULL, 1, &args, &cam) == RES_OK);
+ CHK(scam_create_perspective(NULL, NULL, 1, &args, &cam) == RES_OK);
/* Precompute some view frustum constants */
d3_normalize(axis_z, d3_sub(axis_z, args.target, args.position));