solstice-solver

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

ssol_camera.c (3925B)


      1 /* Copyright (C) 2018-2026 |Meso|Star> (contact@meso-star.com)
      2  * Copyright (C) 2016, 2018 CNRS
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     16 
     17 #include "ssol.h"
     18 #include "ssol_camera.h"
     19 #include "ssol_device_c.h"
     20 
     21 #include <rsys/mem_allocator.h>
     22 
     23 /*******************************************************************************
     24  * Helper functions
     25  ******************************************************************************/
     26 static void
     27 camera_release(ref_T* ref)
     28 {
     29   struct ssol_camera* cam = CONTAINER_OF(ref, struct ssol_camera, ref);
     30   struct ssol_device* dev;
     31   ASSERT(ref);
     32   dev = cam->dev;
     33   MEM_RM(dev->allocator, cam);
     34   SSOL(device_ref_put(dev));
     35 }
     36 
     37 /*******************************************************************************
     38  * Exported functions
     39  ******************************************************************************/
     40 res_T
     41 ssol_camera_create(struct ssol_device* dev, struct ssol_camera** out_cam)
     42 {
     43   const double pos[3] = {0, 0, 0};
     44   const double tgt[3] = {0, 0,-1};
     45   const double up[3] = {0, 1, 0};
     46   struct ssol_camera* cam = NULL;
     47   res_T res = RES_OK;
     48 
     49   if(!dev || !out_cam)  {
     50     res = RES_BAD_ARG;
     51     goto error;
     52   }
     53 
     54   cam = MEM_CALLOC(dev->allocator, 1, sizeof(struct ssol_camera));
     55   if(!cam) {
     56     res = RES_MEM_ERR;
     57     goto error;
     58   }
     59   SSOL(device_ref_get(dev));
     60   cam->dev = dev;
     61   ref_init(&cam->ref);
     62   cam->rcp_proj_ratio = 1.f;
     63   cam->fov_x = (float)(PI/2.0);
     64   SSOL(camera_look_at(cam, pos, tgt, up));
     65 
     66 exit:
     67   if(out_cam) *out_cam = cam;
     68   return res;
     69 error:
     70   if(cam) {
     71     SSOL(camera_ref_put(cam));
     72     cam = NULL;
     73   }
     74   goto exit;
     75 }
     76 
     77 res_T
     78 ssol_camera_ref_get(struct ssol_camera* cam)
     79 {
     80   if(!cam) return RES_BAD_ARG;
     81   ref_get(&cam->ref);
     82   return RES_OK;
     83 }
     84 
     85 res_T
     86 ssol_camera_ref_put(struct ssol_camera* cam)
     87 {
     88   if(!cam) return RES_BAD_ARG;
     89   ref_put(&cam->ref, camera_release);
     90   return RES_OK;
     91 }
     92 
     93 res_T
     94 ssol_camera_set_proj_ratio(struct ssol_camera* cam, const double ratio)
     95 {
     96   float y[3] = {0};
     97   if(!cam || ratio <= 0) return RES_BAD_ARG;
     98   if(f3_normalize(y, cam->axis_y) <= 0) return RES_BAD_ARG;
     99   cam->rcp_proj_ratio = (float)(1.0 / ratio);
    100   f3_mulf(cam->axis_y, y, cam->rcp_proj_ratio);
    101   return RES_OK;
    102 }
    103 
    104 res_T
    105 ssol_camera_set_fov(struct ssol_camera* cam, const double fov_x)
    106 {
    107   float z[3] = {0};
    108   float img_plane_depth;
    109   if(!cam || (float)fov_x <= 0) return RES_BAD_ARG;
    110   if(f3_normalize(z, cam->axis_z) <= 0) return RES_BAD_ARG;
    111   img_plane_depth = (float)(1.0/tan(fov_x*0.5));
    112   f3_mulf(cam->axis_z, z, img_plane_depth);
    113   cam->fov_x = (float)fov_x;
    114   return RES_OK;
    115 }
    116 
    117 res_T
    118 ssol_camera_look_at
    119   (struct ssol_camera* cam,
    120    const double pos[3],
    121    const double tgt[3],
    122    const double up[3])
    123 {
    124   float posf[3], tgtf[3], upf[3];
    125   float x[3], y[3], z[3];
    126   float img_plane_depth;
    127   if(!cam || !pos || !tgt || !up) return RES_BAD_ARG;
    128 
    129   f3_set_d3(posf, pos);
    130   f3_set_d3(tgtf, tgt);
    131   f3_set_d3(upf, up);
    132 
    133   if(f3_normalize(z, f3_sub(z, tgtf, posf)) <= 0) return RES_BAD_ARG;
    134   if(f3_normalize(x, f3_cross(x, z, upf)) <= 0) return RES_BAD_ARG;
    135   if(f3_normalize(y, f3_cross(y, z, x)) <= 0) return RES_BAD_ARG;
    136   img_plane_depth = (float)(1.0/tan(cam->fov_x*0.5));
    137 
    138   f3_set(cam->axis_x, x);
    139   f3_mulf(cam->axis_y, y, cam->rcp_proj_ratio);
    140   f3_mulf(cam->axis_z, z, img_plane_depth);
    141   f3_set(cam->position, posf);
    142   return RES_OK;
    143 }
    144