star-enclosures-3d

Extract enclosures from 3D geometry
git clone git://git.meso-star.fr/star-enclosures-3d.git
Log | Files | Refs | README | LICENSE

test_senc3d_enclosure.c (9978B)


      1 /* Copyright (C) 2018-2020, 2023, 2024 |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 "senc3d.h"
     17 #include "senc3d_sXd_helper.h"
     18 #include "test_senc3d_utils.h"
     19 
     20 #include <rsys/double3.h>
     21 
     22 #include <star/s3d.h>
     23 
     24 static void
     25 test(const int convention)
     26 {
     27   struct mem_allocator allocator;
     28   struct senc3d_device* dev = NULL;
     29   struct senc3d_scene* scn = NULL;
     30   struct senc3d_enclosure* enclosures[2] = { NULL, NULL };
     31   struct senc3d_enclosure* enclosure;
     32   struct senc3d_enclosure_header header;
     33   struct s3d_device* s3d = NULL;
     34   struct s3d_scene* s3d_scn = NULL;
     35   struct s3d_shape* s3d_shp = NULL;
     36   struct s3d_vertex_data s3d_attribs;
     37   unsigned indices[2][3];
     38   unsigned medium;
     39   unsigned gid;
     40   enum senc3d_side side;
     41   double vrtx[3];
     42   double ext_v = 0;
     43   struct context ctx = CONTEXT_NULL__;
     44   unsigned i, n, t, count;
     45   int conv;
     46   const int conv_front = (convention & SENC3D_CONVENTION_NORMAL_FRONT) != 0;
     47   const int conv_in = (convention & SENC3D_CONVENTION_NORMAL_INSIDE) != 0;
     48 
     49   OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator));
     50   OK(senc3d_device_create(NULL, &allocator, SENC3D_NTHREADS_DEFAULT, 1, &dev));
     51 
     52   /* A 3D cube.
     53    * 2 enclosures (inside, outside) sharing the same triangles,
     54    * but opposite sides */
     55   ctx.positions = box_vertices;
     56   ctx.indices = box_indices;
     57   ctx.front_media = medium0;
     58   ctx.back_media = medium1;
     59 
     60   OK(senc3d_scene_create(dev, convention, ntriangles, get_indices, get_media,
     61     nvertices, get_position, &ctx, &scn));
     62 
     63   OK(senc3d_scene_get_convention(scn, &conv));
     64   CHK(conv == convention);
     65 
     66   OK(senc3d_scene_get_enclosure_count(scn, &count));
     67   CHK(count == 2);
     68 
     69   OK(senc3d_scene_get_enclosure(scn, 0, &enclosure));
     70   BA(senc3d_enclosure_ref_get(NULL));
     71   OK(senc3d_enclosure_ref_get(enclosure));
     72   BA(senc3d_enclosure_ref_put(NULL));
     73   OK(senc3d_enclosure_ref_put(enclosure));
     74 
     75   BA(senc3d_enclosure_get_triangle(NULL, 0, indices[0]));
     76   BA(senc3d_enclosure_get_triangle(enclosure, ntriangles, indices[0]));
     77   BA(senc3d_enclosure_get_triangle(enclosure, 0, NULL));
     78   BA(senc3d_enclosure_get_triangle(NULL, ntriangles, indices[0]));
     79   BA(senc3d_enclosure_get_triangle(NULL, 0, NULL));
     80   BA(senc3d_enclosure_get_triangle(enclosure, ntriangles, NULL));
     81   BA(senc3d_enclosure_get_triangle(NULL, ntriangles, NULL));
     82   OK(senc3d_enclosure_get_triangle(enclosure, 0, indices[0]));
     83 
     84   BA(senc3d_enclosure_get_vertex(NULL, 0, vrtx));
     85   BA(senc3d_enclosure_get_vertex(enclosure, nvertices, vrtx));
     86   BA(senc3d_enclosure_get_vertex(enclosure, 0, NULL));
     87   BA(senc3d_enclosure_get_vertex(NULL, nvertices, vrtx));
     88   BA(senc3d_enclosure_get_vertex(NULL, 0, NULL));
     89   BA(senc3d_enclosure_get_vertex(enclosure, nvertices, NULL));
     90   BA(senc3d_enclosure_get_vertex(NULL, nvertices, NULL));
     91   OK(senc3d_enclosure_get_vertex(enclosure, 0, vrtx));
     92 
     93   BA(senc3d_enclosure_get_triangle_id(NULL, 0, &gid, NULL));
     94   BA(senc3d_enclosure_get_triangle_id(enclosure, ntriangles, &gid, NULL));
     95   BA(senc3d_enclosure_get_triangle_id(enclosure, 0, NULL, NULL));
     96   BA(senc3d_enclosure_get_triangle_id(NULL, ntriangles, &gid, NULL));
     97   BA(senc3d_enclosure_get_triangle_id(NULL, 0, NULL, NULL));
     98   BA(senc3d_enclosure_get_triangle_id(enclosure, ntriangles, NULL, NULL));
     99   BA(senc3d_enclosure_get_triangle_id(NULL, ntriangles, NULL, NULL));
    100   BA(senc3d_enclosure_get_triangle_id(enclosure, 0, &gid, NULL));
    101   BA(senc3d_enclosure_get_triangle_id(NULL, 0, &gid, &side));
    102   BA(senc3d_enclosure_get_triangle_id(enclosure, ntriangles, &gid, &side));
    103   BA(senc3d_enclosure_get_triangle_id(enclosure, 0, NULL, &side));
    104   BA(senc3d_enclosure_get_triangle_id(NULL, ntriangles, &gid, &side));
    105   BA(senc3d_enclosure_get_triangle_id(NULL, 0, NULL, &side));
    106   BA(senc3d_enclosure_get_triangle_id(enclosure, ntriangles, NULL, &side));
    107   BA(senc3d_enclosure_get_triangle_id(NULL, ntriangles, NULL, &side));
    108   OK(senc3d_enclosure_get_triangle_id(enclosure, 0, &gid, &side));
    109 
    110   BA(senc3d_enclosure_get_medium(NULL, 0, &medium));
    111   BA(senc3d_enclosure_get_medium(enclosure, 2, &medium));
    112   BA(senc3d_enclosure_get_medium(enclosure, 0, NULL));
    113   BA(senc3d_enclosure_get_medium(NULL, 2, &medium));
    114   BA(senc3d_enclosure_get_medium(NULL, 0, NULL));
    115   BA(senc3d_enclosure_get_medium(enclosure, 2, NULL));
    116   BA(senc3d_enclosure_get_medium(NULL, 2, NULL));
    117   OK(senc3d_enclosure_get_medium(enclosure, 0, &medium));
    118 
    119   OK(senc3d_enclosure_ref_put(enclosure));
    120 
    121   FOR_EACH(i, 0, count) {
    122     OK(senc3d_scene_get_enclosure(scn, i, &enclosure));
    123 
    124     BA(senc3d_enclosure_get_header(NULL, &header));
    125     BA(senc3d_enclosure_get_header(enclosure, NULL));
    126     BA(senc3d_enclosure_get_header(NULL, NULL));
    127     OK(senc3d_enclosure_get_header(enclosure, &header));
    128 
    129     CHK(header.enclosure_id == i);
    130     CHK(header.enclosed_media_count == 1);
    131     OK(senc3d_enclosure_get_medium(enclosure, 0, &medium));
    132     /* Geometrical normals point outside the cube in input triangles:
    133      * if convention is front, front medium (0) is outside,
    134      * that is medium 0's enclosure is infinite */
    135     CHK(conv_front == ((medium == 0) == header.is_infinite));
    136     CHK(header.primitives_count == ntriangles);
    137     CHK(header.unique_primitives_count == ntriangles);
    138     CHK(header.vertices_count == nvertices);
    139     CHK(header.is_infinite == (i == 0));
    140     if(i == 0) ext_v = header.volume;
    141     else CHK(header.volume == -ext_v);
    142 
    143     FOR_EACH(t, 0, header.primitives_count) {
    144       OK(senc3d_enclosure_get_triangle_id(enclosure, t, &gid, &side));
    145       CHK(gid == t);
    146       CHK(side == (medium == 0) ? SENC3D_FRONT : SENC3D_BACK);
    147     }
    148 
    149     OK(senc3d_enclosure_ref_put(enclosure));
    150   }
    151 
    152   FOR_EACH(i, 0, 2)
    153     OK(senc3d_scene_get_enclosure(scn, i, enclosures + i));
    154   FOR_EACH(n, 0, ntriangles) {
    155     int same, reversed;
    156     /* Read same triangles in both enclosures */
    157     FOR_EACH(i, 0, 2)
    158       OK(senc3d_enclosure_get_triangle(enclosures[i], n, indices[i]));
    159     /* Same triangles and opposite sides for the 2 enclosures */
    160     FOR_EACH(i, 0, 3) CHK(indices[0][i] == indices[1][2 - i]);
    161     /* Enclosure 0 is outside (and contains medium 0 if convention is front).
    162      * Geometrical normals in output data point in the same direction that those
    163      * of input triangles for enclosure 0 iff convention is inside.
    164      * The opposite holds for enclosure 1. */
    165     cmp_trg(n, enclosures[0], box_indices + 3 * n, box_vertices, &same, &reversed);
    166     CHK((same && !reversed) == conv_in);
    167     cmp_trg(n, enclosures[1], box_indices + 3 * n, box_vertices, &same, &reversed);
    168     CHK(same && reversed == conv_in);
    169   }
    170   FOR_EACH(i, 0, 2)
    171     OK(senc3d_enclosure_ref_put(enclosures[i]));
    172 
    173   OK(senc3d_scene_ref_put(scn));
    174 
    175   /* Same 3D cube, but with a hole (incomplete).
    176    * 1 single enclosure including both sides of triangles */
    177 
    178   ctx.positions = box_vertices;
    179   ctx.indices = box_indices;
    180   ctx.front_media = medium0;
    181   ctx.back_media = medium1;
    182 
    183   OK(senc3d_scene_create(dev, convention, ntriangles - 1, get_indices, get_media,
    184     nvertices, get_position, &ctx, &scn));
    185 
    186   OK(senc3d_scene_get_frontier_segments_count(scn, &count));
    187   CHK(count == 3);
    188 
    189   OK(senc3d_scene_get_enclosure_count(scn, &count));
    190   CHK(count == 1);
    191 
    192 #ifdef DUMP_ENCLOSURES
    193   dump_enclosure(scn, 0, "test_enclosure_hole.obj");
    194 #endif
    195 
    196   OK(senc3d_scene_get_enclosure(scn, 0, &enclosure));
    197 
    198   BA(senc3d_enclosure_get_header(NULL, &header));
    199   BA(senc3d_enclosure_get_header(enclosure, NULL));
    200   BA(senc3d_enclosure_get_header(NULL, NULL));
    201   OK(senc3d_enclosure_get_header(enclosure, &header));
    202 
    203   CHK(header.enclosure_id == 0);
    204   CHK(header.enclosed_media_count == 2);
    205   CHK(header.primitives_count == 2 * header.unique_primitives_count);
    206   CHK(header.unique_primitives_count == ntriangles - 1);
    207   CHK(header.vertices_count == nvertices);
    208   CHK(header.is_infinite == 1);
    209   CHK(header.volume == 0);
    210 
    211   FOR_EACH(t, 0, header.primitives_count) {
    212     OK(senc3d_enclosure_get_triangle_id(enclosure, t, &gid, &side));
    213     /* The first unique_triangle_count triangles of an enclosure
    214      * are unique triangles */
    215     if(t < header.unique_primitives_count) CHK(gid == t);
    216     CHK(side == (t < header.unique_primitives_count) ? SENC3D_FRONT : SENC3D_BACK);
    217   }
    218 
    219   /* Put geometry in a 3D view using helper functions */
    220   s3d_attribs.type = S3D_FLOAT3;
    221   s3d_attribs.usage = S3D_POSITION;
    222   s3d_attribs.get = senc3d_sXd_enclosure_get_position;
    223   OK(s3d_device_create(NULL, &allocator, 0, &s3d));
    224   OK(s3d_scene_create(s3d, &s3d_scn));
    225   OK(s3d_shape_create_mesh(s3d, &s3d_shp));
    226   OK(s3d_mesh_setup_indexed_vertices(s3d_shp, header.primitives_count,
    227     senc3d_sXd_enclosure_get_indices, header.vertices_count, &s3d_attribs,
    228     1, enclosure));
    229   OK(s3d_scene_attach_shape(s3d_scn, s3d_shp));
    230   S3D(shape_ref_put(s3d_shp));
    231   S3D(device_ref_put(s3d));
    232   S3D(scene_ref_put(s3d_scn));
    233 
    234   SENC3D(scene_ref_put(scn));
    235   SENC3D(device_ref_put(dev));
    236   SENC3D(enclosure_ref_put(enclosure));
    237 
    238   check_memory_allocator(&allocator);
    239   mem_shutdown_proxy_allocator(&allocator);
    240   CHK(mem_allocated_size() == 0);
    241 }
    242 
    243 int
    244 main(int argc, char** argv)
    245 {
    246   (void) argc, (void) argv;
    247   test(SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_INSIDE);
    248   test(SENC3D_CONVENTION_NORMAL_BACK | SENC3D_CONVENTION_NORMAL_INSIDE);
    249   test(SENC3D_CONVENTION_NORMAL_FRONT | SENC3D_CONVENTION_NORMAL_OUTSIDE);
    250   test(SENC3D_CONVENTION_NORMAL_BACK | SENC3D_CONVENTION_NORMAL_OUTSIDE);
    251   return 0;
    252 }