scam.c (4204B)
1 /* Copyright (C) 2021-2023 |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 "scam_c.h" 17 #include "scam_log.h" 18 19 #include <rsys/logger.h> 20 #include <rsys/mem_allocator.h> 21 22 /******************************************************************************* 23 * Helper functions 24 ******************************************************************************/ 25 static INLINE int 26 check_sample 27 (const struct scam* cam, 28 const struct scam_sample* sample) 29 { 30 ASSERT(cam); 31 if(!sample) return 0; 32 33 if(sample->film[0] < 0 || sample->film[0] >= 1 34 || sample->film[1] < 0 || sample->film[1] >= 1) { 35 log_err(cam, 36 "Invalid camera film sample (%g, %g). It must be in [0, 1[^2.\n", 37 SPLIT2(sample->film)); 38 return 0; 39 } 40 41 if(sample->lens[0] < 0 || sample->lens[0] >= 1 42 || sample->lens[1] < 0 || sample->lens[1] >= 1) { 43 log_err(cam, 44 "Invalid camera lens sample (%g, %g). It must be in [0, 1[^2.\n", 45 SPLIT2(sample->lens)); 46 return 0; 47 } 48 return 1; 49 } 50 51 static void 52 release_scam(ref_T* ref) 53 { 54 struct scam* cam = CONTAINER_OF(ref, struct scam, ref); 55 ASSERT(ref); 56 if(cam->logger == &cam->logger__) logger_release(&cam->logger__); 57 MEM_RM(cam->allocator, cam); 58 } 59 60 /******************************************************************************* 61 * Exported functions 62 ******************************************************************************/ 63 res_T 64 scam_generate_ray 65 (const struct scam* cam, 66 const struct scam_sample* sample, 67 struct scam_ray* ray) 68 { 69 res_T res = RES_OK; 70 71 if(!cam || !ray || !check_sample(cam, sample)) { 72 res = RES_BAD_ARG; 73 goto error; 74 } 75 76 switch(cam->type) { 77 case SCAM_ORTHOGRAPHIC: 78 orthographic_generate_ray(cam, sample, ray); 79 break; 80 case SCAM_PERSPECTIVE: 81 perspective_generate_ray(cam, sample, ray); 82 break; 83 default: FATAL("Unreachable code.\n"); break; 84 } 85 86 exit: 87 return res; 88 error: 89 goto exit; 90 } 91 92 res_T 93 scam_get_type(const struct scam* cam, enum scam_type* type) 94 { 95 if(!cam || !type) return RES_BAD_ARG; 96 *type = cam->type; 97 return RES_OK; 98 } 99 100 res_T 101 scam_ref_get(struct scam* cam) 102 { 103 if(!cam) return RES_BAD_ARG; 104 ref_get(&cam->ref); 105 return RES_OK; 106 } 107 108 res_T 109 scam_ref_put(struct scam* cam) 110 { 111 if(!cam) return RES_BAD_ARG; 112 ref_put(&cam->ref, release_scam); 113 return RES_OK; 114 } 115 116 /******************************************************************************* 117 * Local functions 118 ******************************************************************************/ 119 res_T 120 camera_create 121 (struct logger* logger, 122 struct mem_allocator* mem_allocator, 123 const int verbose, /* Verbosity level */ 124 const enum scam_type type, 125 struct scam** out_cam) 126 { 127 struct scam* cam = NULL; 128 struct mem_allocator* allocator = NULL; 129 res_T res = RES_OK; 130 ASSERT(out_cam && (unsigned)type < SCAM_TYPES_COUNT__); 131 132 allocator = mem_allocator ? mem_allocator : &mem_default_allocator; 133 cam = MEM_CALLOC(allocator, 1, sizeof(*cam)); 134 if(!cam) { 135 if(verbose) { 136 #define ERR_STR "Could not allocate the Star-Camera.\n" 137 if(logger) { 138 logger_print(logger, LOG_ERROR, ERR_STR); 139 } else { 140 fprintf(stderr, MSG_ERROR_PREFIX ERR_STR); 141 } 142 #undef ERR_STR 143 } 144 res = RES_MEM_ERR; 145 goto error; 146 } 147 ref_init(&cam->ref); 148 cam->allocator = allocator; 149 cam->type = type; 150 cam->verbose = verbose; 151 152 if(logger) { 153 cam->logger = logger; 154 } else { 155 setup_log_default(cam); 156 } 157 158 exit: 159 if(out_cam) *out_cam = cam; 160 return res; 161 error: 162 if(cam) { 163 SCAM(ref_put(cam)); 164 cam = NULL; 165 } 166 goto exit; 167 } 168