scam_orthographic.c (4555B)
1 /* Copyright (C) 2021-2023 |Méso|Star> (contact@meso-star.com) 2 * 3 * Tyhis 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/double3.h> 20 #include <rsys/double33.h> 21 #include <rsys/math.h> 22 23 #include <math.h> 24 25 /******************************************************************************* 26 * Helper functions 27 ******************************************************************************/ 28 static res_T 29 setup_orthographic(struct scam* cam, const struct scam_orthographic_args* args) 30 { 31 double x[3], y[3], z[3]; 32 res_T res = RES_OK; 33 ASSERT(cam && args && cam->type == SCAM_ORTHOGRAPHIC); 34 35 cam->param.ortho = ORTHOGRAPHIC_DEFAULT; 36 37 if(args->aspect_ratio <= 0) { 38 log_err(cam, 39 "orthographic camera: invalid aspect ratio: %g\n", 40 args->aspect_ratio); 41 res = RES_BAD_ARG; 42 goto error; 43 } 44 45 if(args->height <= 0) { 46 log_err(cam, 47 "orthographic camera: invalid height: %g\n", 48 args->height); 49 res = RES_BAD_ARG; 50 goto error; 51 } 52 53 if(d3_normalize(z, d3_sub(z, args->target, args->position)) <= 0 54 || d3_normalize(x, d3_cross(x, z, args->up)) <= 0 55 || d3_normalize(y, d3_cross(y, z, x)) <= 0) { 56 log_err(cam, 57 "orthographic camera: invalid point of view:\n" 58 " position = %g %g %g\n" 59 " target = %g %g %g\n" 60 " up = %g %g %g\n", 61 SPLIT3(args->position), SPLIT3(args->target), SPLIT3(args->up)); 62 res = RES_BAD_ARG; 63 goto error; 64 } 65 66 cam->param.ortho.height = args->height; 67 cam->param.ortho.aspect_ratio = args->aspect_ratio; 68 69 d3_set(cam->param.ortho.position, args->position); 70 71 d3_muld(cam->param.ortho.screen2world+0, x, 0.5*args->height*args->aspect_ratio); 72 d3_muld(cam->param.ortho.screen2world+3, y, 0.5*args->height); 73 d3_set (cam->param.ortho.screen2world+6, z); 74 75 d3_set(cam->param.ortho.camera2world+0, x); 76 d3_set(cam->param.ortho.camera2world+3, y); 77 d3_set(cam->param.ortho.camera2world+6, z); 78 79 exit: 80 return res; 81 error: 82 goto exit; 83 } 84 85 /******************************************************************************* 86 * Exported function 87 ******************************************************************************/ 88 SCAM_API res_T 89 scam_create_orthographic 90 (struct logger* logger, /* NULL <=> use builtin logger */ 91 struct mem_allocator* allocator, /* NULL <=> use default allocator */ 92 const int verbose, /* Verbosity level */ 93 struct scam_orthographic_args* args, 94 struct scam** out_cam) 95 { 96 struct scam* cam = NULL; 97 res_T res = RES_OK; 98 99 if(!args || !out_cam) { 100 res = RES_BAD_ARG; 101 goto error; 102 } 103 104 res = camera_create(logger, allocator, verbose, SCAM_ORTHOGRAPHIC, &cam); 105 if(res != RES_OK) goto error; 106 res = setup_orthographic(cam, args); 107 if(res != RES_OK) goto error; 108 109 exit: 110 if(out_cam) *out_cam = cam; 111 return res; 112 error: 113 if(cam) { 114 SCAM(ref_put(cam)); 115 cam = NULL; 116 } 117 goto exit; 118 } 119 120 /******************************************************************************* 121 * Local function 122 ******************************************************************************/ 123 void 124 orthographic_generate_ray 125 (const struct scam* cam, 126 const struct scam_sample* sample, 127 struct scam_ray* ray) 128 { 129 double x[3], y[3]; 130 double pos[3]; 131 132 ASSERT(cam && sample && ray); 133 ASSERT(cam->type == SCAM_ORTHOGRAPHIC); 134 ASSERT(0 <= sample->film[0] && sample->film[0] < 1); 135 ASSERT(0 <= sample->film[1] && sample->film[1] < 1); 136 137 /* Transform the sampled position in screen space */ 138 pos[0] = sample->film[0]*2-1; 139 pos[1] = sample->film[1]*2-1; 140 pos[2] = 0; 141 142 /* Transform the sampled position in world space */ 143 d3_muld(x, cam->param.ortho.screen2world+0, pos[0]); 144 d3_muld(y, cam->param.ortho.screen2world+3, pos[1]); 145 d3_add(ray->org, x, y); 146 d3_add(ray->org, ray->org, cam->param.ortho.position); 147 148 /* Setup the ray direction to the image plane normal, i.e. the z axis of the 149 * camera */ 150 d3_set(ray->dir, cam->param.ortho.camera2world+6); 151 }