solstice-anim

Geometry animation library of the solstice app
git clone git://git.meso-star.com/solstice-anim.git
Log | Files | Refs | README | LICENSE

test_sanim_visit.c (17173B)


      1 /* Copyright (C) 2018-2026 |Méso|Star> (contact@meso-star.com)
      2  * Copyright (C) 2016-2018 CNRS
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     16 
     17 #include "sanim.h"
     18 #include "test_sanim_utils.h"
     19 
     20 #include <rsys/double33.h>
     21 
     22 #include <rsys/hash_table.h>
     23 struct transform { double transform[12]; };
     24 #define HTABLE_NAME transforms
     25 #define HTABLE_KEY const struct sanim_node *
     26 #define HTABLE_DATA struct transform
     27 #include <rsys/hash_table.h>
     28 
     29 static res_T
     30 store_transform(const struct sanim_node* n, const double transform[12], void* data) {
     31   struct htable_transforms* transforms = data;
     32   struct transform tr;
     33   int i;
     34   for (i = 0; i < 12; i++) tr.transform[i] = transform[i];
     35   return htable_transforms_set(transforms, &n, &tr);
     36 }
     37 
     38 static void
     39 check_visit
     40   (struct mem_allocator allocator,
     41    double in_dir[3],
     42    struct my_type *root,
     43    struct my_type *pivot,
     44    struct my_type *leaf)
     45 {
     46   struct htable_transforms transforms;
     47   struct transform *tr;
     48   const struct sanim_node *key;
     49   double transform[12];
     50 
     51   htable_transforms_init(&allocator, &transforms);
     52   CHK(sanim_node_visit_tree(
     53     &root->node, in_dir, &transforms, store_transform) == RES_OK);
     54   CHK(htable_transforms_size_get(&transforms) == 3);
     55   key = &leaf->node;
     56   tr = htable_transforms_find(&transforms, &key);
     57   CHK(tr != NULL);
     58   CHK(my_type_solve_pivot(pivot, in_dir) == RES_OK);
     59   CHK(my_type_get_transform(leaf, transform) == RES_OK);
     60   key = &leaf->node;
     61   tr = htable_transforms_find(&transforms, &key);
     62   CHK(tr != NULL);
     63   d34_eq_eps(tr->transform, transform, 1e-10);
     64   CHK(my_type_get_transform(pivot, transform) == RES_OK);
     65   key = &pivot->node;
     66   tr = htable_transforms_find(&transforms, &key);
     67   CHK(tr != NULL);
     68   d34_eq_eps(tr->transform, transform, 1e-10);
     69   CHK(my_type_get_transform(root, transform) == RES_OK);
     70   key = &root->node;
     71   tr = htable_transforms_find(&transforms, &key);
     72   CHK(tr != NULL);
     73   d34_eq_eps(tr->transform, transform, 1e-10);
     74   htable_transforms_release(&transforms);
     75 }
     76 
     77 int
     78 main(int argc, char** argv)
     79 {
     80   struct mem_allocator allocator;
     81   struct my_type *t1, *t2, *t3, *target;
     82   struct sanim_pivot pivot = SANIM_PIVOT_NULL;
     83   struct sanim_tracking tracking = SANIM_TRACKING_NULL;
     84   double transl[3], rot[3], in_dir[3], tmp[3];
     85   (void) argc, (void) argv;
     86 
     87   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
     88 
     89   /*
     90   * 1 axis pivots
     91   * (in/out dirs can be off the YZ plane)
     92   */
     93 
     94   /* 1 axis tracking sun */
     95 
     96   tracking.policy = TRACKING_SUN;
     97   pivot.type = PIVOT_SINGLE_AXIS;
     98   d3(pivot.data.pivot1.ref_normal, 0, 0, 1);
     99 
    100   /* ref_normal not in the YZ plane */
    101   CHK(my_type_create(&allocator, &t1) == RES_OK);
    102   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    103   CHK(my_type_create(&allocator, &t3) == RES_OK);
    104 
    105   CHK(my_type_add_child(t1, t2) == RES_OK);
    106   CHK(my_type_add_child(t2, t3) == RES_OK);
    107 
    108   d3_splat(transl, +1);
    109   d3(rot, 0, 0, PI / 2);
    110   CHK(my_type_set_translation(t1, transl) == RES_OK);
    111   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    112   CHK(my_type_set_translation(t2, transl) == RES_OK);
    113   CHK(my_type_set_translation(t3, transl) == RES_OK);
    114   
    115   d3(in_dir, 1, 0.2, -1);
    116   check_visit(allocator, in_dir, t1, t2, t3);
    117 
    118   CHK(my_type_ref_put(t1) == RES_OK);
    119   CHK(my_type_ref_put(t2) == RES_OK);
    120   CHK(my_type_ref_put(t3) == RES_OK);
    121 
    122   /* 1 axis tracking with a fixed output dir */
    123   
    124   tracking.policy = TRACKING_OUT_DIR;
    125   pivot.type = PIVOT_SINGLE_AXIS;
    126   d3(pivot.data.pivot1.ref_normal, 0, 0, 1);
    127   d3(tracking.data.out_dir.u, 1, 0, 1);
    128 
    129   CHK(my_type_create(&allocator, &t1) == RES_OK);
    130   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    131   CHK(my_type_create(&allocator, &t3) == RES_OK);
    132 
    133   CHK(my_type_add_child(t1, t2) == RES_OK);
    134   CHK(my_type_add_child(t2, t3) == RES_OK);
    135 
    136   CHK(my_type_set_translation(t1, transl) == RES_OK);
    137   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    138   CHK(my_type_set_translation(t2, transl) == RES_OK);
    139   CHK(my_type_set_translation(t3, transl) == RES_OK);
    140 
    141   d3(in_dir, 1, -0.3, -1);
    142   check_visit(allocator, in_dir, t1, t2, t3);
    143 
    144   CHK(my_type_ref_put(t1) == RES_OK);
    145   CHK(my_type_ref_put(t2) == RES_OK);
    146   CHK(my_type_ref_put(t3) == RES_OK);
    147 
    148   /* 1 axis tracking a target point */
    149 
    150   tracking.policy = TRACKING_POINT;
    151   pivot.type = PIVOT_SINGLE_AXIS;
    152   d3(pivot.data.pivot1.ref_normal, 0, 0, 1);
    153   d3(pivot.data.pivot1.ref_point, 0, 0, 0);
    154   d3(tracking.data.point.target, 0, 0, 30);
    155   tracking.data.point.target_is_local = 1;
    156 
    157   CHK(my_type_create(&allocator, &t1) == RES_OK);
    158   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    159   CHK(my_type_create(&allocator, &t3) == RES_OK);
    160 
    161   CHK(my_type_add_child(t1, t2) == RES_OK);
    162   CHK(my_type_add_child(t2, t3) == RES_OK);
    163 
    164   CHK(my_type_set_translation(t1, transl) == RES_OK);
    165   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    166   CHK(my_type_set_translation(t2, transl) == RES_OK);
    167   CHK(my_type_set_translation(t3, transl) == RES_OK);
    168 
    169   d3(in_dir, 1, 0.1, 0);
    170   check_visit(allocator, in_dir, t1, t2, t3);
    171 
    172   CHK(my_type_ref_put(t1) == RES_OK);
    173   CHK(my_type_ref_put(t2) == RES_OK);
    174   CHK(my_type_ref_put(t3) == RES_OK);
    175 
    176   tracking.policy = TRACKING_POINT;
    177   pivot.type = PIVOT_SINGLE_AXIS;
    178   d3(pivot.data.pivot1.ref_normal, 0, 0, 1);
    179   d3(pivot.data.pivot1.ref_point, 0, 0, 10 * sqrt(2));
    180   d3(tracking.data.point.target, 0, 10, 30);
    181   tracking.data.point.target_is_local = 1;
    182 
    183   CHK(my_type_create(&allocator, &t1) == RES_OK);
    184   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    185   CHK(my_type_create(&allocator, &t3) == RES_OK);
    186 
    187   CHK(my_type_add_child(t1, t2) == RES_OK);
    188   CHK(my_type_add_child(t2, t3) == RES_OK);
    189 
    190   CHK(my_type_set_translation(t1, transl) == RES_OK);
    191   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    192   CHK(my_type_set_translation(t2, transl) == RES_OK);
    193   CHK(my_type_set_translation(t3, transl) == RES_OK);
    194 
    195   d3(in_dir, 1, 0.1, 0);
    196   check_visit(allocator, in_dir, t1, t2, t3);
    197 
    198   CHK(my_type_ref_put(t1) == RES_OK);
    199   CHK(my_type_ref_put(t2) == RES_OK);
    200   CHK(my_type_ref_put(t3) == RES_OK);
    201 
    202   /* same 1 axis tracking with a non-local target point */
    203 
    204   tracking.policy = TRACKING_POINT;
    205   pivot.type = PIVOT_SINGLE_AXIS;
    206   d3(pivot.data.pivot1.ref_normal, 0, 0, 1);
    207   d3(pivot.data.pivot1.ref_point, 0, 0, 10 * sqrt(2));
    208   d3(tracking.data.point.target, -10, 2, 32);
    209   tracking.data.point.target_is_local = 0;
    210 
    211   CHK(my_type_create(&allocator, &t1) == RES_OK);
    212   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    213   CHK(my_type_create(&allocator, &t3) == RES_OK);
    214 
    215   CHK(my_type_add_child(t1, t2) == RES_OK);
    216   CHK(my_type_add_child(t2, t3) == RES_OK);
    217 
    218   CHK(my_type_set_translation(t1, transl) == RES_OK);
    219   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    220   CHK(my_type_set_translation(t2, transl) == RES_OK);
    221   CHK(my_type_set_translation(t3, transl) == RES_OK);
    222 
    223   d3(in_dir, 1, -0.5, 0);
    224   check_visit(allocator, in_dir, t1, t2, t3);
    225 
    226   CHK(my_type_ref_put(t1) == RES_OK);
    227   CHK(my_type_ref_put(t2) == RES_OK);
    228   CHK(my_type_ref_put(t3) == RES_OK);
    229 
    230   tracking.policy = TRACKING_POINT;
    231   pivot.type = PIVOT_SINGLE_AXIS;
    232   d3(pivot.data.pivot1.ref_normal, 0, 0, 1);
    233   d3(pivot.data.pivot1.ref_point, 0, 5, 5);
    234   d3(tracking.data.point.target, -12, 2, -10);
    235   tracking.data.point.target_is_local = 0;
    236 
    237   CHK(my_type_create(&allocator, &t1) == RES_OK);
    238   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    239   CHK(my_type_create(&allocator, &t3) == RES_OK);
    240 
    241   CHK(my_type_add_child(t1, t2) == RES_OK);
    242   CHK(my_type_add_child(t2, t3) == RES_OK);
    243 
    244   CHK(my_type_set_translation(t1, transl) == RES_OK);
    245   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    246   CHK(my_type_set_translation(t2, transl) == RES_OK);
    247   CHK(my_type_set_translation(t3, transl) == RES_OK);
    248 
    249   d3(in_dir, 1, 0, -1);
    250   check_visit(allocator, in_dir, t1, t2, t3);
    251 
    252   CHK(my_type_ref_put(t1) == RES_OK);
    253   CHK(my_type_ref_put(t2) == RES_OK);
    254   CHK(my_type_ref_put(t3) == RES_OK);
    255   
    256   /* 1 axis tracking a node target */
    257 
    258   CHK(my_type_create(&allocator, &target) == RES_OK);
    259   d3(tmp, 0, 0, 10 * sqrt(2));
    260   CHK(my_type_set_translation(target, tmp) == RES_OK);
    261 
    262   d3(pivot.data.pivot1.ref_normal, 0, 0, 1);
    263   d3(pivot.data.pivot1.ref_point, 0, 0, 0);
    264   CHK(my_type_track_me(target, &tracking) == RES_OK);
    265 
    266   CHK(my_type_create(&allocator, &t1) == RES_OK);
    267   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    268   CHK(my_type_create(&allocator, &t3) == RES_OK);
    269 
    270   CHK(my_type_add_child(t1, t2) == RES_OK);
    271   CHK(my_type_add_child(t2, t3) == RES_OK);
    272 
    273   CHK(my_type_set_translation(t1, transl) == RES_OK);
    274   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    275   CHK(my_type_set_translation(t2, transl) == RES_OK);
    276   CHK(my_type_set_translation(t3, transl) == RES_OK);
    277 
    278   d3(in_dir, 1, 0.1, 0);
    279   check_visit(allocator, in_dir, t1, t2, t3);
    280 
    281   CHK(my_type_ref_put(t1) == RES_OK);
    282   CHK(my_type_ref_put(t2) == RES_OK);
    283   CHK(my_type_ref_put(t3) == RES_OK);
    284   CHK(my_type_ref_put(target) == RES_OK);
    285 
    286   /*
    287   * 2 axis pivots
    288   * (using only one axis at a time)
    289   */
    290 
    291   /* 2 axis tracking sun */
    292 
    293   tracking.policy = TRACKING_SUN;
    294   pivot.type = PIVOT_TWO_AXIS;
    295   pivot.data.pivot2.spacing = 1;
    296   d3(pivot.data.pivot2.ref_point, 0, 0, 1);
    297 
    298   CHK(my_type_create(&allocator, &t1) == RES_OK);
    299   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    300   CHK(my_type_create(&allocator, &t3) == RES_OK);
    301 
    302   CHK(my_type_add_child(t1, t2) == RES_OK);
    303   CHK(my_type_add_child(t2, t3) == RES_OK);
    304 
    305   d3_splat(transl, +1);
    306   d3(rot, 0, 0, PI / 2);
    307   CHK(my_type_set_translation(t1, transl) == RES_OK);
    308   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    309   CHK(my_type_set_translation(t2, transl) == RES_OK);
    310   CHK(my_type_set_translation(t3, transl) == RES_OK);
    311 
    312   d3(in_dir, 1, 0, -1);
    313   check_visit(allocator, in_dir, t1, t2, t3);
    314 
    315   d3(in_dir, 0, 1, 0);
    316   check_visit(allocator, in_dir, t1, t2, t3);
    317 
    318   CHK(my_type_ref_put(t1) == RES_OK);
    319   CHK(my_type_ref_put(t2) == RES_OK);
    320   CHK(my_type_ref_put(t3) == RES_OK);
    321 
    322   /* 2 axis tracking sun */
    323 
    324   tracking.policy = TRACKING_SUN;
    325   pivot.type = PIVOT_TWO_AXIS;
    326   pivot.data.pivot2.spacing = 1;
    327 
    328   CHK(my_type_create(&allocator, &t1) == RES_OK);
    329   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    330   CHK(my_type_create(&allocator, &t3) == RES_OK);
    331 
    332   CHK(my_type_add_child(t1, t2) == RES_OK);
    333   CHK(my_type_add_child(t2, t3) == RES_OK);
    334 
    335   d3_splat(transl, +1);
    336   d3(rot, 0, 0, PI / 2);
    337   CHK(my_type_set_translation(t1, transl) == RES_OK);
    338   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    339   CHK(my_type_set_translation(t2, transl) == RES_OK);
    340   CHK(my_type_set_translation(t3, transl) == RES_OK);
    341 
    342   d3(in_dir, 1, 0, -1);
    343   check_visit(allocator, in_dir, t1, t2, t3);
    344 
    345   d3(in_dir, 0, 1, 0);
    346   check_visit(allocator, in_dir, t1, t2, t3);
    347 
    348   CHK(my_type_ref_put(t1) == RES_OK);
    349   CHK(my_type_ref_put(t2) == RES_OK);
    350   CHK(my_type_ref_put(t3) == RES_OK);
    351 
    352   /* 2 axis tracking with a fixed output dir */
    353 
    354   tracking.policy = TRACKING_OUT_DIR;
    355   pivot.type = PIVOT_TWO_AXIS;
    356   pivot.data.pivot2.spacing = 1;
    357   d3(tracking.data.out_dir.u, 0, 1, 0);
    358 
    359   CHK(my_type_create(&allocator, &t1) == RES_OK);
    360   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    361   CHK(my_type_create(&allocator, &t3) == RES_OK);
    362 
    363   CHK(my_type_add_child(t1, t2) == RES_OK);
    364   CHK(my_type_add_child(t2, t3) == RES_OK);
    365 
    366   CHK(my_type_set_translation(t1, transl) == RES_OK);
    367   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    368   CHK(my_type_set_translation(t2, transl) == RES_OK);
    369   CHK(my_type_set_translation(t3, transl) == RES_OK);
    370 
    371   d3(in_dir, 0, 0, -1);
    372   check_visit(allocator, in_dir, t1, t2, t3);
    373 
    374   d3(in_dir, -1, 0, 0);
    375   check_visit(allocator, in_dir, t1, t2, t3);
    376 
    377   CHK(my_type_ref_put(t1) == RES_OK);
    378   CHK(my_type_ref_put(t2) == RES_OK);
    379   CHK(my_type_ref_put(t3) == RES_OK);
    380 
    381   /* 2 axis tracking a target point */
    382 
    383   tracking.policy = TRACKING_POINT;
    384   pivot.type = PIVOT_TWO_AXIS;
    385   pivot.data.pivot2.spacing = 0;
    386   d3(pivot.data.pivot2.ref_point, 0, 0, 0);
    387   d3(tracking.data.point.target, 30, 0, 0);
    388   tracking.data.point.target_is_local = 1;
    389 
    390   CHK(my_type_create(&allocator, &t1) == RES_OK);
    391   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    392   CHK(my_type_create(&allocator, &t3) == RES_OK);
    393 
    394   CHK(my_type_add_child(t1, t2) == RES_OK);
    395   CHK(my_type_add_child(t2, t3) == RES_OK);
    396 
    397   CHK(my_type_set_translation(t1, transl) == RES_OK);
    398   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    399   CHK(my_type_set_translation(t2, transl) == RES_OK);
    400   CHK(my_type_set_translation(t3, transl) == RES_OK);
    401 
    402   d3(in_dir, -1, 0, 0);
    403   check_visit(allocator, in_dir, t1, t2, t3);
    404 
    405   CHK(my_type_ref_put(t1) == RES_OK);
    406   CHK(my_type_ref_put(t2) == RES_OK);
    407   CHK(my_type_ref_put(t3) == RES_OK);
    408 
    409   tracking.policy = TRACKING_POINT;
    410   pivot.type = PIVOT_TWO_AXIS;
    411   pivot.data.pivot2.spacing = sqrt(2);
    412   d3(pivot.data.pivot2.ref_point, 0, 10 * sqrt(2), 0);
    413   d3(tracking.data.point.target, 30, -11, 0);
    414   tracking.data.point.target_is_local = 1;
    415 
    416   CHK(my_type_create(&allocator, &t1) == RES_OK);
    417   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    418   CHK(my_type_create(&allocator, &t3) == RES_OK);
    419 
    420   CHK(my_type_add_child(t1, t2) == RES_OK);
    421   CHK(my_type_add_child(t2, t3) == RES_OK);
    422 
    423   CHK(my_type_set_translation(t1, transl) == RES_OK);
    424   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    425   CHK(my_type_set_translation(t2, transl) == RES_OK);
    426   CHK(my_type_set_translation(t3, transl) == RES_OK);
    427 
    428   d3(in_dir, -1, 0, 0);
    429   check_visit(allocator, in_dir, t1, t2, t3);
    430 
    431   CHK(my_type_ref_put(t1) == RES_OK);
    432   CHK(my_type_ref_put(t2) == RES_OK);
    433   CHK(my_type_ref_put(t3) == RES_OK);
    434 
    435   tracking.policy = TRACKING_POINT;
    436   pivot.type = PIVOT_TWO_AXIS;
    437   pivot.data.pivot2.spacing = 1;
    438   d3(pivot.data.pivot2.ref_point, 0, 10 * sqrt(2), 0);
    439   d3(tracking.data.point.target, 0, 30, 10);
    440   tracking.data.point.target_is_local = 1;
    441 
    442   CHK(my_type_create(&allocator, &t1) == RES_OK);
    443   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    444   CHK(my_type_create(&allocator, &t3) == RES_OK);
    445 
    446   CHK(my_type_add_child(t1, t2) == RES_OK);
    447   CHK(my_type_add_child(t2, t3) == RES_OK);
    448 
    449   CHK(my_type_set_translation(t1, transl) == RES_OK);
    450   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    451   CHK(my_type_set_translation(t2, transl) == RES_OK);
    452   CHK(my_type_set_translation(t3, transl) == RES_OK);
    453 
    454   d3(in_dir, 0, 0, -1);
    455   check_visit(allocator, in_dir, t1, t2, t3);
    456 
    457   CHK(my_type_ref_put(t1) == RES_OK);
    458   CHK(my_type_ref_put(t2) == RES_OK);
    459   CHK(my_type_ref_put(t3) == RES_OK);
    460 
    461   tracking.policy = TRACKING_POINT;
    462   pivot.type = PIVOT_TWO_AXIS;
    463   pivot.data.pivot2.spacing = 1;
    464   d3(pivot.data.pivot2.ref_point, 0, 10 * sqrt(2), 0);
    465   d3(tracking.data.point.target, 0, 30, 12);
    466   tracking.data.point.target_is_local = 0;
    467 
    468   CHK(my_type_create(&allocator, &t1) == RES_OK);
    469   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    470   CHK(my_type_create(&allocator, &t3) == RES_OK);
    471 
    472   CHK(my_type_add_child(t1, t2) == RES_OK);
    473   CHK(my_type_add_child(t2, t3) == RES_OK);
    474 
    475   CHK(my_type_set_translation(t1, transl) == RES_OK);
    476   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    477   CHK(my_type_set_translation(t2, transl) == RES_OK);
    478   CHK(my_type_set_translation(t3, transl) == RES_OK);
    479 
    480   d3(in_dir, 0, 0, -1);
    481   check_visit(allocator, in_dir, t1, t2, t3);
    482 
    483   CHK(my_type_ref_put(t1) == RES_OK);
    484   CHK(my_type_ref_put(t2) == RES_OK);
    485   CHK(my_type_ref_put(t3) == RES_OK);
    486 
    487   tracking.policy = TRACKING_POINT;
    488   pivot.type = PIVOT_TWO_AXIS;
    489   pivot.data.pivot2.spacing = 1;
    490   d3(pivot.data.pivot2.ref_point, 10, 8 * sqrt(2), 5 * sqrt(2));
    491   d3(tracking.data.point.target, 10, 12, 15);
    492   tracking.data.point.target_is_local = 0;
    493 
    494   CHK(my_type_create(&allocator, &t1) == RES_OK);
    495   CHK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2) == RES_OK);
    496   CHK(my_type_create(&allocator, &t3) == RES_OK);
    497 
    498   CHK(my_type_add_child(t1, t2) == RES_OK);
    499   CHK(my_type_add_child(t2, t3) == RES_OK);
    500 
    501   CHK(my_type_set_translation(t1, transl) == RES_OK);
    502   CHK(my_type_set_rotations(t1, rot) == RES_OK);
    503   CHK(my_type_set_translation(t2, transl) == RES_OK);
    504   CHK(my_type_set_translation(t3, transl) == RES_OK);
    505 
    506   d3(in_dir, 0, 0, -1);
    507   check_visit(allocator, in_dir, t1, t2, t3);
    508 
    509   /* release memory */
    510   CHK(my_type_ref_put(t1) == RES_OK);
    511   CHK(my_type_ref_put(t2) == RES_OK);
    512   CHK(my_type_ref_put(t3) == RES_OK);
    513   check_memory_allocator(&allocator);
    514   mem_shutdown_proxy_allocator(&allocator);
    515   CHK(mem_allocated_size() == 0);
    516   return 0;
    517 }