commit 763c2106022fde02150fa48a138a73a2804caa91
parent 2207f6f56168967858f02990dbaa6f6a925c1381
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 13 Dec 2016 11:48:35 +0100
Add the ssol_camera API
Diffstat:
4 files changed, 239 insertions(+), 0 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -54,6 +54,7 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(SSOL_FILES_SRC
ssol_atmosphere.c
+ ssol_camera.c
ssol_device.c
ssol_estimator.c
ssol_image.c
@@ -75,6 +76,7 @@ set(SSOL_FILES_INC_API
set(SSOL_FILES_INC
ssol_atmosphere_c.h
ssol_c.h
+ ssol_camera.h
ssol_device_c.h
ssol_estimator_c.h
ssol_image_c.h
diff --git a/src/ssol.h b/src/ssol.h
@@ -47,6 +47,7 @@ struct ssp_rng;
/* Opaque Solstice solver types */
struct ssol_atmosphere;
+struct ssol_camera;
struct ssol_device;
struct ssol_image;
struct ssol_material;
@@ -285,6 +286,40 @@ ssol_device_ref_put
(struct ssol_device* dev);
/*******************************************************************************
+ * Camera API
+ ******************************************************************************/
+SSOL_API res_T
+ssol_camera_create
+ (struct ssol_device* de,
+ struct ssol_camera** cam);
+
+SSOL_API res_T
+ssol_camera_ref_get
+ (struct ssol_camera* cam);
+
+SSOL_API res_T
+ssol_camera_ref_put
+ (struct ssol_camera* cam);
+
+/* Width/height projection ratio */
+SSOL_API res_T
+ssol_camera_set_proj_ratio
+ (struct ssol_camera* cam,
+ const double proj_ratio);
+
+SSOL_API res_T
+ssol_camera_set_fov /* Horizontal field of view */
+ (struct ssol_camera* cam,
+ const double fov); /* In radian */
+
+SSOL_API res_T
+ssol_camera_look_at
+ (struct ssol_camera* cam,
+ const double position[3],
+ const double target[3],
+ const double up[3]);
+
+/*******************************************************************************
* Image API
******************************************************************************/
SSOL_API res_T
diff --git a/src/ssol_camera.c b/src/ssol_camera.c
@@ -0,0 +1,142 @@
+/* Copyright (C) CNRS 2016
+ *
+ * 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 "ssol.h"
+#include "ssol_camera.h"
+#include "ssol_device_c.h"
+
+#include <rsys/mem_allocator.h>
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static void
+camera_release(ref_T* ref)
+{
+ struct ssol_camera* cam = CONTAINER_OF(ref, struct ssol_camera, ref);
+ struct ssol_device* dev;
+ ASSERT(ref);
+ dev = cam->dev;
+ MEM_RM(dev->allocator, cam);
+ SSOL(device_ref_put(dev));
+}
+
+/*******************************************************************************
+ * Exported functions
+ ******************************************************************************/
+res_T
+ssol_camera_create(struct ssol_device* dev, struct ssol_camera** out_cam)
+{
+ const double pos[3] = {0, 0, 0};
+ const double tgt[3] = {0, 0,-1};
+ const double up[3] = {0, 1, 0};
+ struct ssol_camera* cam = NULL;
+ res_T res = RES_OK;
+
+ if(!dev || !out_cam) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ cam = MEM_CALLOC(dev->allocator, 1, sizeof(struct ssol_camera));
+ if(!cam) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ SSOL(device_ref_get(dev));
+ cam->dev = dev;
+ ref_init(&cam->ref);
+ cam->rcp_proj_ratio = 1.f;
+ cam->fov_x = (float)(PI/2.0);
+ SSOL(camera_look_at(cam, pos, tgt, up));
+
+exit:
+ if(out_cam) *out_cam = cam;
+ return res;
+error:
+ if(cam) {
+ SSOL(camera_ref_put(cam));
+ cam = NULL;
+ }
+ goto exit;
+}
+
+res_T
+ssol_camera_ref_get(struct ssol_camera* cam)
+{
+ if(!cam) return RES_BAD_ARG;
+ ref_get(&cam->ref);
+ return RES_OK;
+}
+
+res_T
+ssol_camera_ref_put(struct ssol_camera* cam)
+{
+ if(!cam) return RES_BAD_ARG;
+ ref_put(&cam->ref, camera_release);
+ return RES_OK;
+}
+
+res_T
+ssol_camera_set_proj_ratio(struct ssol_camera* cam, const double ratio)
+{
+ float y[3] = {0};
+ if(!cam || ratio <= 0) return RES_BAD_ARG;
+ if(f3_normalize(y, cam->axis_y) <= 0) return RES_BAD_ARG;
+ cam->rcp_proj_ratio = (float)(1.0 / ratio);
+ f3_mulf(cam->axis_y, y, cam->rcp_proj_ratio);
+ return RES_OK;
+}
+
+res_T
+ssol_camera_set_fov(struct ssol_camera* cam, const double fov_x)
+{
+ float z[3] = {0};
+ float img_plane_depth;
+ if(!cam || (float)fov_x <= 0) return RES_BAD_ARG;
+ if(f3_normalize(z, cam->axis_z) <= 0) return RES_BAD_ARG;
+ img_plane_depth = (float)(1.0/tan(fov_x*0.5));
+ f3_mulf(cam->axis_z, z, img_plane_depth);
+ cam->fov_x = (float)fov_x;
+ return RES_OK;
+}
+
+res_T
+ssol_camera_look_at
+ (struct ssol_camera* cam,
+ const double pos[3],
+ const double tgt[3],
+ const double up[3])
+{
+ float posf[3], tgtf[3], upf[3];
+ float x[3], y[3], z[3];
+ float img_plane_depth;
+ if(!cam || !pos || !tgt || !up) return RES_BAD_ARG;
+
+ f3_set_d3(posf, pos);
+ f3_set_d3(tgtf, tgt);
+ f3_set_d3(upf, up);
+
+ if(f3_normalize(z, f3_sub(z, tgtf, posf)) <= 0) return RES_BAD_ARG;
+ if(f3_normalize(x, f3_cross(x, z, upf)) <= 0) return RES_BAD_ARG;
+ if(f3_normalize(y, f3_cross(y, z, x)) <= 0) return RES_BAD_ARG;
+ img_plane_depth = (float)(1.0/tan(cam->fov_x*0.5));
+
+ f3_set(cam->axis_x, x);
+ f3_mulf(cam->axis_y, y, cam->rcp_proj_ratio);
+ f3_mulf(cam->axis_z, z, img_plane_depth);
+ return RES_OK;
+}
+
diff --git a/src/ssol_camera.h b/src/ssol_camera.h
@@ -0,0 +1,60 @@
+/* Copyright (C) CNRS 2016
+ *
+ * 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 SSOL_CAMERA_H
+#define SSOL_CAMERA_H
+
+#include <rsys/float3.h>
+#include <rsys/ref_count.h>
+
+struct ssol_device;
+
+struct ssol_camera {
+ /* Orthogonal basis of the camera */
+ float axis_x[3];
+ float axis_y[3];
+ float axis_z[3];
+
+ float position[3];
+ float fov_x; /* Field of view in radians */
+ float rcp_proj_ratio; /* height / width */
+
+ ref_T ref;
+ struct ssol_device* dev;
+};
+
+static FINLINE void
+camera_ray
+ (const struct ssol_camera* cam,
+ const double sample[2], /* In [0, 1[ */
+ float org[3],
+ float dir[3])
+{
+ float x[3], y[3], len;
+ (void)len; /* avoid warning in debug */
+ ASSERT(cam && sample && org && dir);
+ ASSERT(sample[0] >= 0 || sample[0] < 1.f);
+ ASSERT(sample[1] >= 0 || sample[1] < 1.f);
+
+ f3_mulf(x, cam->axis_x, (float)sample[0]*2.f - 1.f);
+ f3_mulf(y, cam->axis_y, (float)sample[1]*2.f - 1.f);
+ f3_add(dir, f3_add(dir, x, y), cam->axis_z);
+ len = f3_normalize(dir, dir);
+ ASSERT(len >= 1.e-6f);
+ f3_set(org, cam->position);
+}
+
+#endif /* SSOL_CAMERA_H */
+