test_s3d_sphere_instance.c (6347B)
1 /* Copyright (C) 2015-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 "s3d.h" 17 #include "test_s3d_camera.h" 18 #include "test_s3d_utils.h" 19 20 #include <rsys/image.h> 21 #include <rsys/float2.h> 22 #include <rsys/float3.h> 23 24 #include <string.h> 25 26 static int 27 filter_front_face 28 (const struct s3d_hit* hit, 29 const float pos[3], 30 const float dir[3], 31 const float range[2], 32 void* ray_data, 33 void* filter_data) 34 { 35 CHK(hit != NULL); 36 CHK(pos != NULL); 37 CHK(dir != NULL); 38 CHK(range != NULL); 39 CHK(range[0] < range[1]); 40 CHK(filter_data == NULL); 41 CHK(ray_data == NULL); 42 CHK(S3D_HIT_NONE(hit) == 0); 43 return f3_dot(hit->normal, dir) < 0; 44 } 45 46 static void 47 test_sampling 48 (struct s3d_scene_view* view, 49 const unsigned geom_id, 50 const unsigned inst0_id) 51 { 52 struct s3d_attrib attr0; 53 struct s3d_attrib attr1; 54 struct s3d_primitive prim; 55 int N = 10000; 56 int i; 57 float center[3]; 58 float sum; 59 float st[2]; 60 float E, V, SE; 61 62 /* Check that 50 percents of samples lie onto the 1st instance */ 63 sum = 0; 64 FOR_EACH(i, 0, N) { 65 const float u = rand_canonic(); 66 const float v = rand_canonic(); 67 const float w = rand_canonic(); 68 69 CHK(s3d_scene_view_sample(view, u, v, w, &prim, st) == RES_OK); 70 CHK(prim.geom_id == geom_id); 71 if(prim.inst_id == inst0_id) { 72 sum += 1; 73 } 74 75 CHK(s3d_primitive_get_attrib(&prim, S3D_POSITION, st, &attr0) == RES_OK); 76 CHK(s3d_primitive_get_attrib 77 (&prim, S3D_GEOMETRY_NORMAL, st, &attr1) == RES_OK); 78 79 if(prim.inst_id == inst0_id) { 80 f3_sub(attr0.value, attr0.value, f3(center,-1.5, 0, 0)); 81 } else { 82 f3_sub(attr0.value, attr0.value, f3(center, 1.5, 0, 0)); 83 } 84 f3_mulf(attr1.value, attr1.value, 2.f); 85 CHK(f3_eq_eps(attr0.value, attr1.value, 1.e-3f)); 86 } 87 E = sum / (float)N; 88 V = sum / (float)N - E*E; 89 SE = (float)sqrt(V/(float)N); 90 CHK(eq_epsf(E, 0.5, 2*SE)); 91 } 92 93 static void 94 test_ray_tracing(struct s3d_scene_view* view) 95 { 96 struct image img; 97 struct camera cam; 98 const size_t img_sz[2] = {640, 480}; 99 float pos[3] = {0, 0, 0}; 100 float tgt[3] = {0, 0, 0}; 101 float up[3] = {0, 1, 0}; 102 float proj_ratio; 103 size_t x, y; 104 105 image_init(NULL, &img); 106 CHK(image_setup 107 (&img, img_sz[0], img_sz[1], img_sz[0]*3, IMAGE_RGB8, NULL) == RES_OK); 108 109 f3(pos, 0, 0, -10); 110 f3(tgt, 0, 0, 0); 111 f3(up, 0, 1, 0); 112 proj_ratio = (float)img_sz[0] / (float)img_sz[1]; 113 camera_init(&cam, pos, tgt, up, (float)PI*0.25f, proj_ratio); 114 115 FOR_EACH(y, 0, img_sz[1]) { 116 float pixel[2]; 117 pixel[1] = (float)y / (float)img_sz[1]; 118 FOR_EACH(x, 0, img_sz[0]) { 119 const size_t ipix = (y*img_sz[0] + x)*3/*RGB*/; 120 struct s3d_hit hit; 121 const float range[2] = {0, FLT_MAX}; 122 float org[3]; 123 float dir[3]; 124 125 pixel[0] = (float)x/(float)img_sz[0]; 126 camera_ray(&cam, pixel, org, dir); 127 CHK(s3d_scene_view_trace_ray(view, org, dir, range, NULL, &hit) == RES_OK); 128 if(S3D_HIT_NONE(&hit)) { 129 ((uint8_t*)img.pixels)[ipix+0] = 0; 130 ((uint8_t*)img.pixels)[ipix+1] = 0; 131 ((uint8_t*)img.pixels)[ipix+2] = 0; 132 } else { 133 float normal[3] = {0.f, 0.f, 0.f}; 134 f3_normalize(normal, hit.normal); 135 ((uint8_t*)img.pixels)[ipix+0] = (uint8_t)(fabs(normal[0])*255.f); 136 ((uint8_t*)img.pixels)[ipix+1] = (uint8_t)(fabs(normal[1])*255.f); 137 ((uint8_t*)img.pixels)[ipix+2] = (uint8_t)(fabs(normal[2])*255.f); 138 } 139 } 140 } 141 142 /* Write image */ 143 CHK(image_write_ppm_stream(&img, 0, stdout) == RES_OK); 144 image_release(&img); 145 } 146 147 int 148 main(int argc, char** argv) 149 { 150 struct mem_allocator allocator; 151 struct s3d_device* dev; 152 struct s3d_shape* sphere; 153 struct s3d_shape* sphere0; 154 struct s3d_shape* sphere1; 155 struct s3d_scene* scn; 156 struct s3d_scene_view* view; 157 unsigned geom_id; 158 unsigned inst0_id; 159 unsigned inst1_id; 160 float center[3]; 161 char filter = 0; 162 (void)argc, (void)argv; 163 164 if(argc > 1 && !strcmp(argv[1], "filter")) { 165 filter = 1; 166 } 167 168 CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); 169 CHK(s3d_device_create(NULL, &allocator, 0, &dev) == RES_OK); 170 CHK(s3d_scene_create(dev, &scn) == RES_OK); 171 172 CHK(s3d_shape_create_sphere(dev, &sphere) == RES_OK); 173 CHK(s3d_sphere_setup(sphere, f3_splat(center, 0), 2) == RES_OK); 174 CHK(s3d_shape_get_id(sphere, &geom_id) == RES_OK); 175 CHK(s3d_scene_attach_shape(scn, sphere) == RES_OK); 176 177 CHK(s3d_scene_instantiate(scn, &sphere0) == RES_OK); 178 CHK(s3d_scene_instantiate(scn, &sphere1) == RES_OK); 179 CHK(s3d_shape_get_id(sphere0, &inst0_id) == RES_OK); 180 CHK(s3d_shape_get_id(sphere0, &inst1_id) == RES_OK); 181 CHK(s3d_scene_ref_put(scn) == RES_OK); 182 183 CHK(s3d_scene_create(dev, &scn) == RES_OK); 184 CHK(s3d_scene_attach_shape(scn, sphere0) == RES_OK); 185 CHK(s3d_scene_attach_shape(scn, sphere1) == RES_OK); 186 CHK(s3d_instance_set_position(sphere0, f3(center,-1.5, 0, 0)) == RES_OK); 187 CHK(s3d_instance_set_position(sphere1, f3(center, 1.5, 0, 0)) == RES_OK); 188 189 if(filter) { 190 CHK(s3d_sphere_set_hit_filter_function 191 (NULL, filter_front_face, NULL) == RES_BAD_ARG); 192 CHK(s3d_sphere_set_hit_filter_function 193 (sphere, filter_front_face, NULL) == RES_OK); 194 } 195 196 CHK(s3d_scene_view_create 197 (scn, S3D_TRACE|S3D_GET_PRIMITIVE|S3D_SAMPLE, &view) == RES_OK); 198 199 test_sampling(view, geom_id, inst0_id); 200 test_ray_tracing(view); 201 202 CHK(s3d_device_ref_put(dev) == RES_OK); 203 CHK(s3d_scene_ref_put(scn) == RES_OK); 204 CHK(s3d_shape_ref_put(sphere) == RES_OK); 205 CHK(s3d_shape_ref_put(sphere0) == RES_OK); 206 CHK(s3d_shape_ref_put(sphere1) == RES_OK); 207 CHK(s3d_scene_view_ref_put(view) == RES_OK); 208 209 check_memory_allocator(&allocator); 210 mem_shutdown_proxy_allocator(&allocator); 211 CHK(mem_allocated_size() == 0); 212 return 0; 213 } 214