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