star-3d

Surface structuring for efficient 3D geometric queries
git clone git://git.meso-star.fr/star-3d.git
Log | Files | Refs | README | LICENSE

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