test_scam_orthographic.c (4435B)
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.h" 17 #include "test_scam_utils.h" 18 19 #include <rsys/double3.h> 20 #include <rsys/double33.h> 21 #include <rsys/logger.h> 22 23 static void 24 log_stream(const char* msg, void* ctx) 25 { 26 ASSERT(msg); 27 (void)msg, (void)ctx; 28 printf("%s", msg); 29 } 30 31 int 32 main(int argc, char** argv) 33 { 34 struct logger logger; 35 struct scam_orthographic_args args = SCAM_ORTHOGRAPHIC_ARGS_DEFAULT; 36 struct scam* cam = NULL; 37 const size_t nsamps = 10000; 38 double screen2world[9]; 39 double world2screen[9]; 40 double axis_x[3]; 41 double axis_y[3]; 42 double axis_z[3]; 43 double solid_angle; 44 size_t i; 45 enum scam_type type = SCAM_NONE; 46 (void)argc, (void)argv; 47 48 CHK(scam_create_orthographic(NULL, NULL, 0, NULL, &cam) == RES_BAD_ARG); 49 CHK(scam_create_orthographic(NULL, NULL, 0, &args, NULL) == RES_BAD_ARG); 50 CHK(scam_create_orthographic(NULL, NULL, 0, &args, &cam) == RES_OK); 51 52 CHK(scam_get_type(cam, &type) == RES_OK); 53 CHK(type == SCAM_ORTHOGRAPHIC); 54 CHK(scam_ref_put(cam) == RES_OK); 55 56 CHK(logger_init(&mem_default_allocator, &logger) == RES_OK); 57 logger_set_stream(&logger, LOG_OUTPUT, log_stream, NULL); 58 logger_set_stream(&logger, LOG_ERROR, log_stream, NULL); 59 logger_set_stream(&logger, LOG_WARNING, log_stream, NULL); 60 61 CHK(scam_create_orthographic(&logger, NULL, 0, &args, &cam) == RES_OK); 62 CHK(scam_ref_put(cam) == RES_OK); 63 64 CHK(scam_create_orthographic(NULL, &mem_default_allocator, 0, &args, &cam) == RES_OK); 65 CHK(scam_ref_put(cam) == RES_OK); 66 67 d3_set(args.target, args.position); 68 CHK(scam_create_orthographic(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG); 69 70 d3(args.position, 0, 0, 0); 71 d3(args.target, 0, 1, 0); 72 d3(args.up, 0, 1, 0); 73 CHK(scam_create_orthographic(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG); 74 75 args = SCAM_ORTHOGRAPHIC_ARGS_DEFAULT; 76 args.aspect_ratio = 0; 77 CHK(scam_create_orthographic(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG); 78 79 args.aspect_ratio = 1; 80 args.height = 0; 81 CHK(scam_create_orthographic(NULL, NULL, 1, &args, &cam) == RES_BAD_ARG); 82 83 args.position[0] = rand_canonical(); 84 args.position[1] = rand_canonical(); 85 args.position[2] = rand_canonical(); 86 args.target[0] = rand_canonical(); 87 args.target[1] = rand_canonical(); 88 args.target[2] = rand_canonical(); 89 args.up[0] = rand_canonical(); 90 args.up[1] = rand_canonical(); 91 args.up[2] = rand_canonical(); 92 args.height = 10; 93 args.aspect_ratio = 16.0/9.0; 94 95 CHK(scam_create_orthographic(NULL, NULL, 1, &args, &cam) == RES_OK); 96 CHK(scam_perspective_get_solid_angle(cam, &solid_angle) == RES_BAD_ARG); 97 98 /* Precompute camera parameters */ 99 d3_normalize(axis_z, d3_sub(axis_z, args.target, args.position)); 100 d3_normalize(axis_x, d3_cross(axis_x, axis_z, args.up)); 101 d3_normalize(axis_y, d3_cross(axis_y, axis_z, axis_x)); 102 103 d3_muld(screen2world+0, axis_x, 0.5*args.height*args.aspect_ratio); 104 d3_muld(screen2world+3, axis_y, 0.5*args.height); 105 d3_set (screen2world+6, axis_z); 106 d33_inverse(world2screen, screen2world); 107 108 FOR_EACH(i, 0, nsamps) { 109 double pos[3]; 110 struct scam_sample sample = SCAM_SAMPLE_NULL; 111 struct scam_ray ray = SCAM_RAY_NULL; 112 113 sample.film[0] = rand_canonical(); 114 sample.film[1] = rand_canonical(); 115 CHK(scam_generate_ray(cam, &sample, &ray) == RES_OK); 116 117 /* Check the ray direction */ 118 CHK(d3_eq_eps(ray.dir, axis_z, 1.e-6)); 119 120 /* Transform the ray origin in camera space */ 121 d3_sub(pos, ray.org, args.position); 122 d33_muld3(pos, world2screen, pos); 123 124 /* Check that the ray origin lies on the image plane */ 125 CHK(-1 <= pos[0] && pos[0] <= 1); 126 CHK(-1 <= pos[1] && pos[1] <= 1); 127 CHK(eq_eps(pos[2], 0, 1.e-6)); 128 } 129 130 CHK(scam_ref_put(cam) == RES_OK); 131 132 logger_release(&logger); 133 CHK(mem_allocated_size() == 0); 134 return 0; 135 }