1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 */
16
17 /** \file
18 * \ingroup collada
19 */
20
21 #include "COLLADASWBaseInputElement.h"
22 #include "COLLADASWInstanceController.h"
23 #include "COLLADASWPrimitves.h"
24 #include "COLLADASWSource.h"
25
26 #include "DNA_action_types.h"
27 #include "DNA_meshdata_types.h"
28 #include "DNA_modifier_types.h"
29
30 #include "BKE_action.h"
31 #include "BKE_armature.h"
32 #include "BKE_global.h"
33 #include "BKE_idprop.h"
34 #include "BKE_lib_id.h"
35 #include "BKE_mesh.h"
36
37 #include "ED_armature.h"
38
39 #include "BLI_listbase.h"
40
41 #include "ArmatureExporter.h"
42 #include "ControllerExporter.h"
43 #include "GeometryExporter.h"
44 #include "SceneExporter.h"
45
46 #include "collada_utils.h"
47
is_skinned_mesh(Object * ob)48 bool ControllerExporter::is_skinned_mesh(Object *ob)
49 {
50 return bc_get_assigned_armature(ob) != NULL;
51 }
52
write_bone_URLs(COLLADASW::InstanceController & ins,Object * ob_arm,Bone * bone)53 void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins,
54 Object *ob_arm,
55 Bone *bone)
56 {
57 if (bc_is_root_bone(bone, this->export_settings.get_deform_bones_only())) {
58 std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name);
59 ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, node_id));
60 }
61 else {
62 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
63 write_bone_URLs(ins, ob_arm, child);
64 }
65 }
66 }
67
add_instance_controller(Object * ob)68 bool ControllerExporter::add_instance_controller(Object *ob)
69 {
70 Object *ob_arm = bc_get_assigned_armature(ob);
71 bArmature *arm = (bArmature *)ob_arm->data;
72
73 const std::string &controller_id = get_controller_id(ob_arm, ob);
74
75 COLLADASW::InstanceController ins(mSW);
76 ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
77
78 Mesh *me = (Mesh *)ob->data;
79 if (!me->dvert) {
80 return false;
81 }
82
83 /* write root bone URLs */
84 Bone *bone;
85 for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) {
86 write_bone_URLs(ins, ob_arm, bone);
87 }
88
89 InstanceWriter::add_material_bindings(
90 ins.getBindMaterial(), ob, this->export_settings.get_active_uv_only());
91
92 ins.add();
93 return true;
94 }
95
export_controllers()96 void ControllerExporter::export_controllers()
97 {
98 Scene *sce = blender_context.get_scene();
99 openLibrary();
100
101 GeometryFunctor gf;
102 gf.forEachMeshObjectInExportSet<ControllerExporter>(
103 sce, *this, this->export_settings.get_export_set());
104
105 closeLibrary();
106 }
107
operator ()(Object * ob)108 void ControllerExporter::operator()(Object *ob)
109 {
110 Object *ob_arm = bc_get_assigned_armature(ob);
111 Key *key = BKE_key_from_object(ob);
112
113 if (ob_arm) {
114 export_skin_controller(ob, ob_arm);
115 }
116 if (key && this->export_settings.get_include_shapekeys()) {
117 export_morph_controller(ob, key);
118 }
119 }
120 #if 0
121
122 bool ArmatureExporter::already_written(Object *ob_arm)
123 {
124 return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) !=
125 written_armatures.end();
126 }
127
128 void ArmatureExporter::wrote(Object *ob_arm)
129 {
130 written_armatures.push_back(ob_arm);
131 }
132
133 void ArmatureExporter::find_objects_using_armature(Object *ob_arm,
134 std::vector<Object *> &objects,
135 Scene *sce)
136 {
137 objects.clear();
138
139 Base *base = (Base *)sce->base.first;
140 while (base) {
141 Object *ob = base->object;
142
143 if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) {
144 objects.push_back(ob);
145 }
146
147 base = base->next;
148 }
149 }
150 #endif
151
get_controller_id(Object * ob_arm,Object * ob)152 std::string ControllerExporter::get_controller_id(Object *ob_arm, Object *ob)
153 {
154 return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) +
155 SKIN_CONTROLLER_ID_SUFFIX;
156 }
157
get_controller_id(Key * key,Object * ob)158 std::string ControllerExporter::get_controller_id(Key *key, Object *ob)
159 {
160 return translate_id(id_name(ob)) + MORPH_CONTROLLER_ID_SUFFIX;
161 }
162
163 /* ob should be of type OB_MESH
164 * both args are required */
export_skin_controller(Object * ob,Object * ob_arm)165 void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
166 {
167 /* joint names
168 * joint inverse bind matrices
169 * vertex weights */
170
171 /* input:
172 * joint names: ob -> vertex group names
173 * vertex group weights: me->dvert -> groups -> index, weight */
174
175 bool use_instantiation = this->export_settings.get_use_object_instantiation();
176 Mesh *me;
177
178 if (((Mesh *)ob->data)->dvert == NULL) {
179 return;
180 }
181
182 me = bc_get_mesh_copy(blender_context,
183 ob,
184 this->export_settings.get_export_mesh_type(),
185 this->export_settings.get_apply_modifiers(),
186 this->export_settings.get_triangulate());
187
188 std::string controller_name = id_name(ob_arm);
189 std::string controller_id = get_controller_id(ob_arm, ob);
190
191 openSkin(controller_id,
192 controller_name,
193 COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation)));
194
195 add_bind_shape_mat(ob);
196
197 std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id);
198 std::string inv_bind_mat_source_id = add_inv_bind_mats_source(
199 ob_arm, &ob->defbase, controller_id);
200
201 std::list<int> vcounts;
202 std::list<int> joints;
203 std::list<float> weights;
204
205 {
206 int i, j;
207
208 /* def group index -> joint index */
209 std::vector<int> joint_index_by_def_index;
210 bDeformGroup *def;
211
212 for (def = (bDeformGroup *)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) {
213 if (is_bone_defgroup(ob_arm, def)) {
214 joint_index_by_def_index.push_back(j++);
215 }
216 else {
217 joint_index_by_def_index.push_back(-1);
218 }
219 }
220
221 int oob_counter = 0;
222 for (i = 0; i < me->totvert; i++) {
223 MDeformVert *vert = &me->dvert[i];
224 std::map<int, float> jw;
225
226 /* We're normalizing the weights later */
227 float sumw = 0.0f;
228
229 for (j = 0; j < vert->totweight; j++) {
230 uint idx = vert->dw[j].def_nr;
231 if (idx >= joint_index_by_def_index.size()) {
232 /* XXX: Maybe better find out where and
233 * why the Out Of Bound indexes get created ? */
234 oob_counter += 1;
235 }
236 else {
237 int joint_index = joint_index_by_def_index[idx];
238 if (joint_index != -1 && vert->dw[j].weight > 0.0f) {
239 jw[joint_index] += vert->dw[j].weight;
240 sumw += vert->dw[j].weight;
241 }
242 }
243 }
244
245 if (sumw > 0.0f) {
246 float invsumw = 1.0f / sumw;
247 vcounts.push_back(jw.size());
248 for (std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m) {
249 joints.push_back((*m).first);
250 weights.push_back(invsumw * (*m).second);
251 }
252 }
253 else {
254 vcounts.push_back(0);
255 #if 0
256 vcounts.push_back(1);
257 joints.push_back(-1);
258 weights.push_back(1.0f);
259 #endif
260 }
261 }
262
263 if (oob_counter > 0) {
264 fprintf(stderr,
265 "Ignored %d Vertex weights which use index to non existing VGroup %zu.\n",
266 oob_counter,
267 joint_index_by_def_index.size());
268 }
269 }
270
271 std::string weights_source_id = add_weights_source(me, controller_id, weights);
272 add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
273 add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
274
275 BKE_id_free(NULL, me);
276
277 closeSkin();
278 closeController();
279 }
280
export_morph_controller(Object * ob,Key * key)281 void ControllerExporter::export_morph_controller(Object *ob, Key *key)
282 {
283 bool use_instantiation = this->export_settings.get_use_object_instantiation();
284 Mesh *me;
285
286 me = bc_get_mesh_copy(blender_context,
287 ob,
288 this->export_settings.get_export_mesh_type(),
289 this->export_settings.get_apply_modifiers(),
290 this->export_settings.get_triangulate());
291
292 std::string controller_name = id_name(ob) + "-morph";
293 std::string controller_id = get_controller_id(key, ob);
294
295 openMorph(
296 controller_id,
297 controller_name,
298 COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation)));
299
300 std::string targets_id = add_morph_targets(key, ob);
301 std::string morph_weights_id = add_morph_weights(key, ob);
302
303 COLLADASW::TargetsElement targets(mSW);
304
305 COLLADASW::InputList &input = targets.getInputList();
306
307 input.push_back(COLLADASW::Input(
308 COLLADASW::InputSemantic::MORPH_TARGET, /* constant declared in COLLADASWInputList.h */
309 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, targets_id)));
310 input.push_back(
311 COLLADASW::Input(COLLADASW::InputSemantic::MORPH_WEIGHT,
312 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, morph_weights_id)));
313 targets.add();
314
315 BKE_id_free(NULL, me);
316
317 /* support for animations
318 * can also try the base element and param alternative */
319 add_weight_extras(key);
320 closeMorph();
321 closeController();
322 }
323
add_morph_targets(Key * key,Object * ob)324 std::string ControllerExporter::add_morph_targets(Key *key, Object *ob)
325 {
326 std::string source_id = translate_id(id_name(ob)) + TARGETS_SOURCE_ID_SUFFIX;
327
328 COLLADASW::IdRefSource source(mSW);
329 source.setId(source_id);
330 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
331 source.setAccessorCount(key->totkey - 1);
332 source.setAccessorStride(1);
333
334 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
335 param.push_back("IDREF");
336
337 source.prepareToAppendValues();
338
339 KeyBlock *kb = (KeyBlock *)key->block.first;
340 /* skip the basis */
341 kb = kb->next;
342 for (; kb; kb = kb->next) {
343 std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name);
344 source.appendValues(geom_id);
345 }
346
347 source.finish();
348
349 return source_id;
350 }
351
add_morph_weights(Key * key,Object * ob)352 std::string ControllerExporter::add_morph_weights(Key *key, Object *ob)
353 {
354 std::string source_id = translate_id(id_name(ob)) + WEIGHTS_SOURCE_ID_SUFFIX;
355
356 COLLADASW::FloatSourceF source(mSW);
357 source.setId(source_id);
358 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
359 source.setAccessorCount(key->totkey - 1);
360 source.setAccessorStride(1);
361
362 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
363 param.push_back("MORPH_WEIGHT");
364
365 source.prepareToAppendValues();
366
367 KeyBlock *kb = (KeyBlock *)key->block.first;
368 /* skip the basis */
369 kb = kb->next;
370 for (; kb; kb = kb->next) {
371 float weight = kb->curval;
372 source.appendValues(weight);
373 }
374 source.finish();
375
376 return source_id;
377 }
378
379 /* Added to implement support for animations. */
add_weight_extras(Key * key)380 void ControllerExporter::add_weight_extras(Key *key)
381 {
382 /* can also try the base element and param alternative */
383 COLLADASW::BaseExtraTechnique extra;
384
385 KeyBlock *kb = (KeyBlock *)key->block.first;
386 /* skip the basis */
387 kb = kb->next;
388 for (; kb; kb = kb->next) {
389 /* XXX why is the weight not used here and set to 0.0?
390 * float weight = kb->curval; */
391 extra.addExtraTechniqueParameter("KHR", "morph_weights", 0.000, "MORPH_WEIGHT_TO_TARGET");
392 }
393 }
394
add_joints_element(ListBase * defbase,const std::string & joints_source_id,const std::string & inv_bind_mat_source_id)395 void ControllerExporter::add_joints_element(ListBase *defbase,
396 const std::string &joints_source_id,
397 const std::string &inv_bind_mat_source_id)
398 {
399 COLLADASW::JointsElement joints(mSW);
400 COLLADASW::InputList &input = joints.getInputList();
401
402 input.push_back(COLLADASW::Input(
403 COLLADASW::InputSemantic::JOINT, /* constant declared in COLLADASWInputList.h */
404 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id)));
405 input.push_back(
406 COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX,
407 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id)));
408 joints.add();
409 }
410
add_bind_shape_mat(Object * ob)411 void ControllerExporter::add_bind_shape_mat(Object *ob)
412 {
413 double bind_mat[4][4];
414 float f_obmat[4][4];
415 BKE_object_matrix_local_get(ob, f_obmat);
416
417 if (export_settings.get_apply_global_orientation()) {
418 /* do nothing, rotation is going to be applied to the Data */
419 }
420 else {
421 bc_add_global_transform(f_obmat, export_settings.get_global_transform());
422 }
423
424 // UnitConverter::mat4_to_dae_double(bind_mat, ob->obmat);
425 UnitConverter::mat4_to_dae_double(bind_mat, f_obmat);
426 if (this->export_settings.get_limit_precision()) {
427 BCMatrix::sanitize(bind_mat, LIMITTED_PRECISION);
428 }
429
430 addBindShapeTransform(bind_mat);
431 }
432
add_joints_source(Object * ob_arm,ListBase * defbase,const std::string & controller_id)433 std::string ControllerExporter::add_joints_source(Object *ob_arm,
434 ListBase *defbase,
435 const std::string &controller_id)
436 {
437 std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
438
439 int totjoint = 0;
440 bDeformGroup *def;
441 for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
442 if (is_bone_defgroup(ob_arm, def)) {
443 totjoint++;
444 }
445 }
446
447 COLLADASW::NameSource source(mSW);
448 source.setId(source_id);
449 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
450 source.setAccessorCount(totjoint);
451 source.setAccessorStride(1);
452
453 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
454 param.push_back("JOINT");
455
456 source.prepareToAppendValues();
457
458 for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
459 Bone *bone = get_bone_from_defgroup(ob_arm, def);
460 if (bone) {
461 source.appendValues(get_joint_sid(bone));
462 }
463 }
464
465 source.finish();
466
467 return source_id;
468 }
469
add_inv_bind_mats_source(Object * ob_arm,ListBase * defbase,const std::string & controller_id)470 std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm,
471 ListBase *defbase,
472 const std::string &controller_id)
473 {
474 std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
475
476 int totjoint = 0;
477 for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
478 if (is_bone_defgroup(ob_arm, def)) {
479 totjoint++;
480 }
481 }
482
483 COLLADASW::FloatSourceF source(mSW);
484 source.setId(source_id);
485 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
486 source.setAccessorCount(totjoint); // BLI_listbase_count(defbase));
487 source.setAccessorStride(16);
488
489 source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
490 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
491 param.push_back("TRANSFORM");
492
493 source.prepareToAppendValues();
494
495 bPose *pose = ob_arm->pose;
496 bArmature *arm = (bArmature *)ob_arm->data;
497
498 int flag = arm->flag;
499
500 /* put armature in rest position */
501 if (!(arm->flag & ARM_RESTPOS)) {
502 Depsgraph *depsgraph = blender_context.get_depsgraph();
503 Scene *scene = blender_context.get_scene();
504
505 arm->flag |= ARM_RESTPOS;
506 BKE_pose_where_is(depsgraph, scene, ob_arm);
507 }
508
509 for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
510 if (is_bone_defgroup(ob_arm, def)) {
511 bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name);
512
513 float mat[4][4];
514 float world[4][4];
515 float inv_bind_mat[4][4];
516
517 float bind_mat[4][4]; /* derived from bone->arm_mat */
518
519 bool has_bindmat = bc_get_property_matrix(pchan->bone, "bind_mat", bind_mat);
520
521 if (!has_bindmat) {
522
523 /* Have no bind matrix stored, try old style <= Blender 2.78 */
524
525 bc_create_restpose_mat(
526 this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true);
527
528 /* SL/OPEN_SIM COMPATIBILITY */
529 if (export_settings.get_open_sim()) {
530 float loc[3];
531 float rot[3] = {0, 0, 0};
532 float scale[3];
533 bc_decompose(bind_mat, loc, NULL, NULL, scale);
534
535 /* Only translations, no rotation vs armature */
536 loc_eulO_size_to_mat4(bind_mat, loc, rot, scale, 6);
537 }
538 }
539
540 /* make world-space matrix (bind_mat is armature-space) */
541 mul_m4_m4m4(world, ob_arm->obmat, bind_mat);
542
543 if (!has_bindmat) {
544 if (export_settings.get_apply_global_orientation()) {
545 bc_apply_global_transform(world, export_settings.get_global_transform());
546 }
547 }
548
549 invert_m4_m4(mat, world);
550 UnitConverter::mat4_to_dae(inv_bind_mat, mat);
551 if (this->export_settings.get_limit_precision()) {
552 BCMatrix::sanitize(inv_bind_mat, LIMITTED_PRECISION);
553 }
554 source.appendValues(inv_bind_mat);
555 }
556 }
557
558 /* back from rest position */
559 if (!(flag & ARM_RESTPOS)) {
560 Depsgraph *depsgraph = blender_context.get_depsgraph();
561 Scene *scene = blender_context.get_scene();
562 arm->flag = flag;
563 BKE_pose_where_is(depsgraph, scene, ob_arm);
564 }
565
566 source.finish();
567
568 return source_id;
569 }
570
get_bone_from_defgroup(Object * ob_arm,bDeformGroup * def)571 Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def)
572 {
573 bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name);
574 return pchan ? pchan->bone : NULL;
575 }
576
is_bone_defgroup(Object * ob_arm,bDeformGroup * def)577 bool ControllerExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup *def)
578 {
579 return get_bone_from_defgroup(ob_arm, def) != NULL;
580 }
581
add_weights_source(Mesh * me,const std::string & controller_id,const std::list<float> & weights)582 std::string ControllerExporter::add_weights_source(Mesh *me,
583 const std::string &controller_id,
584 const std::list<float> &weights)
585 {
586 std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
587
588 COLLADASW::FloatSourceF source(mSW);
589 source.setId(source_id);
590 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
591 source.setAccessorCount(weights.size());
592 source.setAccessorStride(1);
593
594 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
595 param.push_back("WEIGHT");
596
597 source.prepareToAppendValues();
598
599 for (std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) {
600 source.appendValues(*i);
601 }
602
603 source.finish();
604
605 return source_id;
606 }
607
add_vertex_weights_element(const std::string & weights_source_id,const std::string & joints_source_id,const std::list<int> & vcounts,const std::list<int> & joints)608 void ControllerExporter::add_vertex_weights_element(const std::string &weights_source_id,
609 const std::string &joints_source_id,
610 const std::list<int> &vcounts,
611 const std::list<int> &joints)
612 {
613 COLLADASW::VertexWeightsElement weightselem(mSW);
614 COLLADASW::InputList &input = weightselem.getInputList();
615
616 int offset = 0;
617 input.push_back(COLLADASW::Input(
618 COLLADASW::InputSemantic::JOINT, /* constant declared in COLLADASWInputList.h */
619 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id),
620 offset++));
621 input.push_back(
622 COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT,
623 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id),
624 offset++));
625
626 weightselem.setCount(vcounts.size());
627
628 /* write number of deformers per vertex */
629 COLLADASW::PrimitivesBase::VCountList vcountlist;
630
631 vcountlist.resize(vcounts.size());
632 std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin());
633
634 weightselem.prepareToAppendVCountValues();
635 weightselem.appendVertexCount(vcountlist);
636
637 weightselem.CloseVCountAndOpenVElement();
638
639 /* write deformer index - weight index pairs */
640 int weight_index = 0;
641 for (std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i) {
642 weightselem.appendValues(*i, weight_index++);
643 }
644
645 weightselem.finish();
646 }
647