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_utils.c (8721B)


      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 "test_sanim_utils.h"
     18 
     19 #include <rsys/rsys.h>
     20 #include <rsys/mem_allocator.h>
     21 #include <rsys/logger.h>
     22 #include <rsys/dynamic_array.h>
     23 
     24 /* Define the darray_tmp data structure */
     25 #define DARRAY_NAME tmp
     26 #define DARRAY_DATA struct my_type*
     27 #include <rsys/dynamic_array.h>
     28 
     29 #include <stdio.h>
     30 
     31 res_T
     32 my_type_create(struct mem_allocator *allocator, struct my_type** out)
     33 {
     34   res_T res = RES_OK;
     35   struct my_type* t;
     36   struct mem_allocator* alloc;
     37   if (!out) return RES_BAD_ARG;
     38   alloc = allocator ? allocator : &mem_default_allocator;
     39   t = MEM_CALLOC(alloc, 1, sizeof(struct my_type));
     40   if (!t) {
     41     res = RES_MEM_ERR;
     42     goto error;
     43   }
     44 
     45   t->my_data = 0;
     46   t->allocator = alloc;
     47   ref_init(&t->ref);
     48 
     49   res = sanim_node_initialize(alloc, &t->node);
     50   if (res != RES_OK) return res;
     51 
     52 exit:
     53   if (out) *out = t;
     54   return res;
     55 error:
     56   if (t) {
     57     my_type_ref_put(t);
     58     t = NULL;
     59   }
     60   goto exit;
     61 }
     62 
     63 res_T
     64 my_type_pivot_create
     65   (struct mem_allocator *allocator, 
     66    const struct sanim_pivot* pivot,
     67    const struct sanim_tracking* tracking,
     68    struct my_type** out)
     69 {
     70   res_T res = RES_OK;
     71   struct my_type* t;
     72   struct mem_allocator* alloc;
     73   if (!out) return RES_BAD_ARG;
     74   alloc = allocator ? allocator : &mem_default_allocator;
     75   t = MEM_CALLOC(alloc, 1, sizeof(struct my_type));
     76   if (!t) {
     77     res = RES_MEM_ERR;
     78     goto error;
     79   }
     80 
     81   t->my_data = 0;
     82   t->allocator = alloc;
     83   ref_init(&t->ref);
     84 
     85   res = sanim_node_initialize_pivot(alloc, pivot, tracking, &t->node);
     86   if (res != RES_OK) goto error;
     87 
     88 exit:
     89   if (out) *out = t;
     90   return res;
     91 error:
     92   if (t) {
     93     my_type_ref_put(t);
     94     t = NULL;
     95   }
     96   goto exit;
     97 }
     98 
     99 res_T
    100 my_type_copy_create
    101   (const struct my_type* src,
    102    struct my_type** dst)
    103 {
    104   struct my_type* t;
    105   res_T res = RES_OK;
    106   if (!dst || ! src) return RES_BAD_ARG;
    107   ASSERT(src->allocator);
    108   t = MEM_CALLOC(src->allocator, 1, sizeof(struct my_type));
    109   if (!t) {
    110     res = RES_MEM_ERR;
    111     goto error;
    112   }
    113   t->allocator = src->allocator;
    114   ref_init(&t->ref);
    115   res = sanim_node_copy_initialize(src->allocator, &src->node, &t->node);
    116   if (res != RES_OK)
    117     goto error;
    118   t->my_data = src->my_data;
    119 exit:
    120   *dst = t;
    121   return res;
    122 error:
    123   if (t) {
    124     my_type_ref_put(t);
    125     t = NULL;
    126   }
    127   goto exit;
    128 }
    129 
    130 res_T
    131 my_type_get_father
    132   (const struct my_type* t,
    133    struct my_type** father)
    134 {
    135   const struct sanim_node* tmp;
    136   res_T res = RES_OK;
    137   if (!t || !father) return RES_BAD_ARG;
    138   res = sanim_node_get_father(&t->node, &tmp);
    139   if (res != RES_OK) return res;
    140   *father = CONTAINER_OF(tmp, struct my_type, node);
    141   return RES_OK;
    142 }
    143 
    144 res_T
    145 my_type_get_children_count
    146   (const struct my_type* t, size_t* count)
    147 {
    148   return sanim_node_get_children_count(&t->node, count);
    149 }
    150 
    151 res_T
    152 my_type_get_child
    153   (const struct my_type* t,
    154    const size_t idx,
    155    struct my_type** child)
    156 {
    157   struct sanim_node* tmp;
    158   res_T res = RES_OK;
    159   if (!t || !child) return RES_BAD_ARG;
    160   res = sanim_node_get_child(&t->node, idx, &tmp);
    161   if (res != RES_OK) return res;
    162   *child = CONTAINER_OF(tmp, struct my_type, node);
    163   return RES_OK;
    164 }
    165 
    166 static res_T
    167 my_type_recursive_copy_
    168   (struct mem_allocator *alloc,
    169    const struct my_type* src,
    170    struct darray_tmp* tmp,
    171    struct my_type** dst)
    172 {
    173   struct my_type* root;
    174   size_t i, sz;
    175   res_T res = RES_OK;
    176 
    177   ASSERT(alloc && src && tmp && dst);
    178   res = my_type_copy_create(src, &root);
    179   if (res != RES_OK) goto error;
    180   darray_tmp_push_back(tmp, &root);
    181   if (res != RES_OK) goto error;
    182   CHK(my_type_get_children_count(src, &sz) == RES_OK);
    183   for (i = 0; i < sz; i++) {
    184     struct my_type* child;
    185     struct my_type* node;
    186     CHK(my_type_get_child(src, i, &child) == RES_OK);
    187     res = my_type_recursive_copy_(alloc, child, tmp, &node);
    188     if (res != RES_OK) goto error;
    189     my_type_add_child(root, node);
    190     my_type_ref_put(node); /* node is referenced by root */
    191   }
    192 exit:
    193   *dst = root;
    194   return res;
    195 error:
    196   root = NULL;
    197   goto exit;
    198 }
    199 
    200 res_T
    201 my_type_recursive_copy
    202 (struct mem_allocator *allocator,
    203   const struct my_type* src,
    204   struct my_type** dst)
    205 {
    206   struct darray_tmp tmp;
    207   struct mem_allocator* alloc;
    208   res_T res = RES_OK;
    209 
    210   if (!dst || !src) return RES_BAD_ARG;
    211   if (*dst == src) return RES_BAD_ARG;
    212   alloc = allocator ? allocator : &mem_default_allocator;
    213   darray_tmp_init(alloc, &tmp);
    214   res = my_type_recursive_copy_(alloc, src, &tmp, dst);
    215   if (res != RES_OK) goto error;
    216 exit:
    217   darray_tmp_release(&tmp);
    218   return res;
    219 error:
    220   {
    221     struct my_type* const* children;
    222     size_t i, sz;
    223     sz = darray_tmp_size_get(&tmp);
    224     children = darray_tmp_cdata_get(&tmp);
    225     for (i = 0; i < sz; i++) {
    226       struct my_type* node = children[i];
    227       my_type_ref_put(node);
    228     }
    229     *dst = NULL;
    230     goto exit;
    231   }
    232 }
    233 
    234 static void
    235 my_type_release(ref_T* ref)
    236 {
    237   size_t i, sz;
    238   struct my_type* t = CONTAINER_OF(ref, struct my_type, ref);
    239   if (t->node.data) {
    240     CHK(my_type_get_children_count(t, &sz) == RES_OK);
    241     for (i = 0; i < sz; i++) {
    242       struct my_type* node;
    243       CHK(my_type_get_child(t, i, &node) == RES_OK);
    244       my_type_ref_put(node);
    245     }
    246   }
    247   SANIM(node_release(&t->node));
    248   MEM_RM(t->allocator, t);
    249 }
    250 
    251 res_T
    252 my_type_ref_get(struct my_type* t)
    253 {
    254   if (!t) return RES_BAD_ARG;
    255   ref_get(&t->ref);
    256   return RES_OK;
    257 }
    258 
    259 res_T
    260 my_type_ref_put(struct my_type* t)
    261 {
    262   if (!t) return RES_BAD_ARG;
    263   ref_put(&t->ref, my_type_release);
    264   return RES_OK;
    265 }
    266 
    267 res_T
    268 my_type_add_child(struct my_type* t, struct my_type* child) {
    269   res_T res = RES_OK;
    270   if (!t || !child) return RES_BAD_ARG;
    271   res = sanim_node_add_child(&t->node, &child->node);
    272   if (res != RES_OK) return res;
    273   my_type_ref_get(child);
    274   return RES_OK;
    275 }
    276 
    277 res_T
    278 my_type_set_translation(struct my_type* t, const double translation[3]) {
    279   if (!t || !translation) return RES_BAD_ARG;
    280   return sanim_node_set_translation(&t->node, translation);
    281 }
    282 
    283 res_T
    284 my_type_get_translation(const struct my_type* t, double translation[3]) {
    285   if (!t || !translation) return RES_BAD_ARG;
    286   return sanim_node_get_translation(&t->node, translation);
    287 }
    288 
    289 res_T
    290 my_type_set_rotations(struct my_type* t, const double rotations[3]) {
    291   if (!t || !rotations) return RES_BAD_ARG;
    292   return sanim_node_set_rotations(&t->node, rotations);
    293 }
    294 
    295 res_T
    296 my_type_get_rotations(const struct my_type* t, double rotations[3]) {
    297   if (!t || !rotations) return RES_BAD_ARG;
    298   return sanim_node_get_rotations(&t->node, rotations);
    299 }
    300 
    301 res_T
    302 my_type_get_transform(struct my_type* t, double transform[12]) {
    303   if (!t || !transform) return RES_BAD_ARG;
    304   return sanim_node_get_transform(&t->node, transform);
    305 }
    306 
    307 res_T
    308 my_type_solve_pivot(struct my_type* t, const double in_dir[3]) {
    309   return sanim_node_solve_pivot(&t->node, in_dir);
    310 }
    311 
    312 res_T
    313 my_type_is_pivot(struct my_type* t, int* pivot) {
    314   return sanim_node_is_pivot(&t->node, pivot);
    315 }
    316 
    317 res_T
    318 my_type_track_me(const struct my_type* t, struct sanim_tracking* tracking) {
    319   return sanim_node_track_me(&t->node, tracking);
    320 }
    321 
    322 char
    323 d3_is_zero_eps(const double v[3], const double eps) {
    324   int x;
    325   ASSERT(eps >= 0);
    326   FOR_EACH(x, 0, 3) {
    327     if (fabs(v[x]) > eps) return 0;
    328   }
    329   return 1;
    330 }
    331 
    332 char
    333 d3_is_zero(const double v[3]) {
    334   int x;
    335   FOR_EACH(x, 0, 3) {
    336     if (v[x]) return 0;
    337   }
    338   return 1;
    339 }
    340 
    341 char
    342 d33_is_identity_eps(const double v[9], const double eps) {
    343   int i = 0, x, y;
    344   ASSERT(eps >= 0);
    345   FOR_EACH(x, 0, 3) {
    346     FOR_EACH(y, 0, 3) {
    347       if (fabs(v[i] - (x == y ? 1 : 0)) > eps) return 0;
    348       ++i;
    349     }
    350   }
    351   return 1;
    352 }
    353 
    354 char
    355 d34_eq_eps(const double a[12], const double b[12], const double eps) {
    356   int i;
    357   ASSERT(eps >= 0);
    358   FOR_EACH(i, 0, 12) {
    359       if (fabs(a[i] - b[i]) > eps) return 0;
    360   }
    361   return 1;
    362 }
    363 
    364 void
    365 log_stream(const char* msg, void* ctx) {
    366   ASSERT(msg);
    367   (void) msg, (void) ctx;
    368   printf("%s\n", msg);
    369 }
    370 
    371 void
    372 check_memory_allocator(struct mem_allocator* allocator) {
    373   if (MEM_ALLOCATED_SIZE(allocator)) {
    374     char dump[512];
    375     MEM_DUMP(allocator, dump, sizeof(dump) / sizeof(char));
    376     fprintf(stderr, "%s\n", dump);
    377     FATAL("Memory leaks\n");
    378   }
    379 }
    380