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