star-cpr

Clip 2D meshes with 2D polygons
git clone git://git.meso-star.fr/star-cpr.git
Log | Files | Refs | README | LICENSE

test_scpr_clip.c (8094B)


      1 /* Copyright (C) 2016-2018, 2021-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 #define _POSIX_C_SOURCE 200112L
     17 
     18 #include "scpr.h"
     19 #include "test_scpr_utils.h"
     20 
     21 #include <rsys/math.h>
     22 #include <rsys/stretchy_array.h>
     23 
     24 #include <memory.h>
     25 
     26 static void
     27 dump_obj(FILE* stream, const struct scpr_mesh* mesh)
     28 {
     29   size_t i, n;
     30 
     31   CHK(stream != NULL);
     32   CHK(mesh != NULL);
     33 
     34   OK(scpr_mesh_get_vertices_count(mesh, &n));
     35   FOR_EACH(i, 0, n) {
     36     double pos[2];
     37     OK(scpr_mesh_get_position(mesh, i, pos));
     38     fprintf(stream, "v %g %g 0\n", SPLIT2(pos));
     39   }
     40 
     41   OK(scpr_mesh_get_triangles_count(mesh, &n));
     42   FOR_EACH(i, 0, n) {
     43     size_t ids[3];
     44     OK(scpr_mesh_get_indices(mesh, i, ids));
     45     fprintf(stream, "f %lu %lu %lu\n",
     46       (unsigned long)(ids[0] + 1),
     47       (unsigned long)(ids[1] + 1),
     48       (unsigned long)(ids[2] + 1));
     49   }
     50 }
     51 
     52 static void
     53 test_triangle
     54   (struct scpr_device* dev,
     55    struct mem_allocator* allocator,
     56    struct scpr_mesh* mesh)
     57 {
     58   const double triangle_pos1[] = { 0, 0, 0, 1, 1, 0 };
     59   double triangle_pos2[] = { 0, 0, 0, 1e20, 1e20, 0}; /* To be replaced */
     60   const size_t triangle_ids[] = { 0, 1, 2 };
     61   double** clip_pos;
     62   double range[2];
     63   size_t nverts[] = { 3 };
     64   size_t ncomps = 1;
     65   const double clip_pos0[] = { -1.0, 0.25, 1.0, 0.75, 1, 0.25 };
     66   struct scpr_polygon* poly;
     67   struct polygon_context pctx;
     68   struct mesh_context mctx;
     69   size_t ntris;
     70 
     71   /* Set out-of-range value in triangle_pos2 */
     72   SCPR(device_get_range(dev, range));
     73   triangle_pos2[3] = triangle_pos2[4] = range[1] + 1;
     74 
     75   clip_pos = (double**)MEM_CALLOC(allocator, ncomps, sizeof(*clip_pos));
     76   *clip_pos = (double*)MEM_CALLOC(allocator, nverts[0], 2*sizeof(**clip_pos));
     77   memcpy(*clip_pos, clip_pos0, 2*nverts[0]*sizeof(**clip_pos));
     78 
     79   pctx.coords = clip_pos;
     80   pctx.nverts = nverts;
     81   pctx.ncomps = ncomps;
     82   OK(scpr_polygon_create(dev, &poly));
     83   OK(scpr_polygon_setup_indexed_vertices(poly, ncomps, pget_nverts, pget_pos, &pctx));
     84 
     85   /* Check out-of-range */
     86   mctx.coords = triangle_pos2;
     87   mctx.nverts = 3;
     88   mctx.indices = triangle_ids;
     89   mctx.ntris = 1;
     90   BAD(scpr_mesh_setup_indexed_vertices
     91     (mesh, mctx.ntris, mget_ids, 3, mget_pos, &mctx));
     92 
     93   mctx.coords = triangle_pos1;
     94   OK(scpr_mesh_setup_indexed_vertices
     95     (mesh, mctx.ntris, mget_ids, 3, mget_pos, &mctx));
     96 
     97   BAD(scpr_mesh_clip(NULL, SCPR_OPERATIONS_COUNT__, NULL));
     98   BAD(scpr_mesh_clip(mesh, SCPR_OPERATIONS_COUNT__, NULL));
     99   BAD(scpr_mesh_clip(NULL, SCPR_OPERATIONS_COUNT__, poly));
    100   BAD(scpr_mesh_clip(mesh, SCPR_OPERATIONS_COUNT__, poly));
    101   BAD(scpr_mesh_clip(NULL, SCPR_SUB, NULL));
    102   BAD(scpr_mesh_clip(mesh, SCPR_SUB, NULL));
    103   BAD(scpr_mesh_clip(NULL, SCPR_SUB, poly));
    104   OK(scpr_mesh_clip(mesh, SCPR_SUB, poly));
    105 
    106   /*dump_obj(stdout, mesh);*/
    107 
    108   OK(scpr_mesh_get_triangles_count(mesh, &ntris));
    109   CHK(ntris == 3);
    110 
    111   MEM_RM(allocator, *clip_pos);
    112   MEM_RM(allocator, clip_pos);
    113   OK(scpr_polygon_ref_put(poly));
    114 }
    115 
    116 static void
    117 test_quad
    118   (struct scpr_device* dev,
    119    struct mem_allocator* allocator,
    120    struct scpr_mesh* mesh)
    121 {
    122   const double quad_pos[] = { 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0 };
    123   const size_t quad_ids[] = { 0, 1, 3, 3, 1, 2 };
    124   double** clip_pos;
    125   size_t nverts[] = { 4 };
    126   size_t ncomps = 1;
    127   const double clip_pos0[] = { -0.25, 0.25, -0.25, 0.75, 1.25, 0.75, 1.25, 0.25 };
    128   struct scpr_polygon* poly;
    129   struct polygon_context pctx;
    130   struct mesh_context mctx;
    131 
    132   clip_pos = (double**)MEM_CALLOC(allocator, ncomps, sizeof(*clip_pos));
    133   *clip_pos = (double*)MEM_CALLOC(allocator, nverts[0], 2*sizeof(**clip_pos));
    134   memcpy(*clip_pos, clip_pos0, 2*nverts[0]*sizeof(**clip_pos));
    135 
    136   pctx.coords = clip_pos;
    137   pctx.nverts = nverts;
    138   pctx.ncomps = ncomps;
    139   OK(scpr_polygon_create(dev, &poly));
    140   OK(scpr_polygon_setup_indexed_vertices(poly, ncomps, pget_nverts, pget_pos, &pctx));
    141 
    142   mctx.coords = quad_pos;
    143   mctx.nverts = sizeof(quad_pos)/(2*sizeof(double));
    144   mctx.indices = quad_ids;
    145   mctx.ntris = sizeof(quad_ids)/(3*sizeof(size_t));
    146   OK(scpr_mesh_setup_indexed_vertices
    147     (mesh, mctx.ntris, mget_ids, mctx.nverts, mget_pos, &mctx));
    148 
    149   OK(scpr_mesh_clip(mesh, SCPR_AND, poly));
    150 
    151   /*dump_obj(stdout, mesh);*/
    152 
    153   MEM_RM(allocator, *clip_pos);
    154   MEM_RM(allocator, clip_pos);
    155   OK(scpr_polygon_ref_put(poly));
    156 }
    157 
    158 static void
    159 test_disk
    160   (struct scpr_device* dev,
    161    struct mem_allocator* allocator,
    162    struct scpr_mesh* mesh)
    163 {
    164   double** clip_pos;
    165   size_t nverts[] = { 4 };
    166   size_t ncomps = 1;
    167   const double clip_pos0[]
    168     =  { -1.75, -1.75, 1.75, -1.75, 1.75, 1.75, -1.75, 1.75 };
    169   const size_t ninternal_disks = 10;
    170   const double radius = 2.5;
    171   const double internal_disk_step = radius / (double)ninternal_disks;
    172   const size_t nslices = 64;
    173   struct scpr_polygon* poly;
    174   struct polygon_context pctx;
    175   struct mesh_context mctx;
    176   double* pos = NULL;
    177   size_t* ids = NULL;
    178   size_t i, j;
    179 
    180   clip_pos = (double**)MEM_CALLOC(allocator, ncomps, sizeof(*clip_pos));
    181   *clip_pos = (double*)MEM_CALLOC(allocator, nverts[0], 2*sizeof(**clip_pos));
    182   memcpy(*clip_pos, clip_pos0, 2*nverts[0]*sizeof(**clip_pos));
    183 
    184   FOR_EACH(i, 0, ninternal_disks) {
    185     const double r = (double)(i+1)*internal_disk_step;
    186     FOR_EACH(j, 0, nslices) {
    187       const double theta = (double)j / (double)nslices * 2 * PI;
    188       const double x = r * cos(theta);
    189       const double y = r * sin(theta);
    190       sa_push(pos, x);
    191       sa_push(pos, y);
    192     }
    193   }
    194 
    195   /* Center point */
    196   sa_push(pos, 0.0);
    197   sa_push(pos, 0.0);
    198 
    199   FOR_EACH(i, 0, ninternal_disks-1) {
    200     const size_t offset = (i+1) * nslices;
    201     FOR_EACH(j, 0, nslices) {
    202       const size_t id0 = j + offset;
    203       const size_t id1 = ((j + 1) % nslices) + offset;
    204       const size_t id2 = id0 - nslices;
    205       const size_t id3 = id1 - nslices;
    206 
    207       sa_push(ids, id0);
    208       sa_push(ids, id2);
    209       sa_push(ids, id1);
    210 
    211       sa_push(ids, id1);
    212       sa_push(ids, id2);
    213       sa_push(ids, id3);
    214     }
    215   }
    216 
    217   /* Center triangles */
    218   FOR_EACH(j, 0, nslices) {
    219     const size_t id0 = j;
    220     const size_t id1 = (j + 1) % nslices;
    221     const size_t id2 = sa_size(pos)/2 - 1;
    222 
    223     sa_push(ids, id0);
    224     sa_push(ids, id2);
    225     sa_push(ids, id1);
    226   }
    227 
    228   pctx.coords = clip_pos;
    229   pctx.nverts = nverts;
    230   pctx.ncomps = ncomps;
    231   OK(scpr_polygon_create(dev, &poly));
    232   OK(scpr_polygon_setup_indexed_vertices(poly, ncomps, pget_nverts, pget_pos, &pctx));
    233 
    234   mctx.coords = pos;
    235   mctx.nverts = sa_size(pos)/2;
    236   mctx.indices = ids;
    237   mctx.ntris = sa_size(ids)/3;
    238   OK(scpr_mesh_setup_indexed_vertices
    239     (mesh, mctx.ntris, mget_ids, mctx.nverts, mget_pos, &mctx));
    240 
    241   OK(scpr_mesh_clip(mesh, SCPR_SUB, poly));
    242 
    243   dump_obj(stdout, mesh);
    244 
    245   MEM_RM(allocator, *clip_pos);
    246   MEM_RM(allocator, clip_pos);
    247   sa_release(pos);
    248   sa_release(ids);
    249   OK(scpr_polygon_ref_put(poly));
    250 }
    251 
    252 int
    253 main(int argc, char** argv)
    254 {
    255   struct mem_allocator allocator;
    256   struct scpr_device_create_args args = SCPR_DEVICE_CREATE_ARGS_DEFAULT;
    257   struct scpr_device* dev;
    258   struct scpr_mesh* mesh;
    259   (void)argc, (void)argv;
    260 
    261   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
    262 
    263   args.allocator = &allocator;
    264   OK(scpr_device_create(&args, &dev));
    265   OK(scpr_mesh_create(dev, &mesh));
    266 
    267   test_triangle(dev, &allocator, mesh);
    268   test_quad(dev, &allocator, mesh);
    269   test_disk(dev, &allocator, mesh);
    270 
    271   OK(scpr_mesh_ref_put(mesh));
    272   OK(scpr_device_ref_put(dev));
    273 
    274   check_memory_allocator(&allocator);
    275   mem_shutdown_proxy_allocator(&allocator);
    276   CHK(mem_allocated_size() == 0);
    277   return 0;
    278 }
    279