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_scene_view_aabb.c (16150B)


      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_utils.h"
     18 #include "test_s3d_cbox.h"
     19 
     20 #include <rsys/float3.h>
     21 
     22 /*******************************************************************************
     23  * Helper functions
     24  ******************************************************************************/
     25 static void
     26 compute_mesh_aabb
     27   (const float* pos,
     28    const size_t nverts,
     29    const unsigned* ids,
     30    const size_t ntris,
     31    float low[3],
     32    float upp[3])
     33 {
     34   size_t i;
     35 
     36   CHK(low && upp && pos && nverts && ids && ntris);
     37   f3_splat(low, FLT_MAX);
     38   f3_splat(upp,-FLT_MAX);
     39 
     40   FOR_EACH(i, 0, ntris*3) {
     41     const float* vertex = pos + ids[i]*3;
     42     f3_min(low, vertex, low);
     43     f3_max(upp, vertex, upp);
     44   }
     45 }
     46 
     47 static int
     48 aabb_is_degenerated(const float low[3], const float upp[3])
     49 {
     50   CHK(low && upp);
     51   return low[0] > upp[0]
     52       && low[1] > upp[1]
     53       && low[2] > upp[2];
     54 }
     55 
     56 /*******************************************************************************
     57  * Instances
     58  ******************************************************************************/
     59 static void
     60 test_instances(struct s3d_device* dev)
     61 {
     62   struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL;
     63   struct s3d_scene* scn = NULL;
     64   struct s3d_scene* scn2 = NULL;
     65   struct s3d_scene_view* view = NULL;
     66   struct s3d_shape* sphere = NULL;
     67   struct s3d_shape* tall_block = NULL;
     68   struct s3d_shape* inst0 = NULL;
     69   struct s3d_shape* inst1 = NULL;
     70   struct cbox_desc desc;
     71   float low[3], upp[3];
     72   float scn_low[3], scn_upp[3];
     73   float scn2_low[3], scn2_upp[3];
     74   float inst0_low[3], inst0_upp[3];
     75   float inst1_low[3], inst1_upp[3];
     76   float tall_block_low[3], tall_block_upp[3];
     77   float sphere_low[3], sphere_upp[3];
     78   float inst0_trans[3];
     79   float inst1_trans[3];
     80   float pos[3];
     81   float radius;
     82 
     83   /* Create the tall block shape*/
     84   vdata.usage = S3D_POSITION;
     85   vdata.type = S3D_FLOAT3;
     86   vdata.get = cbox_get_position;
     87   desc.vertices = cbox_tall_block;
     88   desc.indices = cbox_block_ids;
     89   CHK(s3d_shape_create_mesh(dev, &tall_block) == RES_OK);
     90   CHK(s3d_mesh_setup_indexed_vertices(tall_block, cbox_block_ntris, cbox_get_ids,
     91     cbox_block_nverts, &vdata, 1, &desc) == RES_OK);
     92   compute_mesh_aabb(cbox_tall_block, cbox_block_nverts, cbox_block_ids,
     93     cbox_block_ntris, tall_block_low, tall_block_upp);
     94 
     95   /* Create the sphere and ensure that it is not contained into the block */
     96   pos[0] =  tall_block_low[0] - 10.f;
     97   pos[1] = (tall_block_upp[1] + tall_block_low[1]) * 0.5f;
     98   pos[2] = (tall_block_upp[2] + tall_block_low[2]) * 0.5f;
     99   radius = 1.f;
    100   CHK(s3d_shape_create_sphere(dev, &sphere) == RES_OK);
    101   CHK(s3d_sphere_setup(sphere, pos, radius) == RES_OK);
    102   f3_subf(sphere_low, pos, radius);
    103   f3_addf(sphere_upp, pos, radius);
    104 
    105   /* Create the scene to instantiate */
    106   CHK(s3d_scene_create(dev, &scn) == RES_OK);
    107   CHK(s3d_scene_attach_shape(scn, sphere) == RES_OK);
    108   CHK(s3d_scene_attach_shape(scn, tall_block) == RES_OK);
    109 
    110   /* Compute the AABB of the original scene */
    111   f3_min(scn_low, tall_block_low, sphere_low);
    112   f3_max(scn_upp, tall_block_upp, sphere_upp);
    113 
    114   /* Create two instances */
    115   inst0_trans[0] = -100.f;
    116   inst0_trans[1] = 0.f;
    117   inst0_trans[2] = -50.f;
    118   inst1_trans[0] = 123.f;
    119   inst1_trans[1] = 4.56f;
    120   inst1_trans[2] = 0.789f;
    121   CHK(s3d_scene_instantiate(scn, &inst0) == RES_OK);
    122   CHK(s3d_scene_instantiate(scn, &inst1) == RES_OK);
    123   CHK(s3d_instance_translate(inst0, S3D_WORLD_TRANSFORM, inst0_trans) == RES_OK);
    124   CHK(s3d_instance_translate(inst1, S3D_WORLD_TRANSFORM, inst1_trans) == RES_OK);
    125   f3_add(inst0_low, scn_low, inst0_trans);
    126   f3_add(inst0_upp, scn_upp, inst0_trans);
    127   f3_add(inst1_low, scn_low, inst1_trans);
    128   f3_add(inst1_upp, scn_upp, inst1_trans);
    129 
    130   /* Create the scene with the 2 instances */
    131   CHK(s3d_scene_create(dev, &scn2) == RES_OK);
    132   CHK(s3d_scene_attach_shape(scn2, inst0) == RES_OK);
    133   CHK(s3d_scene_attach_shape(scn2, inst1) == RES_OK);
    134 
    135   /* Compute the AABB of the scene with instances */
    136   f3_min(scn2_low, inst0_low, inst1_low);
    137   f3_max(scn2_upp, inst0_upp, inst1_upp);
    138 
    139   /* Original scene */
    140   CHK(s3d_scene_view_create(scn, 0, &view) == RES_OK);
    141   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    142   CHK(f3_eq_eps(scn_low, low, 1.e-6f));
    143   CHK(f3_eq_eps(scn_upp, upp, 1.e-6f));
    144   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    145 
    146   /* Retry the original scene to test the cache mechanism */
    147   CHK(s3d_scene_view_create(scn, 0, &view) == RES_OK);
    148   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    149   CHK(f3_eq_eps(scn_low, low, 1.e-6f));
    150   CHK(f3_eq_eps(scn_upp, upp, 1.e-6f));
    151   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    152 
    153   /* Scene with the 2 instances */
    154   CHK(s3d_scene_view_create(scn2, 0, &view) == RES_OK);
    155   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    156   CHK(f3_eq_eps(scn2_low, low, 1.e-6f));
    157   CHK(f3_eq_eps(scn2_upp, upp, 1.e-6f));
    158   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    159 
    160   /* Retry the scene with the 2 instances to check the cache mechanism */
    161   CHK(s3d_scene_view_create(scn2, 0, &view) == RES_OK);
    162   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    163   CHK(f3_eq_eps(scn2_low, low, 1.e-6f));
    164   CHK(f3_eq_eps(scn2_upp, upp, 1.e-6f));
    165   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    166 
    167   /* Scene with only one instance */
    168   CHK(s3d_shape_enable(inst0, 0) == RES_OK);
    169   CHK(s3d_scene_view_create(scn2, 0, &view) == RES_OK);
    170   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    171   CHK(f3_eq_eps(inst1_low, low, 1.e-6f));
    172   CHK(f3_eq_eps(inst1_upp, upp, 1.e-6f));
    173   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    174 
    175   /* Scene whose instances have only the tall_block */
    176   CHK(s3d_shape_enable(inst0, 1) == RES_OK);
    177   CHK(s3d_shape_enable(sphere, 0) == RES_OK);
    178   f3_add(inst0_low, tall_block_low, inst0_trans);
    179   f3_add(inst0_upp, tall_block_upp, inst0_trans);
    180   f3_add(inst1_low, tall_block_low, inst1_trans);
    181   f3_add(inst1_upp, tall_block_upp, inst1_trans);
    182   f3_min(scn2_low, inst0_low, inst1_low);
    183   f3_max(scn2_upp, inst0_upp, inst1_upp);
    184   CHK(s3d_scene_view_create(scn2, 0, &view) == RES_OK);
    185   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    186   CHK(f3_eq_eps(scn2_low, low, 1.e-6f));
    187   CHK(f3_eq_eps(scn2_upp, upp, 1.e-6f));
    188   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    189 
    190   /* Scene with one instance, one mesh and one sphere */
    191   CHK(s3d_scene_detach_shape(scn2, inst1) == RES_OK);
    192   CHK(s3d_scene_attach_shape(scn2, sphere) == RES_OK);
    193   CHK(s3d_scene_attach_shape(scn2, tall_block) == RES_OK);
    194   f3_min(scn2_low, f3_min(scn2_low, tall_block_low, sphere_low), inst0_low);
    195   f3_max(scn2_upp, f3_max(scn2_upp, tall_block_upp, sphere_upp), inst0_upp);
    196   CHK(s3d_scene_view_create(scn2, 0, &view) == RES_OK);
    197   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    198   CHK(f3_eq_eps(scn2_low, low, 1.e-6f));
    199   CHK(f3_eq_eps(scn2_upp, upp, 1.e-6f));
    200   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    201 
    202   /* Clean up */
    203   CHK(s3d_scene_ref_put(scn) == RES_OK);
    204   CHK(s3d_scene_ref_put(scn2) == RES_OK);
    205   CHK(s3d_shape_ref_put(sphere) == RES_OK);
    206   CHK(s3d_shape_ref_put(tall_block) == RES_OK);
    207   CHK(s3d_shape_ref_put(inst0) == RES_OK);
    208   CHK(s3d_shape_ref_put(inst1) == RES_OK);
    209 }
    210 
    211 /*******************************************************************************
    212  * Cornell box
    213  ******************************************************************************/
    214 static void
    215 test_cbox(struct s3d_device* dev)
    216 {
    217   struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL;
    218   struct s3d_scene* scn = NULL;
    219   struct s3d_scene_view* view = NULL;
    220   struct s3d_shape* walls = NULL;
    221   struct s3d_shape* tall_block = NULL;
    222   struct s3d_shape* short_block = NULL;
    223   struct cbox_desc desc;
    224   float low[3], upp[3];
    225   float walls_low[3], walls_upp[3];
    226   float tall_block_low[3], tall_block_upp[3];
    227   float short_block_low[3], short_block_upp[3];
    228   float aabb_low[3], aabb_upp[3];
    229 
    230   /* Create the Star-3D scene and the Cornell box meshes */
    231   CHK(s3d_scene_create(dev, &scn) == RES_OK);
    232   CHK(s3d_shape_create_mesh(dev, &walls) == RES_OK);
    233   CHK(s3d_shape_create_mesh(dev, &tall_block) == RES_OK);
    234   CHK(s3d_shape_create_mesh(dev, &short_block) == RES_OK);
    235 
    236   vdata.usage = S3D_POSITION;
    237   vdata.type = S3D_FLOAT3;
    238   vdata.get = cbox_get_position;
    239 
    240   /* Setup the Cornell box walls */
    241   desc.vertices = cbox_walls;
    242   desc.indices = cbox_walls_ids;
    243   CHK(s3d_mesh_setup_indexed_vertices(walls, cbox_walls_ntris, cbox_get_ids,
    244     cbox_walls_nverts, &vdata, 1, &desc) == RES_OK);
    245   compute_mesh_aabb(cbox_walls, cbox_walls_nverts, cbox_walls_ids,
    246     cbox_walls_ntris, walls_low, walls_upp);
    247 
    248   /* Setup the Cornell box tall block */
    249   desc.vertices = cbox_tall_block;
    250   desc.indices = cbox_block_ids;
    251   CHK(s3d_mesh_setup_indexed_vertices(tall_block, cbox_block_ntris, cbox_get_ids,
    252     cbox_block_nverts, &vdata, 1, &desc) == RES_OK);
    253   compute_mesh_aabb(cbox_tall_block, cbox_block_nverts, cbox_block_ids,
    254     cbox_block_ntris, tall_block_low, tall_block_upp);
    255 
    256   /* Setup the Cornell box short block */
    257   desc.vertices = cbox_short_block;
    258   desc.indices = cbox_block_ids;
    259   CHK(s3d_mesh_setup_indexed_vertices(short_block, cbox_block_ntris, cbox_get_ids,
    260     cbox_block_nverts, &vdata, 1, &desc) == RES_OK);
    261   compute_mesh_aabb(cbox_short_block, cbox_block_nverts, cbox_block_ids,
    262     cbox_block_ntris, short_block_low, short_block_upp);
    263 
    264   /* Tall block only */
    265   CHK(s3d_scene_attach_shape(scn, tall_block) == RES_OK);
    266   CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK);
    267   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    268   CHK(f3_eq_eps(tall_block_low, low, 1.e-6f));
    269   CHK(f3_eq_eps(tall_block_upp, upp, 1.e-6f));
    270   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    271 
    272   /* Disabled tall block only */
    273   CHK(s3d_shape_enable(tall_block, 0) == RES_OK);
    274   CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK);
    275   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    276   CHK(aabb_is_degenerated(low, upp));
    277   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    278 
    279   /* Tall block only with wo S3D_TRACE flag */
    280   CHK(s3d_shape_enable(tall_block, 1) == RES_OK);
    281   CHK(s3d_scene_view_create(scn, 0, &view) == RES_OK);
    282   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    283   CHK(f3_eq_eps(tall_block_low, low, 1.e-6f));
    284   CHK(f3_eq_eps(tall_block_upp, upp, 1.e-6f));
    285   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    286 
    287   /* All blocks */
    288   CHK(s3d_scene_attach_shape(scn, short_block) == RES_OK);
    289   CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK);
    290   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    291   f3_min(aabb_low, tall_block_low, short_block_low);
    292   f3_max(aabb_upp, tall_block_upp, short_block_upp);
    293   CHK(f3_eq_eps(aabb_low, low, 1.e-6f));
    294   CHK(f3_eq_eps(aabb_upp, upp, 1.e-6f));
    295   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    296 
    297   /* Another try with all blocks to check the cache mechanism */
    298   CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK);
    299   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    300   CHK(f3_eq_eps(aabb_low, low, 1.e-6f));
    301   CHK(f3_eq_eps(aabb_upp, upp, 1.e-6f));
    302   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    303 
    304   /* All blocks but the tall block is disabled */
    305   CHK(s3d_shape_enable(tall_block, 0) == RES_OK);
    306   CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK);
    307   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    308   CHK(f3_eq_eps(short_block_low, low, 1.e-6f));
    309   CHK(f3_eq_eps(short_block_upp, upp, 1.e-6f));
    310   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    311 
    312   /* All blocks but the short block is disabled */
    313   CHK(s3d_shape_enable(tall_block, 1) == RES_OK);
    314   CHK(s3d_shape_enable(short_block, 0) == RES_OK);
    315   CHK(s3d_scene_view_create(scn, 0, &view) == RES_OK);
    316   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    317   CHK(f3_eq_eps(tall_block_low, low, 1.e-6f));
    318   CHK(f3_eq_eps(tall_block_upp, upp, 1.e-6f));
    319   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    320 
    321   /* The whole Cornell box */
    322   CHK(s3d_shape_enable(short_block, 1) == RES_OK);
    323   CHK(s3d_scene_attach_shape(scn, walls) == RES_OK);
    324   CHK(s3d_scene_view_create(scn, 0, &view) == RES_OK);
    325   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    326   f3_min(aabb_low, f3_min(aabb_low, tall_block_low, short_block_low), walls_low);
    327   f3_max(aabb_upp, f3_max(aabb_upp, tall_block_upp, short_block_upp), walls_upp);
    328   CHK(f3_eq_eps(aabb_low, low, 1.e-6f));
    329   CHK(f3_eq_eps(aabb_upp, upp, 1.e-6f));
    330   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    331 
    332   /* Retry the whole Cornell box */
    333   CHK(s3d_scene_view_create(scn, 0, &view) == RES_OK);
    334   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    335   CHK(f3_eq_eps(aabb_low, low, 1.e-6f));
    336   CHK(f3_eq_eps(aabb_upp, upp, 1.e-6f));
    337   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    338 
    339   /* Disable all */
    340   CHK(s3d_shape_enable(walls, 0) == RES_OK);
    341   CHK(s3d_shape_enable(tall_block, 0) == RES_OK);
    342   CHK(s3d_shape_enable(short_block, 0) == RES_OK);
    343   CHK(s3d_scene_view_create(scn, 0, &view) == RES_OK);
    344   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    345   CHK(aabb_is_degenerated(low, upp));
    346   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    347 
    348   /* Only the short block */
    349   CHK(s3d_shape_enable(walls, 1) == RES_OK);
    350   CHK(s3d_shape_enable(tall_block, 1) == RES_OK);
    351   CHK(s3d_shape_enable(short_block, 1) == RES_OK);
    352   CHK(s3d_scene_detach_shape(scn, walls) == RES_OK);
    353   CHK(s3d_scene_detach_shape(scn, tall_block) == RES_OK);
    354   CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK);
    355   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    356   CHK(f3_eq_eps(short_block_low, low, 1.e-6f));
    357   CHK(f3_eq_eps(short_block_upp, upp, 1.e-6f));
    358   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    359 
    360   /* Only the short block */
    361   CHK(s3d_scene_clear(scn) == RES_OK);
    362   CHK(s3d_scene_view_create(scn, S3D_TRACE, &view) == RES_OK);
    363   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    364   CHK(aabb_is_degenerated(low, upp));
    365   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    366 
    367   /* Clean up the data */
    368   CHK(s3d_scene_ref_put(scn) == RES_OK);
    369   CHK(s3d_shape_ref_put(walls) == RES_OK);
    370   CHK(s3d_shape_ref_put(tall_block) == RES_OK);
    371   CHK(s3d_shape_ref_put(short_block) == RES_OK);
    372 }
    373 
    374 /*******************************************************************************
    375  * Test the API
    376  ******************************************************************************/
    377 static void
    378 test_api(struct s3d_device* dev)
    379 {
    380   struct s3d_scene* scn = NULL;
    381   struct s3d_scene_view* view = NULL;
    382   float low[3] = {0,0,0};
    383   float upp[3] = {0,0,0};
    384 
    385   CHK(s3d_scene_create(dev, &scn) == RES_OK);
    386   CHK(s3d_scene_view_create(scn, 0, &view) == RES_OK);
    387 
    388   CHK(s3d_scene_view_get_aabb(NULL, low, upp) == RES_BAD_ARG);
    389   CHK(s3d_scene_view_get_aabb(view, NULL, upp) == RES_BAD_ARG);
    390   CHK(s3d_scene_view_get_aabb(view, low, NULL) == RES_BAD_ARG);
    391   CHK(s3d_scene_view_get_aabb(view, low, upp) == RES_OK);
    392   CHK(aabb_is_degenerated(low, upp));
    393 
    394   CHK(s3d_scene_view_ref_put(view) == RES_OK);
    395   CHK(s3d_scene_ref_put(scn) == RES_OK);
    396 }
    397 
    398 /*******************************************************************************
    399  * Main function
    400  ******************************************************************************/
    401 int
    402 main(int argc, char** argv)
    403 {
    404   struct mem_allocator allocator;
    405   struct s3d_device* dev = NULL;
    406   (void)argc, (void)argv;
    407 
    408   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
    409   CHK(s3d_device_create(NULL, &allocator, 1, &dev) == RES_OK);
    410 
    411   test_api(dev);
    412   test_cbox(dev);
    413   test_instances(dev);
    414 
    415   CHK(s3d_device_ref_put(dev) == RES_OK);
    416 
    417   check_memory_allocator(&allocator);
    418   mem_shutdown_proxy_allocator(&allocator);
    419   CHK(mem_allocated_size() == 0);
    420   return 0;
    421 }