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