star-3d

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

test_s3d_scene.c (13231B)


      1 /* Copyright (C) 2015-2023, 2026 |Méso|Star> (contact@meso-star.com)
      2  *
      3  * This file is part of Star-3D.
      4  *
      5  * Star-3D is free software: you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation, either version 3 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * Star-3D is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with Star-3D. If not, see <http://www.gnu.org/licenses/>. */
     17 
     18 #include "s3d.h"
     19 #include "test_s3d_utils.h"
     20 #include "test_s3d_cbox.h"
     21 
     22 #include <rsys/math.h>
     23 
     24 static const float cube_verts[] = {
     25   5.f, 5.f, 5.f,
     26   6.f, 5.f, 5.f,
     27   5.f, 6.f, 5.f,
     28   6.f, 6.f, 5.f,
     29   5.f, 5.f, 6.f,
     30   6.f, 5.f, 6.f,
     31   5.f, 6.f, 6.f,
     32   6.f, 6.f, 6.f
     33 };
     34 static const unsigned cube_nverts = sizeof(cube_verts) / (sizeof(float)*3);
     35 
     36 /* Front faces are CW. The normals point into the cube */
     37 static const unsigned cube_ids[] = {
     38   0, 2, 1, 1, 2, 3, /* Front */
     39   0, 4, 2, 2, 4, 6, /* Left */
     40   4, 5, 6, 6, 5, 7, /* Back */
     41   3, 7, 1, 1, 7, 5, /* Right */
     42   2, 6, 3, 3, 6, 7, /* Top */
     43   0, 1, 4, 4, 1, 5 /* Bottom */
     44 };
     45 static const unsigned cube_ntris = sizeof(cube_ids) / (sizeof(unsigned)*3);
     46 
     47 static void
     48 cube_get_ids(const unsigned itri, unsigned ids[3], void* data)
     49 {
     50   const unsigned id = itri * 3;
     51   CHK(data == NULL);
     52   CHK(ids != NULL);
     53   CHK(itri < cube_ntris);
     54   ids[0] = cube_ids[id + 0];
     55   ids[1] = cube_ids[id + 1];
     56   ids[2] = cube_ids[id + 2];
     57 }
     58 
     59 static void
     60 cube_get_pos(const unsigned ivert, float pos[3], void* data)
     61 {
     62   const unsigned i = ivert*3;
     63   CHK(data == NULL);
     64   CHK(pos != NULL);
     65   CHK(ivert < cube_nverts);
     66   pos[0] = cube_verts[i + 0];
     67   pos[1] = cube_verts[i + 1];
     68   pos[2] = cube_verts[i + 2];
     69 }
     70 
     71 int
     72 main(int argc, char** argv)
     73 {
     74   struct mem_allocator allocator;
     75   struct s3d_primitive prims[10];
     76   struct s3d_device* dev, *dev2;
     77   struct s3d_scene* scn;
     78   struct s3d_scene* scn2;
     79   struct s3d_scene* scn3;
     80   struct s3d_scene_view* scnview;
     81   struct s3d_scene_view* scnview2;
     82   struct s3d_scene_view* scnview3;
     83   struct s3d_vertex_data attribs;
     84   struct s3d_shape* shapes[4];
     85   const size_t nshapes = sizeof(shapes)/sizeof(struct s3d_shape*);
     86   void* data = (void*)&cbox_walls_desc;
     87   size_t i, n;
     88   size_t nprims;
     89   float area, volume, lower[3], upper[3];
     90   unsigned id;
     91   int mask;
     92   (void)argc, (void)argv;
     93 
     94   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
     95 
     96   CHK(s3d_device_create(NULL, &allocator, 1, &dev) == RES_OK);
     97   FOR_EACH(i, 0, nshapes)
     98     CHK(s3d_shape_create_mesh(dev, shapes + i) == RES_OK);
     99 
    100   CHK(s3d_scene_create(NULL, NULL) == RES_BAD_ARG);
    101   CHK(s3d_scene_create(dev, NULL) == RES_BAD_ARG);
    102   CHK(s3d_scene_create(NULL, &scn) == RES_BAD_ARG);
    103   CHK(s3d_scene_create(dev, &scn) == RES_OK);
    104   CHK(s3d_scene_create(dev, &scn2) == RES_OK);
    105   CHK(s3d_scene_create(dev, &scn3) == RES_OK);
    106 
    107   CHK(s3d_scene_get_shapes_count(NULL, NULL) == RES_BAD_ARG);
    108   CHK(s3d_scene_get_shapes_count(scn, NULL) == RES_BAD_ARG);
    109   CHK(s3d_scene_get_shapes_count(NULL, &n) == RES_BAD_ARG);
    110   CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK);
    111   CHK(n == 0);
    112 
    113   CHK(s3d_scene_attach_shape(NULL, NULL) == RES_BAD_ARG);
    114   CHK(s3d_scene_attach_shape(scn, NULL) == RES_BAD_ARG);
    115   CHK(s3d_scene_attach_shape(NULL, shapes[0]) == RES_BAD_ARG);
    116   CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK);
    117   CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK);
    118   CHK(n == 1);
    119   CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK);
    120   CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK);
    121   CHK(n == 1);
    122 
    123   CHK(s3d_scene_detach_shape(NULL, NULL) == RES_BAD_ARG);
    124   CHK(s3d_scene_detach_shape(scn, NULL) == RES_BAD_ARG);
    125   CHK(s3d_scene_detach_shape(NULL, shapes[0]) == RES_BAD_ARG);
    126   CHK(s3d_scene_detach_shape(scn, shapes[0]) == RES_OK);
    127   CHK(s3d_scene_detach_shape(scn, shapes[0]) == RES_BAD_ARG);
    128   CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK);
    129   CHK(n == 0);
    130 
    131   FOR_EACH(i, 1, nshapes) {
    132     CHK(s3d_scene_attach_shape(scn, shapes[i]) == RES_OK);
    133     CHK(s3d_shape_ref_put(shapes[i]) == RES_OK);
    134   }
    135   CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK);
    136   CHK(n == nshapes - 1);
    137 
    138   CHK(s3d_scene_instantiate(NULL, NULL) == RES_BAD_ARG);
    139   CHK(s3d_scene_instantiate(scn, NULL) == RES_BAD_ARG);
    140   CHK(s3d_scene_instantiate(NULL, shapes + 1) == RES_BAD_ARG);
    141   CHK(s3d_scene_instantiate(scn, shapes + 1) == RES_OK);
    142 
    143   CHK(s3d_shape_get_id(NULL, NULL) == RES_BAD_ARG);
    144   CHK(s3d_shape_get_id(shapes[1], NULL) == RES_BAD_ARG);
    145   CHK(s3d_shape_get_id(NULL, &id) == RES_BAD_ARG);
    146   CHK(s3d_shape_get_id(shapes[1], &id) == RES_OK);
    147   CHK(id != S3D_INVALID_ID);
    148 
    149   CHK(s3d_scene_clear(NULL) == RES_BAD_ARG);
    150   CHK(s3d_scene_clear(scn) == RES_OK);
    151   CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK);
    152   CHK(n == 0);
    153   CHK(s3d_scene_clear(scn) == RES_OK);
    154   CHK(s3d_scene_instantiate(scn, shapes + 2) == RES_OK);
    155   CHK(s3d_scene_attach_shape(scn, shapes[2]) == RES_BAD_ARG);
    156 
    157   CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK);
    158   CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK);
    159   CHK(n == 1);
    160 
    161   CHK(s3d_scene_view_create(scn, S3D_TRACE, &scnview) == RES_OK);
    162   CHK(s3d_scene_view_get_mask(scnview, &mask) == RES_OK);
    163   CHK(mask == S3D_TRACE);
    164 
    165   CHK(s3d_scene_detach_shape(scn, shapes[0]) == RES_OK);
    166   CHK(s3d_scene_clear(scn) == RES_OK);
    167 
    168   CHK(s3d_scene_view_ref_put(scnview) == RES_OK);
    169 
    170   CHK(s3d_scene_view_create(scn, S3D_TRACE, &scnview) == RES_OK);
    171   CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK);
    172   CHK(s3d_scene_detach_shape(scn, shapes[0]) == RES_OK);
    173   CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK);
    174   CHK(s3d_scene_view_ref_put(scnview) == RES_OK);
    175 
    176   CHK(s3d_scene_attach_shape(scn2, shapes[1]) == RES_OK);
    177   CHK(s3d_scene_attach_shape(scn2, shapes[2]) == RES_OK);
    178   CHK(s3d_scene_attach_shape(scn3, shapes[1]) == RES_OK);
    179 
    180   CHK(s3d_scene_get_shapes_count(scn, &n) == RES_OK);
    181   CHK(n == 1);
    182   CHK(s3d_scene_get_shapes_count(scn2, &n) == RES_OK);
    183   CHK(n == 2);
    184   CHK(s3d_scene_get_shapes_count(scn3, &n) == RES_OK);
    185   CHK(n == 1);
    186 
    187   CHK(s3d_scene_view_create(scn2, S3D_SAMPLE|S3D_TRACE, &scnview2) == RES_OK);
    188   CHK(s3d_scene_view_create(scn, S3D_SAMPLE, &scnview) == RES_OK);
    189   CHK(s3d_scene_view_create(scn3, S3D_SAMPLE, &scnview3) == RES_OK);
    190   CHK(s3d_scene_view_ref_put(scnview3) == RES_OK);
    191 
    192   CHK(s3d_scene_view_compute_area(NULL, NULL) == RES_BAD_ARG);
    193   CHK(s3d_scene_view_compute_area(scnview2, NULL) == RES_BAD_ARG);
    194   CHK(s3d_scene_view_compute_area(NULL, &area) == RES_BAD_ARG);
    195   CHK(s3d_scene_view_compute_area(scnview2, &area) == RES_OK);
    196   CHK(area == 0.f);
    197 
    198   CHK(s3d_scene_view_compute_volume(NULL, NULL) == RES_BAD_ARG);
    199   CHK(s3d_scene_view_compute_volume(scnview2, NULL) == RES_BAD_ARG);
    200   CHK(s3d_scene_view_compute_volume(NULL, &volume) == RES_BAD_ARG);
    201   CHK(s3d_scene_view_compute_volume(scnview2, &volume) == RES_OK);
    202   CHK(volume == 0.f);
    203 
    204   CHK(s3d_scene_view_primitives_count(NULL, NULL) == RES_BAD_ARG);
    205   CHK(s3d_scene_view_primitives_count(scnview2, NULL) == RES_BAD_ARG);
    206   CHK(s3d_scene_view_primitives_count(NULL, &nprims) == RES_BAD_ARG);
    207   CHK(s3d_scene_view_primitives_count(scnview2, &nprims) == RES_OK);
    208   CHK(nprims == 0);
    209 
    210   CHK(s3d_scene_view_get_aabb(NULL, NULL, NULL) == RES_BAD_ARG);
    211   CHK(s3d_scene_view_get_aabb(scnview2, NULL, NULL) == RES_BAD_ARG);
    212   CHK(s3d_scene_view_get_aabb(NULL, lower, NULL) == RES_BAD_ARG);
    213   CHK(s3d_scene_view_get_aabb(scnview2, lower, NULL) == RES_BAD_ARG);
    214   CHK(s3d_scene_view_get_aabb(NULL, NULL, upper) == RES_BAD_ARG);
    215   CHK(s3d_scene_view_get_aabb(scnview2, NULL, upper) == RES_BAD_ARG);
    216   CHK(s3d_scene_view_get_aabb(NULL, lower, upper) == RES_BAD_ARG);
    217   CHK(s3d_scene_view_get_aabb(scnview2, lower, upper) == RES_OK);
    218   CHK(lower[0] > upper[0]);
    219   CHK(lower[1] > upper[1]);
    220   CHK(lower[2] > upper[2]);
    221 
    222   CHK(s3d_scene_view_ref_put(scnview) == RES_OK);
    223   CHK(s3d_scene_view_ref_put(scnview2) == RES_OK);
    224 
    225   CHK(s3d_scene_instantiate(scn2, shapes + 3) == RES_OK);
    226   CHK(s3d_scene_attach_shape(scn3, shapes[3]) == RES_OK);
    227   CHK(s3d_scene_get_shapes_count(scn3, &n) == RES_OK);
    228   CHK(n == 2);
    229   CHK(s3d_scene_view_create(scn3, S3D_SAMPLE|S3D_TRACE, &scnview3) == RES_BAD_ARG);
    230 
    231   CHK(s3d_scene_detach_shape(scn, shapes[0]) == RES_OK);
    232 
    233   CHK(s3d_shape_ref_put(shapes[0]) == RES_OK);
    234   CHK(s3d_shape_ref_put(shapes[1]) == RES_OK);
    235   CHK(s3d_shape_ref_put(shapes[2]) == RES_OK);
    236   CHK(s3d_shape_ref_put(shapes[3]) == RES_OK);
    237 
    238   CHK(s3d_scene_ref_get(NULL) == RES_BAD_ARG);
    239   CHK(s3d_scene_ref_get(scn) == RES_OK);
    240   CHK(s3d_scene_ref_put(NULL) == RES_BAD_ARG);
    241   CHK(s3d_scene_ref_put(scn) == RES_OK);
    242   CHK(s3d_scene_ref_put(scn) == RES_OK);
    243   CHK(s3d_scene_ref_put(scn2) == RES_OK);
    244   CHK(s3d_scene_ref_put(scn3) == RES_OK);
    245 
    246   CHK(s3d_scene_create(dev, &scn) == RES_OK);
    247   CHK(s3d_scene_create(dev, &scn2) == RES_OK);
    248 
    249   attribs.type = S3D_FLOAT3;
    250   attribs.usage = S3D_POSITION;
    251   attribs.get = cbox_get_position;
    252   CHK(s3d_shape_create_mesh(dev, shapes + 0) == RES_OK);
    253   CHK(s3d_mesh_setup_indexed_vertices(shapes[0], cbox_walls_ntris,
    254     cbox_get_ids, cbox_walls_nverts, &attribs, 1, data) == RES_OK);
    255   CHK(s3d_scene_attach_shape(scn, shapes[0]) == RES_OK);
    256 
    257   CHK(s3d_scene_view_create(scn, S3D_TRACE, &scnview) == RES_OK);
    258   CHK(s3d_scene_view_compute_area(scnview, &area) == RES_OK);
    259   CHK(eq_epsf(area, 1532296.f, 1.e-6f) == 1);
    260   CHK(s3d_scene_view_primitives_count(scnview, &nprims) == RES_OK);
    261   CHK(nprims == 10);
    262   CHK(s3d_scene_view_get_aabb(scnview, lower, upper) == RES_OK);
    263   CHK(eq_epsf(lower[0], 0.f, 1.e-6f) == 1);
    264   CHK(eq_epsf(lower[1], 0.f, 1.e-6f) == 1);
    265   CHK(eq_epsf(lower[2], 0.f, 1.e-6f) == 1);
    266   CHK(eq_epsf(upper[0], 552.f, 1.e-6f) == 1);
    267   CHK(eq_epsf(upper[1], 559.f, 1.e-6f) == 1);
    268   CHK(eq_epsf(upper[2], 548.f, 1.e-6f) == 1);
    269 
    270   CHK(s3d_scene_instantiate(scn, shapes + 1) == RES_OK);
    271   CHK(s3d_scene_attach_shape(scn2, shapes[1]) == RES_OK);
    272 
    273   CHK(s3d_scene_view_create(scn2, S3D_GET_PRIMITIVE, &scnview2) == RES_OK);
    274   CHK(s3d_scene_view_compute_area(scnview2, &area) == RES_OK);
    275   CHK(eq_epsf(area, 1532296.f, 1.e-6f) == 1);
    276   CHK(s3d_scene_view_primitives_count(scnview2, &nprims) == RES_OK);
    277   CHK(nprims == 10);
    278   CHK(s3d_scene_view_get_aabb(scnview2, lower, upper) == RES_OK);
    279   CHK(eq_epsf(lower[0], 0.f, 1.e-6f) == 1);
    280   CHK(eq_epsf(lower[1], 0.f, 1.e-6f) == 1);
    281   CHK(eq_epsf(lower[2], 0.f, 1.e-6f) == 1);
    282   CHK(eq_epsf(upper[0], 552.f, 1.e-6f) == 1);
    283   CHK(eq_epsf(upper[1], 559.f, 1.e-6f) == 1);
    284   CHK(eq_epsf(upper[2], 548.f, 1.e-6f) == 1);
    285 
    286   CHK(s3d_scene_view_compute_area(scnview, &area) == RES_OK);
    287   CHK(eq_epsf(area, 1532296.f, 1.e-6f) == 1);
    288   CHK(s3d_scene_view_ref_put(scnview) == RES_OK);
    289 
    290   CHK(s3d_scene_view_get_primitive(NULL, 11, NULL) == RES_BAD_ARG);
    291   CHK(s3d_scene_view_get_primitive(scnview2, 11, NULL) == RES_BAD_ARG);
    292   CHK(s3d_scene_view_get_primitive(NULL, 0, NULL) == RES_BAD_ARG);
    293   CHK(s3d_scene_view_get_primitive(scnview2, 0, NULL) == RES_BAD_ARG);
    294   CHK(s3d_scene_view_get_primitive(NULL, 11, prims + 0) == RES_BAD_ARG);
    295   CHK(s3d_scene_view_get_primitive(scnview2, 11, prims + 0) == RES_BAD_ARG);
    296   CHK(s3d_scene_view_get_primitive(NULL, 0, prims + 0) == RES_BAD_ARG);
    297 
    298   FOR_EACH(i, 0, nprims) {
    299     size_t j;
    300     CHK(s3d_scene_view_get_primitive(scnview2, (unsigned)i, prims + i) == RES_OK);
    301     CHK(S3D_PRIMITIVE_EQ(prims + i, &S3D_PRIMITIVE_NULL) == 0);
    302     CHK(prims[i].scene_prim_id == i);
    303     FOR_EACH(j, 0, i)
    304       CHK(S3D_PRIMITIVE_EQ(prims + i, prims + j) == 0);
    305   }
    306   CHK(s3d_scene_view_ref_put(scnview2) == RES_OK);
    307 
    308   attribs.type = S3D_FLOAT3;
    309   attribs.usage = S3D_POSITION;
    310   attribs.get = cube_get_pos;
    311   CHK(s3d_mesh_setup_indexed_vertices
    312     (shapes[0], cube_ntris, cube_get_ids, cube_nverts, &attribs, 1, NULL) == RES_OK);
    313 
    314   CHK(s3d_scene_view_create(scn, S3D_TRACE, &scnview) == RES_OK);
    315   CHK(s3d_scene_view_compute_area(scnview, &area) == RES_OK);
    316   CHK(eq_epsf(area, 6.f, 1.e-6f) == 1);
    317   CHK(s3d_scene_view_compute_volume(scnview, &volume) == RES_OK);
    318   CHK(eq_epsf(volume, 1.f, 1.e-6f) == 1);
    319   CHK(s3d_scene_view_ref_put(scnview) == RES_OK);
    320 
    321   CHK(s3d_shape_flip_surface(shapes[0]) == RES_OK);
    322   CHK(s3d_scene_view_create(scn, S3D_GET_PRIMITIVE, &scnview) == RES_OK);
    323   CHK(s3d_scene_view_compute_volume(scnview, &volume) == RES_OK);
    324   CHK(eq_epsf(volume, -1.f, 1.e-6f) == 1);
    325   CHK(s3d_scene_view_ref_put(scnview) == RES_OK);
    326 
    327   CHK(s3d_scene_get_device(NULL, NULL) == RES_BAD_ARG);
    328   CHK(s3d_scene_get_device(scn, NULL) == RES_BAD_ARG);
    329   CHK(s3d_scene_get_device(NULL, &dev2) == RES_BAD_ARG);
    330   CHK(s3d_scene_get_device(scn, &dev2) == RES_OK);
    331   CHK(dev2 == dev);
    332   CHK(s3d_scene_get_device(scn2, &dev2) == RES_OK);
    333   CHK(dev2 == dev);
    334 
    335   CHK(s3d_scene_ref_put(scn) == RES_OK);
    336   CHK(s3d_scene_ref_put(scn2) == RES_OK);
    337   CHK(s3d_shape_ref_put(shapes[0]) == RES_OK);
    338   CHK(s3d_shape_ref_put(shapes[1]) == RES_OK);
    339 
    340   CHK(s3d_device_ref_put(dev) == RES_OK);;
    341 
    342   check_memory_allocator(&allocator);
    343   mem_shutdown_proxy_allocator(&allocator);
    344   CHK(mem_allocated_size() == 0);
    345   return 0;
    346 }
    347