solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

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:
Mcmake/CMakeLists.txt | 2++
Msrc/ssol.h | 35+++++++++++++++++++++++++++++++++++
Asrc/ssol_camera.c | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ssol_camera.h | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 */ +