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