Cleanup: trailing space
[blender.git] / source / blender / collada / collada_utils.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (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, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/collada/collada_utils.cpp
24  *  \ingroup collada
25  */
26
27
28 /* COLLADABU_ASSERT, may be able to remove later */
29 #include "COLLADABUPlatform.h"
30
31 #include "COLLADAFWGeometry.h"
32 #include "COLLADAFWMeshPrimitive.h"
33 #include "COLLADAFWMeshVertexData.h"
34
35 #include <set>
36
37 extern "C" {
38 #include "DNA_modifier_types.h"
39 #include "DNA_customdata_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_armature_types.h"
44
45 #include "BLI_math.h"
46 #include "BLI_linklist.h"
47
48 #include "BKE_context.h"
49 #include "BKE_customdata.h"
50 #include "BKE_depsgraph.h"
51 #include "BKE_object.h"
52 #include "BKE_global.h"
53 #include "BKE_mesh.h"
54 #include "BKE_scene.h"
55 #include "BKE_DerivedMesh.h"
56 #include "BKE_main.h"
57
58 #include "ED_armature.h"
59
60 #include "WM_api.h" // XXX hrm, see if we can do without this
61 #include "WM_types.h"
62
63 #include "bmesh.h"
64 #include "bmesh_tools.h"
65 }
66
67 #include "collada_utils.h"
68 #include "ExportSettings.h"
69
70 float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index)
71 {
72         if (index >= array.getValuesCount())
73                 return 0.0f;
74
75         if (array.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT)
76                 return array.getFloatValues()->getData()[index];
77         else
78                 return array.getDoubleValues()->getData()[index];
79 }
80
81 // copied from /editors/object/object_relations.c
82 int bc_test_parent_loop(Object *par, Object *ob)
83 {
84         /* test if 'ob' is a parent somewhere in par's parents */
85
86         if (par == NULL) return 0;
87         if (ob == par) return 1;
88
89         return bc_test_parent_loop(par->parent, ob);
90 }
91
92 // a shortened version of parent_set_exec()
93 // if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting
94 int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
95 {
96         Object workob;
97         Scene *sce = CTX_data_scene(C);
98
99         if (!par || bc_test_parent_loop(par, ob))
100                 return false;
101
102         ob->parent = par;
103         ob->partype = PAROBJECT;
104
105         ob->parsubstr[0] = 0;
106
107         if (is_parent_space) {
108                 float mat[4][4];
109                 // calc par->obmat
110                 BKE_object_where_is_calc(sce, par);
111
112                 // move child obmat into world space
113                 mul_m4_m4m4(mat, par->obmat, ob->obmat);
114                 copy_m4_m4(ob->obmat, mat);
115         }
116
117         // apply child obmat (i.e. decompose it into rot/loc/size)
118         BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
119
120         // compute parentinv
121         BKE_object_workob_calc_parent(sce, ob, &workob);
122         invert_m4_m4(ob->parentinv, workob.obmat);
123
124         DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
125         DAG_id_tag_update(&par->id, OB_RECALC_OB);
126
127         /** done once after import */
128 #if 0
129         DAG_relations_tag_update(bmain);
130         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
131 #endif
132
133         return true;
134 }
135
136 EvaluationContext *bc_get_evaluation_context(Main *bmain)
137 {
138         return bmain->eval_ctx;
139 }
140
141 void bc_update_scene(Main *bmain, Scene *scene, float ctime)
142 {
143         BKE_scene_frame_set(scene, ctime);
144         EvaluationContext *ev_context = bc_get_evaluation_context(bmain);
145         BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
146 }
147
148 Object *bc_add_object(Main *bmain, Scene *scene, int type, const char *name)
149 {
150         Object *ob = BKE_object_add_only_object(bmain, type, name);
151
152         ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
153         ob->lay = scene->lay;
154         DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
155
156         BKE_scene_base_select(scene, BKE_scene_base_add(scene, ob));
157
158         return ob;
159 }
160
161 Mesh *bc_get_mesh_copy(
162         Main *bmain, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate)
163 {
164         Mesh *tmpmesh;
165         CustomDataMask mask = CD_MASK_MESH;
166         Mesh *mesh = (Mesh *)ob->data;
167         DerivedMesh *dm = NULL;
168         if (apply_modifiers) {
169                 switch (export_mesh_type) {
170                         case BC_MESH_TYPE_VIEW:
171                         {
172                                 dm = mesh_create_derived_view(scene, ob, mask);
173                                 break;
174                         }
175                         case BC_MESH_TYPE_RENDER:
176                         {
177                                 dm = mesh_create_derived_render(scene, ob, mask);
178                                 break;
179                         }
180                 }
181         }
182         else {
183                 dm = mesh_create_derived((Mesh *)ob->data, NULL);
184         }
185
186         tmpmesh = BKE_mesh_add(bmain, "ColladaMesh"); // name is not important here
187         DM_to_mesh(dm, tmpmesh, ob, CD_MASK_MESH, true);
188         tmpmesh->flag = mesh->flag;
189
190         if (triangulate) {
191                 bc_triangulate_mesh(tmpmesh);
192         }
193         BKE_mesh_tessface_ensure(tmpmesh);
194         return tmpmesh;
195 }
196
197 Object *bc_get_assigned_armature(Object *ob)
198 {
199         Object *ob_arm = NULL;
200
201         if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
202                 ob_arm = ob->parent;
203         }
204         else {
205                 ModifierData *mod;
206                 for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) {
207                         if (mod->type == eModifierType_Armature) {
208                                 ob_arm = ((ArmatureModifierData *)mod)->object;
209                         }
210                 }
211         }
212
213         return ob_arm;
214 }
215
216 // Returns the highest selected ancestor
217 // returns NULL if no ancestor is selected
218 // IMPORTANT: This function expects that
219 // all exported objects have set:
220 // ob->id.tag & LIB_TAG_DOIT
221 Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob)
222 {
223         Object *ancestor = ob;
224         while (ob->parent && bc_is_marked(ob->parent)) {
225                 ob = ob->parent;
226                 ancestor = ob;
227         }
228         return ancestor;
229 }
230
231
232 bool bc_is_base_node(LinkNode *export_set, Object *ob)
233 {
234         Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob);
235         return (root == ob);
236 }
237
238 bool bc_is_in_Export_set(LinkNode *export_set, Object *ob)
239 {
240         return (BLI_linklist_index(export_set, ob) != -1);
241 }
242
243 bool bc_has_object_type(LinkNode *export_set, short obtype)
244 {
245         LinkNode *node;
246
247         for (node = export_set; node; node = node->next) {
248                 Object *ob = (Object *)node->link;
249                 /* XXX - why is this checking for ob->data? - we could be looking for empties */
250                 if (ob->type == obtype && ob->data) {
251                         return true;
252                 }
253         }
254         return false;
255 }
256
257 int bc_is_marked(Object *ob)
258 {
259         return ob && (ob->id.tag & LIB_TAG_DOIT);
260 }
261
262 void bc_remove_mark(Object *ob)
263 {
264         ob->id.tag &= ~LIB_TAG_DOIT;
265 }
266
267 void bc_set_mark(Object *ob)
268 {
269         ob->id.tag |= LIB_TAG_DOIT;
270 }
271
272 // Use bubble sort algorithm for sorting the export set
273 void bc_bubble_sort_by_Object_name(LinkNode *export_set)
274 {
275         bool sorted = false;
276         LinkNode *node;
277         for (node = export_set; node->next && !sorted; node = node->next) {
278
279                 sorted = true;
280
281                 LinkNode *current;
282                 for (current = export_set; current->next; current = current->next) {
283                         Object *a = (Object *)current->link;
284                         Object *b = (Object *)current->next->link;
285
286                         if (strcmp(a->id.name, b->id.name) > 0) {
287                                 current->link       = b;
288                                 current->next->link = a;
289                                 sorted = false;
290                         }
291
292                 }
293         }
294 }
295
296 /* Check if a bone is the top most exportable bone in the bone hierarchy.
297  * When deform_bones_only == false, then only bones with NO parent
298  * can be root bones. Otherwise the top most deform bones in the hierarchy
299  * are root bones.
300  */
301 bool bc_is_root_bone(Bone *aBone, bool deform_bones_only)
302 {
303         if (deform_bones_only) {
304                 Bone *root = NULL;
305                 Bone *bone = aBone;
306                 while (bone) {
307                         if (!(bone->flag & BONE_NO_DEFORM))
308                                 root = bone;
309                         bone = bone->parent;
310                 }
311                 return (aBone == root);
312         }
313         else
314                 return !(aBone->parent);
315 }
316
317 int bc_get_active_UVLayer(Object *ob)
318 {
319         Mesh *me = (Mesh *)ob->data;
320         return CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
321 }
322
323 std::string bc_url_encode(std::string data)
324 {
325         /* XXX We probably do not need to do a full encoding.
326          * But in case that is necessary,then it can be added here.
327          */
328         return bc_replace_string(data,"#", "%23");
329 }
330
331 std::string bc_replace_string(std::string data, const std::string& pattern,
332                               const std::string& replacement)
333 {
334         size_t pos = 0;
335         while ((pos = data.find(pattern, pos)) != std::string::npos) {
336                 data.replace(pos, pattern.length(), replacement);
337                 pos += replacement.length();
338         }
339         return data;
340 }
341
342 /**
343  * Calculate a rescale factor such that the imported scene's scale
344  * is preserved. I.e. 1 meter in the import will also be
345  * 1 meter in the current scene.
346  */
347
348 void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene)
349 {
350         if (scale_to_scene) {
351                 mul_m4_m4m4(ob->obmat, bc_unit.get_scale(), ob->obmat);
352         }
353         mul_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat);
354         BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
355 }
356
357 void bc_match_scale(std::vector<Object *> *objects_done,
358                         UnitConverter &bc_unit,
359                         bool scale_to_scene)
360 {
361         for (std::vector<Object *>::iterator it = objects_done->begin();
362                         it != objects_done->end();
363                         ++it)
364         {
365                 Object *ob = *it;
366                 if (ob -> parent == NULL) {
367                         bc_match_scale(*it, bc_unit, scale_to_scene);
368                 }
369         }
370 }
371
372 /*
373  * Convenience function to get only the needed components of a matrix
374  */
375 void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
376 {
377         if (size) {
378                 mat4_to_size(size, mat);
379         }
380
381         if (eul) {
382                 mat4_to_eul(eul, mat);
383         }
384
385         if (quat) {
386                 mat4_to_quat(quat, mat);
387         }
388
389         if (loc) {
390                 copy_v3_v3(loc, mat[3]);
391         }
392 }
393
394 /*
395  * Create rotation_quaternion from a delta rotation and a reference quat
396  *
397  * Input:
398  * mat_from: The rotation matrix before rotation
399  * mat_to  : The rotation matrix after rotation
400  * qref    : the quat corresponding to mat_from
401  *
402  * Output:
403  * rot     : the calculated result (quaternion)
404  *
405  */
406 void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4])
407 {
408         float qd[4];
409         float matd[4][4];
410         float mati[4][4];
411         float mat_from[4][4];
412         quat_to_mat4(mat_from, quat_from);
413
414         // Calculate the difference matrix matd between mat_from and mat_to
415         invert_m4_m4(mati, mat_from);
416         mul_m4_m4m4(matd, mati, mat_to);
417
418         mat4_to_quat(qd, matd);
419
420         mul_qt_qtqt(quat_to, qd, quat_from); // rot is the final rotation corresponding to mat_to
421 }
422
423 void bc_triangulate_mesh(Mesh *me)
424 {
425         bool use_beauty  = false;
426         bool tag_only    = false;
427         int  quad_method = MOD_TRIANGULATE_QUAD_SHORTEDGE; /* XXX: The triangulation method selection could be offered in the UI */
428
429         const struct BMeshCreateParams bm_create_params = {0};
430         BMesh *bm = BM_mesh_create(
431                 &bm_mesh_allocsize_default,
432                 &bm_create_params);
433         BMeshFromMeshParams bm_from_me_params = {0};
434         bm_from_me_params.calc_face_normal = true;
435         BM_mesh_bm_from_me(bm, me, &bm_from_me_params);
436         BM_mesh_triangulate(bm, quad_method, use_beauty, tag_only, NULL, NULL, NULL);
437
438         BMeshToMeshParams bm_to_me_params = {0};
439         bm_to_me_params.calc_object_remap = false;
440         BM_mesh_bm_to_me(NULL, bm, me, &bm_to_me_params);
441         BM_mesh_free(bm);
442 }
443
444 /*
445  * A bone is a leaf when it has no children or all children are not connected.
446  */
447 bool bc_is_leaf_bone(Bone *bone)
448 {
449         for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
450                 if (child->flag & BONE_CONNECTED)
451                         return false;
452         }
453         return true;
454 }
455
456 EditBone *bc_get_edit_bone(bArmature * armature, char *name) {
457         EditBone  *eBone;
458
459         for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) {
460                 if (STREQ(name, eBone->name))
461                         return eBone;
462         }
463
464         return NULL;
465
466 }
467 int bc_set_layer(int bitfield, int layer)
468 {
469         return bc_set_layer(bitfield, layer, true); /* enable */
470 }
471
472 int bc_set_layer(int bitfield, int layer, bool enable)
473 {
474         int bit = 1u << layer;
475
476         if (enable)
477                 bitfield |= bit;
478         else
479                 bitfield &= ~bit;
480
481         return bitfield;
482 }
483
484 /**
485  * This method creates a new extension map when needed.
486  * \note The ~BoneExtensionManager destructor takes care
487  * to delete the created maps when the manager is removed.
488  */
489 BoneExtensionMap &BoneExtensionManager::getExtensionMap(bArmature *armature)
490 {
491         std::string key = armature->id.name;
492         BoneExtensionMap *result = extended_bone_maps[key];
493         if (result == NULL)
494         {
495                 result = new BoneExtensionMap();
496                 extended_bone_maps[key] = result;
497         }
498         return *result;
499 }
500
501 BoneExtensionManager::~BoneExtensionManager()
502 {
503         std::map<std::string, BoneExtensionMap *>::iterator map_it;
504         for (map_it = extended_bone_maps.begin(); map_it != extended_bone_maps.end(); ++map_it)
505         {
506                 BoneExtensionMap *extended_bones = map_it->second;
507                 for (BoneExtensionMap::iterator ext_it = extended_bones->begin(); ext_it != extended_bones->end(); ++ext_it) {
508                         if (ext_it->second != NULL)
509                                 delete ext_it->second;
510                 }
511                 extended_bones->clear();
512                 delete extended_bones;
513         }
514 }
515
516 /**
517  * BoneExtended is a helper class needed for the Bone chain finder
518  * See ArmatureImporter::fix_leaf_bones()
519  * and ArmatureImporter::connect_bone_chains()
520  */
521
522 BoneExtended::BoneExtended(EditBone *aBone)
523 {
524         this->set_name(aBone->name);
525         this->chain_length = 0;
526         this->is_leaf = false;
527         this->tail[0] = 0.0f;
528         this->tail[1] = 0.5f;
529         this->tail[2] = 0.0f;
530         this->use_connect = -1;
531         this->roll = 0;
532         this->bone_layers = 0;
533
534         this->has_custom_tail = false;
535         this->has_custom_roll = false;
536 }
537
538 char *BoneExtended::get_name()
539 {
540         return name;
541 }
542
543 void BoneExtended::set_name(char *aName)
544 {
545         BLI_strncpy(name, aName, MAXBONENAME);
546 }
547
548 int BoneExtended::get_chain_length()
549 {
550         return chain_length;
551 }
552
553 void BoneExtended::set_chain_length(const int aLength)
554 {
555         chain_length = aLength;
556 }
557
558 void BoneExtended::set_leaf_bone(bool state)
559 {
560         is_leaf = state;
561 }
562
563 bool BoneExtended::is_leaf_bone()
564 {
565         return is_leaf;
566 }
567
568 void BoneExtended::set_roll(float roll)
569 {
570         this->roll = roll;
571         this->has_custom_roll = true;
572 }
573
574 bool BoneExtended::has_roll()
575 {
576         return this->has_custom_roll;
577 }
578
579 float BoneExtended::get_roll()
580 {
581         return this->roll;
582 }
583
584 void BoneExtended::set_tail(float vec[])
585 {
586         this->tail[0] = vec[0];
587         this->tail[1] = vec[1];
588         this->tail[2] = vec[2];
589         this->has_custom_tail = true;
590 }
591
592 bool BoneExtended::has_tail()
593 {
594         return this->has_custom_tail;
595 }
596
597 float *BoneExtended::get_tail()
598 {
599         return this->tail;
600 }
601
602 inline bool isInteger(const std::string & s)
603 {
604         if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;
605
606         char *p;
607         strtol(s.c_str(), &p, 10);
608
609         return (*p == 0);
610 }
611
612 void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::string> &layer_labels)
613 {
614         std::stringstream ss(layerString);
615         std::string layer;
616         int pos;
617
618         while (ss >> layer) {
619
620                 /* Blender uses numbers to specify layers*/
621                 if (isInteger(layer))
622                 {
623                         pos = atoi(layer.c_str());
624                         if (pos >= 0 && pos < 32) {
625                                 this->bone_layers = bc_set_layer(this->bone_layers, pos);
626                                 continue;
627                         }
628                 }
629
630                 /* layer uses labels (not supported by blender). Map to layer numbers:*/
631                 pos = find(layer_labels.begin(), layer_labels.end(), layer) - layer_labels.begin();
632                 if (pos >= layer_labels.size()) {
633                         layer_labels.push_back(layer); /* remember layer number for future usage*/
634                 }
635
636                 if (pos > 31)
637                 {
638                         fprintf(stderr, "Too many layers in Import. Layer %s mapped to Blender layer 31\n", layer.c_str());
639                         pos = 31;
640                 }
641
642                 /* If numeric layers and labeled layers are used in parallel (unlikely),
643                  * we get a potential mixup. Just leave as is for now.
644                  */
645                 this->bone_layers = bc_set_layer(this->bone_layers, pos);
646
647         }
648 }
649
650 std::string BoneExtended::get_bone_layers(int bitfield)
651 {
652         std::string result = "";
653         std::string sep = "";
654         int bit = 1u;
655
656         std::ostringstream ss;
657         for (int i = 0; i < 32; i++)
658         {
659                 if (bit & bitfield)
660                 {
661                         ss << sep << i;
662                         sep = " ";
663                 }
664                 bit = bit << 1;
665         }
666         return ss.str();
667 }
668
669 int BoneExtended::get_bone_layers()
670 {
671         return (bone_layers == 0) ? 1 : bone_layers; // ensure that the bone is in at least one bone layer!
672 }
673
674
675 void BoneExtended::set_use_connect(int use_connect)
676 {
677         this->use_connect = use_connect;
678 }
679
680 int BoneExtended::get_use_connect()
681 {
682         return this->use_connect;
683 }
684
685 /**
686  * Stores a 4*4 matrix as a custom bone property array of size 16
687  */
688 void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
689 {
690         IDProperty *idgroup = (IDProperty *)ebone->prop;
691         if (idgroup == NULL)
692         {
693                 IDPropertyTemplate val = { 0 };
694                 idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
695                 ebone->prop = idgroup;
696         }
697
698         IDPropertyTemplate val = { 0 };
699         val.array.len = 16;
700         val.array.type = IDP_FLOAT;
701
702         IDProperty *data = IDP_New(IDP_ARRAY, &val, key);
703         float *array = (float *)IDP_Array(data);
704         for (int i = 0; i < 4; i++)
705                 for (int j = 0; j < 4; j++)
706                         array[4 * i + j] = mat[i][j];
707
708         IDP_AddToGroup(idgroup, data);
709 }
710
711 #if 0
712 /**
713  * Stores a Float value as a custom bone property
714  *
715  * Note: This function is currently not needed. Keep for future usage
716  */
717 static void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
718 {
719         if (ebone->prop == NULL)
720         {
721                 IDPropertyTemplate val = { 0 };
722                 ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
723         }
724
725         IDProperty *pgroup = (IDProperty *)ebone->prop;
726         IDPropertyTemplate val = { 0 };
727         IDProperty *prop = IDP_New(IDP_FLOAT, &val, key);
728         IDP_Float(prop) = value;
729         IDP_AddToGroup(pgroup, prop);
730
731 }
732 #endif
733
734 /**
735  * Get a custom property when it exists.
736  * This function is also used to check if a property exists.
737  */
738 IDProperty *bc_get_IDProperty(Bone *bone, std::string key)
739 {
740         return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str());
741 }
742
743 /**
744  * Read a custom bone property and convert to float
745  * Return def if the property does not exist.
746  */
747 float bc_get_property(Bone *bone, std::string key, float def)
748 {
749         float result = def;
750         IDProperty *property = bc_get_IDProperty(bone, key);
751         if (property) {
752                 switch (property->type) {
753                         case IDP_INT:
754                                 result = (float)(IDP_Int(property));
755                                 break;
756                         case IDP_FLOAT:
757                                 result = (float)(IDP_Float(property));
758                                 break;
759                         case IDP_DOUBLE:
760                                 result = (float)(IDP_Double(property));
761                                 break;
762                         default:
763                                 result = def;
764                 }
765         }
766         return result;
767 }
768
769 /**
770  * Read a custom bone property and convert to matrix
771  * Return true if conversion was successful
772  *
773  * Return false if:
774  * - the property does not exist
775  * - is not an array of size 16
776  */
777 bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
778 {
779         IDProperty *property = bc_get_IDProperty(bone, key);
780         if (property && property->type == IDP_ARRAY && property->len == 16) {
781                 float *array = (float *)IDP_Array(property);
782                 for (int i = 0; i < 4; i++)
783                         for (int j = 0; j < 4; j++)
784                                 mat[i][j] = array[4 * i + j];
785                 return true;
786         }
787         return false;
788 }
789
790 /**
791  * get a vector that is stored in 3 custom properties (used in Blender <= 2.78)
792  */
793 void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3])
794 {
795         val[0] = bc_get_property(bone, key + "_x", def[0]);
796         val[1] = bc_get_property(bone, key + "_y", def[1]);
797         val[2] = bc_get_property(bone, key + "_z", def[2]);
798 }
799
800 /**
801  * Check if vector exist stored in 3 custom properties (used in Blender <= 2.78)
802  */
803 static bool has_custom_props(Bone *bone, bool enabled, std::string key)
804 {
805         if (!enabled)
806                 return false;
807
808         return (bc_get_IDProperty(bone, key + "_x")
809                 ||      bc_get_IDProperty(bone, key + "_y")
810                 ||      bc_get_IDProperty(bone, key + "_z"));
811
812 }
813
814 /**
815  * Check if custom information about bind matrix exists and modify the from_mat
816  * accordingly.
817  *
818  * Note: This is old style for Blender <= 2.78 only kept for compatibility
819  */
820 void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space)
821 {
822         float loc[3];
823         float rot[3];
824         float scale[3];
825         static const float V0[3] = { 0, 0, 0 };
826
827         if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") &&
828                 !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") &&
829                 !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale"))
830         {
831                 /* No need */
832                 copy_m4_m4(to_mat, from_mat);
833                 return;
834         }
835
836         bc_decompose(from_mat, loc, rot, NULL, scale);
837         loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
838
839         if (export_settings->keep_bind_info) {
840                 bc_get_property_vector(bone, "restpose_loc", loc, loc);
841
842                 if (use_local_space && bone->parent) {
843                         Bone *b = bone;
844                         while (b->parent) {
845                                 b = b->parent;
846                                 float ploc[3];
847                                 bc_get_property_vector(b, "restpose_loc", ploc, V0);
848                                 loc[0] += ploc[0];
849                                 loc[1] += ploc[1];
850                                 loc[2] += ploc[2];
851                         }
852                 }
853         }
854
855         if (export_settings->keep_bind_info) {
856                 if (bc_get_IDProperty(bone, "restpose_rot_x"))
857                     rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0));
858                 if (bc_get_IDProperty(bone, "restpose_rot_y"))
859                         rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0));
860                 if (bc_get_IDProperty(bone, "restpose_rot_z"))
861                         rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0));
862         }
863
864         if (export_settings->keep_bind_info) {
865                 bc_get_property_vector(bone, "restpose_scale", scale, scale);
866         }
867
868         loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
869
870 }
871
872 /*
873  * Make 4*4 matrices better readable
874  */
875 void bc_sanitize_mat(float mat[4][4], int precision)
876 {
877         for (int i = 0; i < 4; i++)
878                 for (int j = 0; j < 4; j++)
879                         mat[i][j] = double_round(mat[i][j], precision);
880 }
881
882 void bc_sanitize_mat(double mat[4][4], int precision)
883 {
884         for (int i = 0; i < 4; i++)
885                 for (int j = 0; j < 4; j++)
886                         mat[i][j] = double_round(mat[i][j], precision);
887 }
888
889 void bc_copy_m4_farray(float r[4][4], float *a)
890 {
891         for (int i = 0; i < 4; i++)
892                 for (int j = 0; j < 4; j++)
893                         r[i][j] = *a++;
894 }
895
896 void bc_copy_farray_m4(float *r, float a[4][4])
897 {
898         for (int i = 0; i < 4; i++)
899                 for (int j = 0; j < 4; j++)
900                         *r++ = a[i][j];
901
902 }
903
904 /*
905 * Returns name of Active UV Layer or empty String if no active UV Layer defined.
906 * Assuming the Object is of type MESH
907 */
908 std::string bc_get_active_uvlayer_name(Object *ob)
909 {
910         Mesh *me = (Mesh *)ob->data;
911         return bc_get_active_uvlayer_name(me);
912 }
913
914 /**
915  * Returns name of Active UV Layer or empty String if no active UV Layer defined
916  */
917 std::string bc_get_active_uvlayer_name(Mesh *me)
918 {
919         int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
920         if (num_layers) {
921                 char *layer_name = bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE);
922                 if (layer_name) {
923                         return std::string(layer_name);
924                 }
925         }
926         return "";
927 }
928
929 /*
930  * Returns UV Layer name or empty string if layer index is out of range
931  */
932 std::string bc_get_uvlayer_name(Mesh *me, int layer)
933 {
934         int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
935         if (num_layers && layer < num_layers) {
936                 char *layer_name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, layer);
937                 if (layer_name) {
938                         return std::string(layer_name);
939                 }
940         }
941         return "";
942 }
943
944 /**********************************************************************
945 *
946 * Return the list of Mesh objects with assigned UVtextures and Images
947 * Note: We need to create artificaial materials for each of them
948 *
949 ***********************************************************************/
950 std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers)
951 {
952         std::set <Object *> UVObjects;
953         Base *base = (Base *)sce->base.first;
954
955         while (base) {
956                 Object *ob = base->object;
957                 bool has_uvimage = false;
958                 if (ob->type == OB_MESH) {
959                         Mesh *me = (Mesh *)ob->data;
960                         int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
961
962                         for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
963                                 if (all_uv_layers || active_uv_layer == i)
964                                 {
965                                         if (me->pdata.layers[i].type == CD_MTEXPOLY) {
966                                                 MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
967                                                 MPoly *mpoly = me->mpoly;
968                                                 for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
969
970                                                         Image *ima = txface->tpage;
971                                                         if (ima != NULL) {
972                                                                 has_uvimage = true;
973                                                                 break;
974                                                         }
975                                                 }
976                                         }
977                                 }
978                         }
979
980                         if (has_uvimage) {
981                                 UVObjects.insert(ob);
982                         }
983                 }
984                 base = base->next;
985         }
986         return UVObjects;
987 }
988
989 /**********************************************************************
990 *
991 * Return the list of UV Texture images from all exported Mesh Items
992 * Note: We need to create one artificial material for each Image.
993 *
994 ***********************************************************************/
995 std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers)
996 {
997         std::set <Image *> UVImages;
998         Base *base = (Base *)sce->base.first;
999
1000         while (base) {
1001                 Object *ob = base->object;
1002                 bool has_uvimage = false;
1003                 if (ob->type == OB_MESH) {
1004                         Mesh *me = (Mesh *)ob->data;
1005                         int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
1006
1007                         for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
1008                                 if (all_uv_layers || active_uv_layer == i)
1009                                 {
1010                                         if (me->pdata.layers[i].type == CD_MTEXPOLY) {
1011                                                 MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
1012                                                 MPoly *mpoly = me->mpoly;
1013                                                 for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
1014
1015                                                         Image *ima = txface->tpage;
1016                                                         if (ima != NULL) {
1017                                                                 if (UVImages.find(ima) == UVImages.end())
1018                                                                         UVImages.insert(ima);
1019                                                         }
1020                                                 }
1021                                         }
1022                                 }
1023                         }
1024                 }
1025                 base = base->next;
1026         }
1027         return UVImages;
1028 }
1029
1030 /**********************************************************************
1031 *
1032 * Return the list of UV Texture images for the given Object
1033 * Note: We need to create one artificial material for each Image.
1034 *
1035 ***********************************************************************/
1036 std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers)
1037 {
1038         std::set <Image *> UVImages;
1039
1040         bool has_uvimage = false;
1041         if (ob->type == OB_MESH) {
1042                 Mesh *me = (Mesh *)ob->data;
1043                 int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
1044
1045                 for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
1046                         if (all_uv_layers || active_uv_layer == i)
1047                         {
1048                                 if (me->pdata.layers[i].type == CD_MTEXPOLY) {
1049                                         MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
1050                                         MPoly *mpoly = me->mpoly;
1051                                         for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
1052
1053                                                 Image *ima = txface->tpage;
1054                                                 if (ima != NULL) {
1055                                                         if (UVImages.find(ima) == UVImages.end())
1056                                                                 UVImages.insert(ima);
1057                                                 }
1058                                         }
1059                                 }
1060                         }
1061                 }
1062         }
1063         return UVImages;
1064 }