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