star-2d

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

test_s2d_scene_view.c (18198B)


      1 /* Copyright (C) 2016-2021, 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 "s2d.h"
     17 #include "test_s2d_utils.h"
     18 
     19 #include <rsys/float2.h>
     20 
     21 #include <string.h>
     22 
     23 static void
     24 test_miscellaneous
     25   (struct s2d_device* dev,
     26    struct s2d_shape* square,
     27    struct s2d_shape* line)
     28 {
     29   struct s2d_scene* scn;
     30   struct s2d_scene_view* scnview;
     31   int mask;
     32 
     33   CHK(s2d_scene_create(dev, &scn) == RES_OK);
     34   CHK(s2d_scene_attach_shape(scn, square) == RES_OK);
     35   CHK(s2d_scene_attach_shape(scn, line) == RES_OK);
     36 
     37   CHK(s2d_scene_view_create(NULL, 0, NULL) == RES_BAD_ARG);
     38   CHK(s2d_scene_view_create(scn, 0, NULL) == RES_BAD_ARG);
     39   CHK(s2d_scene_view_create(NULL, S2D_SAMPLE, NULL) == RES_BAD_ARG);
     40   CHK(s2d_scene_view_create(scn, S2D_SAMPLE, NULL) == RES_BAD_ARG);
     41   CHK(s2d_scene_view_create(NULL, 0, &scnview) == RES_BAD_ARG);
     42   CHK(s2d_scene_view_create(scn, 0, &scnview) == RES_BAD_ARG);
     43   CHK(s2d_scene_view_create(NULL, S2D_SAMPLE, &scnview) == RES_BAD_ARG);
     44   CHK(s2d_scene_view_create(scn, S2D_SAMPLE, &scnview) == RES_OK);
     45 
     46   CHK(s2d_scene_view_get_mask(NULL, NULL) == RES_BAD_ARG);
     47   CHK(s2d_scene_view_get_mask(scnview, NULL) == RES_BAD_ARG);
     48   CHK(s2d_scene_view_get_mask(NULL, &mask) == RES_BAD_ARG);
     49   CHK(s2d_scene_view_get_mask(scnview, &mask) == RES_OK);
     50   CHK(mask == S2D_SAMPLE);
     51 
     52   CHK(s2d_scene_view_ref_get(NULL) == RES_BAD_ARG);
     53   CHK(s2d_scene_view_ref_get(scnview) == RES_OK);
     54   CHK(s2d_scene_view_ref_put(NULL) == RES_BAD_ARG);
     55   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
     56   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
     57 
     58   CHK(s2d_scene_view_create(scn, S2D_TRACE|S2D_GET_PRIMITIVE, &scnview) == RES_OK);
     59   CHK(s2d_scene_view_get_mask(scnview, &mask) == RES_OK);
     60   CHK((mask & S2D_TRACE) == S2D_TRACE);
     61   CHK((mask & S2D_GET_PRIMITIVE) == S2D_GET_PRIMITIVE);
     62   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
     63 
     64   CHK(s2d_scene_view_create(scn, S2D_SAMPLE|S2D_GET_PRIMITIVE, &scnview) == RES_OK);
     65   CHK(s2d_scene_view_get_mask(scnview, &mask) == RES_OK);
     66   CHK((mask & S2D_SAMPLE) == S2D_SAMPLE);
     67   CHK((mask & S2D_GET_PRIMITIVE) == S2D_GET_PRIMITIVE);
     68   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
     69 
     70   CHK(s2d_scene_ref_put(scn) == RES_OK);
     71 }
     72 
     73 static void
     74 test_trace_ray
     75   (struct s2d_device* dev,
     76    struct s2d_shape* square,
     77    struct s2d_shape* line)
     78 {
     79   struct s2d_scene* scn;
     80   struct s2d_scene* scn2;
     81   struct s2d_scene_view* scnview;
     82   struct s2d_scene_view* scnview2;
     83   struct s2d_hit hit, hit2;
     84   float org[2], dir[2], range[2];
     85   unsigned isquare;
     86   unsigned iline;
     87 
     88   CHK(s2d_shape_get_id(square, &isquare) == RES_OK);
     89   CHK(s2d_shape_get_id(line, &iline) == RES_OK);
     90 
     91   CHK(s2d_scene_create(dev, &scn) == RES_OK);
     92   CHK(s2d_scene_create(dev, &scn2) == RES_OK);
     93   CHK(s2d_scene_attach_shape(scn, line) == RES_OK);
     94   CHK(s2d_scene_attach_shape(scn, square) == RES_OK);
     95   CHK(s2d_scene_attach_shape(scn2, square) == RES_OK);
     96   CHK(s2d_scene_attach_shape(scn2, line) == RES_OK);
     97 
     98   CHK(s2d_scene_view_create(scn, S2D_SAMPLE|S2D_GET_PRIMITIVE, &scnview) == RES_OK);
     99 
    100   f2(org, 10.f, 9.75f);
    101   f2(dir, 0.f, 1.f);
    102   f2(range, 0.f, FLT_MAX);
    103   CHK(s2d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit) == RES_BAD_OP);
    104 
    105   CHK(s2d_scene_view_create(scn, S2D_TRACE, &scnview2) == RES_OK);
    106   CHK(s2d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit) == RES_OK);
    107   CHK(S2D_HIT_NONE(&hit) == 0);
    108   CHK(hit.prim.geom_id == iline);
    109   CHK(hit.prim.prim_id == 0);
    110 
    111   f2(dir, 0.f, -1.f);
    112   CHK(s2d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit) == RES_OK);
    113   CHK(S2D_HIT_NONE(&hit) == 0);
    114   CHK(hit.prim.geom_id == isquare);
    115   CHK(hit.prim.prim_id == 0);
    116   f2(dir, 0.f, 1.f);
    117 
    118   CHK(s2d_shape_enable(line, 0) == RES_OK);
    119   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    120   CHK(s2d_scene_view_create(scn, S2D_TRACE, &scnview) == RES_OK);
    121 
    122   CHK(s2d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit) == RES_OK);
    123   CHK(S2D_HIT_NONE(&hit) == 0);
    124   CHK(hit.prim.geom_id == iline);
    125   CHK(hit.prim.prim_id == 0);
    126 
    127   CHK(s2d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit) == RES_OK);
    128   CHK(S2D_HIT_NONE(&hit) == 0);
    129   CHK(hit.prim.geom_id == isquare);
    130   CHK(hit.prim.prim_id == 2);
    131 
    132   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    133   CHK(s2d_scene_view_ref_put(scnview2) == RES_OK);
    134   CHK(s2d_shape_enable(line, 1) == RES_OK);
    135 
    136   CHK(s2d_scene_view_create(scn, S2D_TRACE, &scnview) == RES_OK);
    137   CHK(s2d_scene_view_create(scn2, S2D_TRACE, &scnview2) == RES_OK);
    138 
    139   CHK(s2d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit) == RES_OK);
    140   CHK(s2d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit2) == RES_OK);
    141   CHK(f2_eq(hit.normal, hit2.normal));
    142   CHK(hit.u == hit2.u);
    143   CHK(hit.distance == hit2.distance);
    144   CHK(S2D_PRIMITIVE_EQ(&hit.prim, &hit2.prim) == 1);
    145   CHK(hit.prim.geom_id == iline);
    146   CHK(hit.prim.prim_id == 0);
    147 
    148   CHK(s2d_scene_detach_shape(scn2, line) == RES_OK);
    149   CHK(s2d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit2) == RES_OK);
    150   CHK(f2_eq(hit.normal, hit2.normal));
    151   CHK(hit.u == hit2.u);
    152   CHK(hit.distance == hit2.distance);
    153   CHK(S2D_PRIMITIVE_EQ(&hit.prim, &hit2.prim) == 1);
    154 
    155   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    156   CHK(s2d_scene_view_ref_put(scnview2) == RES_OK);
    157 
    158   CHK(s2d_scene_view_create(scn, S2D_TRACE, &scnview) == RES_OK);
    159   CHK(s2d_scene_view_create(scn2, S2D_TRACE, &scnview2) == RES_OK);
    160 
    161   CHK(s2d_scene_view_trace_ray(scnview, org, dir, range, NULL, &hit) == RES_OK);
    162   CHK(f2_eq(hit.normal, hit2.normal));
    163   CHK(hit.u == hit2.u);
    164   CHK(hit.distance == hit2.distance);
    165   CHK(S2D_PRIMITIVE_EQ(&hit.prim, &hit2.prim) == 1);
    166   CHK(hit.prim.geom_id == iline);
    167   CHK(hit.prim.prim_id == 0);
    168 
    169   CHK(s2d_scene_view_trace_ray(scnview2, org, dir, range, NULL, &hit2) == RES_OK);
    170   CHK(hit2.prim.geom_id == isquare);
    171   CHK(hit2.prim.prim_id == 2);
    172 
    173   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    174   CHK(s2d_scene_view_ref_put(scnview2) == RES_OK);
    175 
    176   CHK(s2d_scene_ref_put(scn) == RES_OK);
    177   CHK(s2d_scene_ref_put(scn2) == RES_OK);
    178 }
    179 
    180 static void
    181 test_sample
    182   (struct s2d_device* dev,
    183    struct s2d_shape* square,
    184    struct s2d_shape* line)
    185 {
    186   #define NSAMPS 512
    187   struct s2d_scene* scn;
    188   struct s2d_scene_view* scnview;
    189   struct s2d_primitive prims[NSAMPS];
    190   float u, v, s;
    191   unsigned isquare;
    192   unsigned iline;
    193   int nsamps_square;
    194   int nsamps_line;
    195   int i;
    196 
    197   CHK(s2d_scene_create(dev, &scn) == RES_OK);
    198   CHK(s2d_scene_attach_shape(scn, square) == RES_OK);
    199   CHK(s2d_scene_attach_shape(scn, line) == RES_OK);
    200   CHK(s2d_shape_get_id(square, &isquare) == RES_OK);
    201   CHK(s2d_shape_get_id(line, &iline) == RES_OK);
    202 
    203   CHK(s2d_scene_view_create(scn, S2D_TRACE, &scnview) == RES_OK);
    204   CHK(s2d_scene_view_sample(scnview, 0.f, 0.f, &prims[0], &s) == RES_BAD_OP);
    205   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    206 
    207   CHK(s2d_scene_view_create(scn, S2D_SAMPLE, &scnview) == RES_OK);
    208   CHK(s2d_scene_view_sample(scnview, 0.f, 0.f, &prims[0], &s) == RES_OK);
    209   CHK(prims[0].geom_id == isquare || prims[0].geom_id == iline);
    210 
    211   nsamps_square = 0;
    212   nsamps_line = 0;
    213   srand(0);
    214   FOR_EACH(i, 0, NSAMPS) {
    215     u = rand_canonic(), v = rand_canonic();
    216     CHK(s2d_scene_view_sample(scnview, u, v, &prims[i], &s) == RES_OK);
    217     if(prims[i].geom_id == isquare) {
    218       ++nsamps_square;
    219     } else {
    220       CHK(prims[i].geom_id == iline);
    221       ++nsamps_line;
    222     }
    223   }
    224   CHK(nsamps_square != 0);
    225   CHK(nsamps_line != 0);
    226 
    227   CHK(s2d_shape_enable(square, 0) == RES_OK);
    228   srand(0);
    229   FOR_EACH(i, 0, NSAMPS) {
    230     struct s2d_primitive prim;
    231     u = rand_canonic(), v = rand_canonic();
    232     CHK(s2d_scene_view_sample(scnview, u, v, &prim, &s) == RES_OK);
    233     CHK(S2D_PRIMITIVE_EQ(&prim, &prims[i]) == 1);
    234   }
    235 
    236   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    237   CHK(s2d_scene_view_create(scn, S2D_SAMPLE, &scnview) == RES_OK);
    238 
    239   srand(0);
    240   FOR_EACH(i, 0, NSAMPS) {
    241     u = rand_canonic(), v = rand_canonic();
    242     CHK(s2d_scene_view_sample(scnview, u, v, &prims[i], &s) == RES_OK);
    243     CHK(prims[i].geom_id == iline);
    244   }
    245 
    246   CHK(s2d_shape_enable(square, 1) == RES_OK);
    247   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    248   CHK(s2d_scene_ref_put(scn) == RES_OK);
    249 }
    250 
    251 static void
    252 test_get_primitive
    253   (struct s2d_device* dev,
    254    struct s2d_shape* square,
    255    struct s2d_shape* line)
    256 {
    257   struct s2d_scene* scn;
    258   struct s2d_scene_view* scnview;
    259   struct s2d_primitive prim;
    260   size_t nprims;
    261   unsigned i;
    262   unsigned isquare;
    263   unsigned iline;
    264   int square_prims[4];
    265   int line_prims;
    266 
    267   CHK(s2d_scene_create(dev, &scn) == RES_OK);
    268   CHK(s2d_scene_attach_shape(scn, square) == RES_OK);
    269   CHK(s2d_scene_attach_shape(scn, line) == RES_OK);
    270   CHK(s2d_shape_get_id(square, &isquare) == RES_OK);
    271   CHK(s2d_shape_get_id(line, &iline) == RES_OK);
    272 
    273   CHK(s2d_scene_view_create(scn, S2D_TRACE, &scnview) == RES_OK);
    274   CHK(s2d_scene_view_get_primitive(scnview, 0, &prim) == RES_BAD_OP);
    275   CHK(s2d_scene_view_primitives_count(scnview, &nprims) == RES_OK);
    276   CHK(nprims == 5);
    277   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    278 
    279   CHK(s2d_scene_view_create(scn, S2D_GET_PRIMITIVE, &scnview) == RES_OK);
    280   CHK(s2d_scene_view_primitives_count(scnview, &nprims) == RES_OK);
    281   CHK(nprims == 5);
    282 
    283   memset(square_prims, 0, sizeof(square_prims));
    284   line_prims = 0;
    285   FOR_EACH(i, 0, nprims) {
    286     CHK(s2d_scene_view_get_primitive(scnview, i, &prim) == RES_OK);
    287     CHK(prim.scene_prim_id == i);
    288     if(prim.geom_id == isquare) {
    289       square_prims[prim.prim_id] = 1;
    290     } else {
    291       CHK(prim.geom_id == iline);
    292       line_prims = 1;
    293     }
    294   }
    295   FOR_EACH(i, 0, 4) CHK(square_prims[i]);
    296   CHK(line_prims);
    297 
    298   CHK(s2d_scene_detach_shape(scn, square) == RES_OK);
    299   CHK(s2d_scene_view_primitives_count(scnview, &nprims) == RES_OK);
    300   CHK(nprims == 5);
    301   memset(square_prims, 0, sizeof(square_prims));
    302   line_prims = 0;
    303   FOR_EACH(i, 0, nprims) {
    304     CHK(s2d_scene_view_get_primitive(scnview, i, &prim) == RES_OK);
    305     CHK(prim.scene_prim_id == i);
    306     if(prim.geom_id == isquare) {
    307       square_prims[prim.prim_id] = 1;
    308     } else {
    309       CHK(prim.geom_id == iline);
    310       line_prims = 1;
    311     }
    312   }
    313   FOR_EACH(i, 0, 4) CHK(square_prims[i]);
    314   CHK(line_prims);
    315 
    316   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    317   CHK(s2d_scene_view_create(scn, S2D_GET_PRIMITIVE, &scnview) == RES_OK);
    318   CHK(s2d_scene_view_primitives_count(scnview, &nprims) == RES_OK);
    319   CHK(nprims == 1);
    320   line_prims = 0;
    321   CHK(s2d_scene_view_get_primitive(scnview, 0, &prim) == RES_OK);
    322   CHK(prim.scene_prim_id == 0);
    323   CHK(prim.geom_id == iline);
    324 
    325   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    326   CHK(s2d_scene_attach_shape(scn, square) == RES_OK);
    327   CHK(s2d_shape_enable(line, 0) == RES_OK);
    328   CHK(s2d_scene_view_create(scn, S2D_GET_PRIMITIVE, &scnview) == RES_OK);
    329   CHK(s2d_scene_view_primitives_count(scnview, &nprims) == RES_OK);
    330   CHK(nprims == 4);
    331   memset(square_prims, 0, sizeof(square_prims));
    332   FOR_EACH(i, 0, nprims) {
    333     CHK(s2d_scene_view_get_primitive(scnview, i, &prim) == RES_OK);
    334     CHK(prim.scene_prim_id == i);
    335     CHK(prim.geom_id == isquare);
    336     square_prims[prim.prim_id] = 1;
    337   }
    338   FOR_EACH(i, 0, 4) CHK(square_prims[i]);
    339 
    340   CHK(s2d_shape_enable(line, 1) == RES_OK);
    341   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    342   CHK(s2d_scene_ref_put(scn) == RES_OK);
    343 }
    344 
    345 static void
    346 test_contour_length
    347   (struct s2d_device* dev,
    348    struct s2d_shape* square,
    349    struct s2d_shape* line)
    350 {
    351   struct s2d_scene* scn;
    352   struct s2d_scene_view* scnview;
    353   float length;
    354 
    355   CHK(s2d_scene_create(dev, &scn) == RES_OK);
    356   CHK(s2d_scene_attach_shape(scn, square) == RES_OK);
    357   CHK(s2d_scene_attach_shape(scn, line) == RES_OK);
    358 
    359   CHK(s2d_scene_view_create(scn, S2D_GET_PRIMITIVE, &scnview) == RES_OK);
    360   CHK(s2d_scene_view_compute_contour_length(NULL, NULL) == RES_BAD_ARG);
    361   CHK(s2d_scene_view_compute_contour_length(scnview, NULL) == RES_BAD_ARG);
    362   CHK(s2d_scene_view_compute_contour_length(NULL, &length) == RES_BAD_ARG);
    363   CHK(s2d_scene_view_compute_contour_length(scnview, &length) == RES_OK);
    364   CHK(eq_epsf(length, 10.f, 1.e-6f));
    365 
    366   CHK(s2d_shape_enable(line, 0) == RES_OK);
    367   CHK(s2d_scene_view_compute_contour_length(scnview, &length) == RES_OK);
    368   CHK(eq_epsf(length, 10.f, 1.e-6f));
    369 
    370   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    371   CHK(s2d_scene_view_create(scn, S2D_GET_PRIMITIVE, &scnview) == RES_OK);
    372   CHK(s2d_scene_view_compute_contour_length(scnview, &length) == RES_OK);
    373   CHK(eq_epsf(length, 8.f, 1.e-6f));
    374 
    375   CHK(s2d_shape_enable(line, 1) == RES_OK);
    376   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    377 
    378   CHK(s2d_scene_ref_put(scn) == RES_OK);
    379 }
    380 
    381 static void
    382 test_area
    383   (struct s2d_device* dev, struct s2d_shape* square)
    384 {
    385   struct s2d_scene* scn;
    386   struct s2d_scene_view* scnview;
    387   float area;
    388 
    389   CHK(s2d_scene_create(dev, &scn) == RES_OK);
    390   CHK(s2d_scene_attach_shape(scn, square) == RES_OK);
    391 
    392   CHK(s2d_scene_view_create(scn, S2D_GET_PRIMITIVE, &scnview) == RES_OK);
    393   CHK(s2d_scene_view_compute_area(NULL, NULL) == RES_BAD_ARG);
    394   CHK(s2d_scene_view_compute_area(scnview, NULL) == RES_BAD_ARG);
    395   CHK(s2d_scene_view_compute_area(NULL, &area) == RES_BAD_ARG);
    396   CHK(s2d_scene_view_compute_area(scnview, &area) == RES_OK);
    397   CHK(eq_epsf(area, 4.f, 1.e-6f));
    398 
    399   CHK(s2d_shape_flip_contour(square) == RES_OK);
    400   CHK(s2d_scene_view_compute_area(scnview, &area) == RES_OK);
    401   CHK(eq_epsf(area, 4.f, 1.e-6f));
    402 
    403   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    404   CHK(s2d_scene_view_create(scn, S2D_GET_PRIMITIVE, &scnview) == RES_OK);
    405   CHK(s2d_scene_view_compute_area(scnview, &area) == RES_OK);
    406   CHK(eq_epsf(area, -4.f, 1.e-6f));
    407 
    408   CHK(s2d_shape_flip_contour(square) == RES_OK);
    409   CHK(s2d_shape_enable(square, 0) == RES_OK);
    410   CHK(s2d_scene_view_compute_area(scnview, &area) == RES_OK);
    411   CHK(eq_epsf(area, -4.f, 1.e-6f));
    412 
    413   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    414   CHK(s2d_scene_view_create(scn, S2D_GET_PRIMITIVE, &scnview) == RES_OK);
    415   CHK(s2d_scene_view_compute_area(scnview, &area) == RES_OK);
    416   CHK(area == 0.f);
    417 
    418   CHK(s2d_shape_enable(square, 1) == RES_OK);
    419 
    420   CHK(s2d_scene_ref_put(scn) == RES_OK);
    421   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    422 }
    423 
    424 static void
    425 test_aabb
    426   (struct s2d_device* dev, struct s2d_shape* square, struct s2d_shape* line)
    427 {
    428   struct s2d_scene* scn;
    429   struct s2d_scene_view* scnview;
    430   float lower[2];
    431   float upper[2];
    432 
    433   CHK(s2d_scene_create(dev, &scn) == RES_OK);
    434   CHK(s2d_scene_attach_shape(scn, square) == RES_OK);
    435   CHK(s2d_scene_attach_shape(scn, line) == RES_OK);
    436 
    437   CHK(s2d_scene_view_create(scn, S2D_GET_PRIMITIVE, &scnview) == RES_OK);
    438   CHK(s2d_scene_view_get_aabb(NULL, NULL, NULL) == RES_BAD_ARG);
    439   CHK(s2d_scene_view_get_aabb(scnview, NULL, NULL) == RES_BAD_ARG);
    440   CHK(s2d_scene_view_get_aabb(NULL, lower, NULL) == RES_BAD_ARG);
    441   CHK(s2d_scene_view_get_aabb(scnview, lower, NULL) == RES_BAD_ARG);
    442   CHK(s2d_scene_view_get_aabb(NULL, lower, upper) == RES_BAD_ARG);
    443   CHK(s2d_scene_view_get_aabb(scnview, lower, upper) == RES_OK);
    444   CHK(lower[0] == 9.f && upper[0] == 11.f);
    445   CHK(lower[1] == 9.f && upper[1] == 11.f);
    446 
    447   CHK(s2d_shape_enable(square, 0) == RES_OK);
    448   CHK(s2d_scene_view_get_aabb(scnview, lower, upper) == RES_OK);
    449   CHK(lower[0] == 9.f && upper[0] == 11.f);
    450   CHK(lower[1] == 9.f && upper[1] == 11.f);
    451 
    452   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    453   CHK(s2d_scene_view_create(scn, S2D_GET_PRIMITIVE, &scnview) == RES_OK);
    454   CHK(s2d_scene_view_get_aabb(scnview, lower, upper) == RES_OK);
    455   CHK(lower[0] == 9.f && upper[0] == 11.f);
    456   CHK(lower[1] == 10.f && upper[1] == 10.f);
    457 
    458   CHK(s2d_scene_detach_shape(scn, line) == RES_OK);
    459   CHK(s2d_scene_view_get_aabb(scnview, lower, upper) == RES_OK);
    460   CHK(lower[0] == 9.f && upper[0] == 11.f);
    461   CHK(lower[1] == 10.f && upper[1] == 10.f);
    462 
    463   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    464   CHK(s2d_scene_view_create(scn, S2D_GET_PRIMITIVE, &scnview) == RES_OK);
    465   CHK(s2d_scene_view_get_aabb(scnview, lower, upper) == RES_OK);
    466   CHK(lower[0] > upper[0]);
    467   CHK(lower[1] > upper[1]);
    468 
    469   CHK(s2d_shape_enable(square, 1) == RES_OK);
    470 
    471   CHK(s2d_scene_ref_put(scn) == RES_OK);
    472   CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
    473 }
    474 
    475 /*******************************************************************************
    476  * Main test function
    477  ******************************************************************************/
    478 int
    479 main(int argc, char** argv)
    480 {
    481   struct mem_allocator allocator;
    482   struct s2d_device* dev;
    483   struct s2d_shape* square;
    484   struct s2d_shape* line;
    485   struct s2d_vertex_data vdata;
    486   (void)argc, (void)argv;
    487 
    488   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
    489 
    490   CHK(s2d_device_create(NULL, &allocator, 1, &dev) == RES_OK);
    491 
    492   vdata.type = S2D_FLOAT2;
    493   vdata.usage = S2D_POSITION;
    494   vdata.get = line_segments_get_position;
    495 
    496   CHK(s2d_shape_create_line_segments(dev, &square) == RES_OK);
    497   CHK(s2d_line_segments_setup_indexed_vertices(square, square_nsegs,
    498     line_segments_get_ids, square_nverts, &vdata, 1, (void*)&square_desc)
    499     == RES_OK);
    500 
    501   CHK(s2d_shape_create_line_segments(dev, &line) == RES_OK);
    502   CHK(s2d_line_segments_setup_indexed_vertices(line, line_nsegs,
    503     line_segments_get_ids, line_nverts, &vdata, 1, (void*)&line_desc)
    504     == RES_OK);
    505 
    506   test_miscellaneous(dev, square, line);
    507   test_trace_ray(dev, square, line);
    508   test_sample(dev, square, line);
    509   test_get_primitive(dev, square, line);
    510   test_contour_length(dev, square, line);
    511   test_area(dev, square);
    512   test_aabb(dev, square, line);
    513 
    514   CHK(s2d_shape_ref_put(square) == RES_OK);
    515   CHK(s2d_shape_ref_put(line) == RES_OK);
    516   CHK(s2d_device_ref_put(dev) == RES_OK);
    517 
    518   check_memory_allocator(&allocator);
    519   mem_shutdown_proxy_allocator(&allocator);
    520   CHK(mem_allocated_size() == 0);
    521   return 0;
    522 }
    523