~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

Viewing changes to source/blender/collada/ArmatureExporter.cpp

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2012-07-23 08:54:18 UTC
  • mfrom: (14.2.16 sid)
  • mto: (14.2.19 sid)
  • mto: This revision was merged to the branch mainline in revision 42.
  • Revision ID: package-import@ubuntu.com-20120723085418-9foz30v6afaf5ffs
Tags: 2.63a-2
* debian/: Cycles support added (Closes: #658075)
  For now, this top feature has been enabled only
  on [any-amd64 any-i386] architectures because
  of OpenImageIO failing on all others
* debian/: scripts installation path changed
  from /usr/lib to /usr/share:
  + debian/patches/: patchset re-worked for path changing
  + debian/control: "Breaks" field added on yafaray-exporter

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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, Jan Diederich, Tod Liverseed,
 
19
 *                 Nathan Letwory
 
20
 *
 
21
 * ***** END GPL LICENSE BLOCK *****
 
22
 */
 
23
 
 
24
/** \file blender/collada/ArmatureExporter.cpp
 
25
 *  \ingroup collada
 
26
 */
 
27
 
 
28
 
 
29
#include "COLLADASWBaseInputElement.h"
 
30
#include "COLLADASWInstanceController.h"
 
31
#include "COLLADASWPrimitves.h"
 
32
#include "COLLADASWSource.h"
 
33
 
 
34
#include "DNA_action_types.h"
 
35
#include "DNA_meshdata_types.h"
 
36
#include "DNA_modifier_types.h"
 
37
 
 
38
#include "BKE_action.h"
 
39
#include "BKE_armature.h"
 
40
#include "ED_armature.h"
 
41
 
 
42
#include "BLI_listbase.h"
 
43
 
 
44
#include "GeometryExporter.h"
 
45
#include "ArmatureExporter.h"
 
46
#include "SceneExporter.h"
 
47
 
 
48
// XXX exporter writes wrong data for shared armatures.  A separate
 
49
// controller should be written for each armature-mesh binding how do
 
50
// we make controller ids then?
 
51
ArmatureExporter::ArmatureExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryControllers(sw), export_settings(export_settings) {}
 
52
 
 
53
// write bone nodes
 
54
void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene* sce,
 
55
                                                                                  SceneExporter* se,
 
56
                                                                                  std::list<Object*>& child_objects)
 
57
{
 
58
        // write bone nodes
 
59
        bArmature *arm = (bArmature*)ob_arm->data;
 
60
        for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) {
 
61
                // start from root bones
 
62
                if (!bone->parent)
 
63
                        add_bone_node(bone, ob_arm, sce, se, child_objects);
 
64
        }
 
65
}
 
66
 
 
67
bool ArmatureExporter::is_skinned_mesh(Object *ob)
 
68
{
 
69
        return get_assigned_armature(ob) != NULL;
 
70
}
 
71
 
 
72
void ArmatureExporter::add_instance_controller(Object *ob)
 
73
{
 
74
        Object *ob_arm = get_assigned_armature(ob);
 
75
        bArmature *arm = (bArmature*)ob_arm->data;
 
76
 
 
77
        const std::string& controller_id = get_controller_id(ob_arm, ob);
 
78
 
 
79
        COLLADASW::InstanceController ins(mSW);
 
80
        ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
 
81
 
 
82
        // write root bone URLs
 
83
        Bone *bone;
 
84
        for (bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) {
 
85
                if (!bone->parent)
 
86
                        ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm)));
 
87
        }
 
88
 
 
89
        InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob);
 
90
                
 
91
        ins.add();
 
92
}
 
93
 
 
94
void ArmatureExporter::export_controllers(Scene *sce)
 
95
{
 
96
        scene = sce;
 
97
 
 
98
        openLibrary();
 
99
 
 
100
        GeometryFunctor gf;
 
101
        gf.forEachMeshObjectInScene<ArmatureExporter>(sce, *this, this->export_settings->selected);
 
102
 
 
103
        closeLibrary();
 
104
}
 
105
 
 
106
void ArmatureExporter::operator()(Object *ob)
 
107
{
 
108
        Object *ob_arm = get_assigned_armature(ob);
 
109
 
 
110
        if (ob_arm /*&& !already_written(ob_arm)*/)
 
111
                export_controller(ob, ob_arm);
 
112
}
 
113
#if 0
 
114
 
 
115
bool ArmatureExporter::already_written(Object *ob_arm)
 
116
{
 
117
        return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end();
 
118
}
 
119
 
 
120
void ArmatureExporter::wrote(Object *ob_arm)
 
121
{
 
122
        written_armatures.push_back(ob_arm);
 
123
}
 
124
 
 
125
void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce)
 
126
{
 
127
        objects.clear();
 
128
 
 
129
        Base *base= (Base*) sce->base.first;
 
130
        while(base) {
 
131
                Object *ob = base->object;
 
132
                
 
133
                if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) {
 
134
                        objects.push_back(ob);
 
135
                }
 
136
 
 
137
                base= base->next;
 
138
        }
 
139
}
 
140
#endif
 
141
 
 
142
Object *ArmatureExporter::get_assigned_armature(Object *ob)
 
143
{
 
144
        Object *ob_arm = NULL;
 
145
 
 
146
        if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
 
147
                ob_arm = ob->parent;
 
148
        }
 
149
        else {
 
150
                ModifierData *mod = (ModifierData*)ob->modifiers.first;
 
151
                while (mod) {
 
152
                        if (mod->type == eModifierType_Armature) {
 
153
                                ob_arm = ((ArmatureModifierData*)mod)->object;
 
154
                        }
 
155
 
 
156
                        mod = mod->next;
 
157
                }
 
158
        }
 
159
 
 
160
        return ob_arm;
 
161
}
 
162
 
 
163
std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm)
 
164
{
 
165
        return get_joint_id(bone, ob_arm);
 
166
}
 
167
 
 
168
// parent_mat is armature-space
 
169
void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene* sce,
 
170
                                                                         SceneExporter* se,
 
171
                                                                         std::list<Object*>& child_objects)
 
172
{
 
173
        std::string node_id = get_joint_id(bone, ob_arm);
 
174
        std::string node_name = std::string(bone->name);
 
175
        std::string node_sid = get_joint_sid(bone, ob_arm);
 
176
 
 
177
        COLLADASW::Node node(mSW);
 
178
 
 
179
        node.setType(COLLADASW::Node::JOINT);
 
180
        node.setNodeId(node_id);
 
181
        node.setNodeName(node_name);
 
182
        node.setNodeSid(node_sid);
 
183
 
 
184
        /*if ( bone->childbase.first == NULL || BLI_countlist(&(bone->childbase))>=2)
 
185
                add_blender_leaf_bone( bone, ob_arm , node );
 
186
        else{*/
 
187
        node.start();
 
188
 
 
189
        add_bone_transform(ob_arm, bone, node);
 
190
 
 
191
        // Write nodes of childobjects, remove written objects from list
 
192
        std::list<Object*>::iterator i = child_objects.begin();
 
193
 
 
194
        while( i != child_objects.end() )
 
195
        {
 
196
                if ((*i)->partype == PARBONE && (0 == strcmp((*i)->parsubstr, bone->name)))
 
197
                {
 
198
                        float backup_parinv[4][4];
 
199
                        copy_m4_m4(backup_parinv, (*i)->parentinv);
 
200
 
 
201
                        // crude, temporary change to parentinv
 
202
                        // so transform gets exported correctly.
 
203
 
 
204
                        // Add bone tail- translation... don't know why
 
205
                        // bone parenting is against the tail of a bone
 
206
                        // and not it's head, seems arbitrary.
 
207
                        (*i)->parentinv[3][1] += bone->length;
 
208
 
 
209
                        // SECOND_LIFE_COMPATIBILITY
 
210
                        // TODO: when such objects are animated as
 
211
                        // single matrix the tweak must be applied
 
212
                        // to the result.
 
213
                        if (export_settings->second_life)
 
214
                        {
 
215
                                // tweak objects parentinverse to match compatibility
 
216
                                float temp[4][4];
 
217
 
 
218
                                copy_m4_m4(temp, bone->arm_mat);
 
219
                                temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
 
220
 
 
221
                                mult_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv);
 
222
                        }
 
223
 
 
224
                        se->writeNodes(*i, sce);
 
225
 
 
226
                        copy_m4_m4((*i)->parentinv, backup_parinv);
 
227
                        child_objects.erase(i++);
 
228
                }
 
229
                else i++;
 
230
        }
 
231
 
 
232
        for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next) {
 
233
                add_bone_node(child, ob_arm, sce, se, child_objects);
 
234
        }
 
235
        node.end();
 
236
        //}
 
237
}
 
238
 
 
239
/*void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADASW::Node& node)
 
240
{
 
241
        node.start();
 
242
        
 
243
        add_bone_transform(ob_arm, bone, node);
 
244
        
 
245
        node.addExtraTechniqueParameter("blender", "tip_x", bone->tail[0] );
 
246
        node.addExtraTechniqueParameter("blender", "tip_y", bone->tail[1] );
 
247
        node.addExtraTechniqueParameter("blender", "tip_z", bone->tail[2] );
 
248
        
 
249
        for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next) {
 
250
                add_bone_node(child, ob_arm, sce, se, child_objects);
 
251
        }
 
252
        node.end();
 
253
        
 
254
}*/
 
255
void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node)
 
256
{
 
257
        bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
 
258
 
 
259
        float mat[4][4];
 
260
 
 
261
        if (bone->parent) {
 
262
                // get bone-space matrix from armature-space
 
263
                bPoseChannel *parchan = get_pose_channel(ob_arm->pose, bone->parent->name);
 
264
 
 
265
                float invpar[4][4];
 
266
                invert_m4_m4(invpar, parchan->pose_mat);
 
267
                mult_m4_m4m4(mat, invpar, pchan->pose_mat);
 
268
        }
 
269
        else {
 
270
                copy_m4_m4(mat, pchan->pose_mat);
 
271
                // Why? Joint's localspace is still it's parent node
 
272
                //get world-space from armature-space
 
273
                //mult_m4_m4m4(mat, ob_arm->obmat, pchan->pose_mat);
 
274
        }
 
275
 
 
276
        // SECOND_LIFE_COMPATIBILITY
 
277
        if (export_settings->second_life)
 
278
        {
 
279
                // Remove rotations vs armature from transform
 
280
                // parent_rest_rot * mat * irest_rot
 
281
                float temp[4][4];
 
282
                copy_m4_m4(temp, bone->arm_mat);
 
283
                temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
 
284
                invert_m4(temp);
 
285
 
 
286
                mult_m4_m4m4(mat, mat, temp);
 
287
 
 
288
                if (bone->parent)
 
289
                {
 
290
                        copy_m4_m4(temp, bone->parent->arm_mat);
 
291
                        temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
 
292
 
 
293
                        mult_m4_m4m4(mat, temp, mat);
 
294
                }
 
295
        }
 
296
 
 
297
        TransformWriter::add_node_transform(node, mat,NULL );
 
298
}
 
299
 
 
300
std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob)
 
301
{
 
302
        return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
 
303
}
 
304
 
 
305
// ob should be of type OB_MESH
 
306
// both args are required
 
307
void ArmatureExporter::export_controller(Object* ob, Object *ob_arm)
 
308
{
 
309
        // joint names
 
310
        // joint inverse bind matrices
 
311
        // vertex weights
 
312
 
 
313
        // input:
 
314
        // joint names: ob -> vertex group names
 
315
        // vertex group weights: me->dvert -> groups -> index, weight
 
316
 
 
317
        /*
 
318
        me->dvert:
 
319
 
 
320
        typedef struct MDeformVert {
 
321
                struct MDeformWeight *dw;
 
322
                int totweight;
 
323
                int flag;       // flag only in use for weightpaint now
 
324
        } MDeformVert;
 
325
 
 
326
        typedef struct MDeformWeight {
 
327
                int                             def_nr;
 
328
                float                   weight;
 
329
        } MDeformWeight;
 
330
        */
 
331
 
 
332
        Mesh *me = (Mesh*)ob->data;
 
333
        if (!me->dvert) return;
 
334
 
 
335
        std::string controller_name = id_name(ob_arm);
 
336
        std::string controller_id = get_controller_id(ob_arm, ob);
 
337
 
 
338
        openSkin(controller_id, controller_name,
 
339
                 COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob)));
 
340
 
 
341
        add_bind_shape_mat(ob);
 
342
 
 
343
        std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id);
 
344
        std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id);
 
345
 
 
346
        std::list<int> vcounts;
 
347
        std::list<int> joints;
 
348
        std::list<float> weights;
 
349
 
 
350
        {
 
351
                int i, j;
 
352
 
 
353
                // def group index -> joint index
 
354
                std::vector<int> joint_index_by_def_index;
 
355
                bDeformGroup *def;
 
356
 
 
357
                for (def = (bDeformGroup*)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) {
 
358
                        if (is_bone_defgroup(ob_arm, def))
 
359
                                joint_index_by_def_index.push_back(j++);
 
360
                        else
 
361
                                joint_index_by_def_index.push_back(-1);
 
362
                }
 
363
 
 
364
                for (i = 0; i < me->totvert; i++) {
 
365
                        MDeformVert *vert = &me->dvert[i];
 
366
                        std::map<int, float> jw;
 
367
 
 
368
                        // We're normalizing the weights later
 
369
                        float sumw = 0.0f;
 
370
 
 
371
                        for (j = 0; j < vert->totweight; j++) {
 
372
                                int joint_index = joint_index_by_def_index[vert->dw[j].def_nr];
 
373
                                if (joint_index != -1 && vert->dw[j].weight > 0.0f)
 
374
                                {
 
375
                                        jw[joint_index] += vert->dw[j].weight;
 
376
                                        sumw += vert->dw[j].weight;
 
377
                                }
 
378
                        }
 
379
 
 
380
                        if (sumw > 0.0f)
 
381
                        {
 
382
                                float invsumw = 1.0f/sumw;
 
383
                                vcounts.push_back(jw.size());
 
384
                                for (std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m)
 
385
                                {
 
386
                                        joints.push_back((*m).first);
 
387
                                        weights.push_back(invsumw*(*m).second);
 
388
                                }
 
389
                        }
 
390
                        else
 
391
                        {
 
392
                                vcounts.push_back(0);
 
393
                                /*vcounts.push_back(1);
 
394
                                joints.push_back(-1);
 
395
                                weights.push_back(1.0f);*/
 
396
                        }
 
397
                }
 
398
        }
 
399
 
 
400
        std::string weights_source_id = add_weights_source(me, controller_id, weights);
 
401
        add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
 
402
        add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
 
403
 
 
404
        closeSkin();
 
405
        closeController();
 
406
}
 
407
 
 
408
void ArmatureExporter::add_joints_element(ListBase *defbase,
 
409
                                                const std::string& joints_source_id, const std::string& inv_bind_mat_source_id)
 
410
{
 
411
        COLLADASW::JointsElement joints(mSW);
 
412
        COLLADASW::InputList &input = joints.getInputList();
 
413
 
 
414
        input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
 
415
                                                           COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id)));
 
416
        input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX,
 
417
                                                           COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id)));
 
418
        joints.add();
 
419
}
 
420
 
 
421
void ArmatureExporter::add_bind_shape_mat(Object *ob)
 
422
{
 
423
        double bind_mat[4][4];
 
424
 
 
425
        converter.mat4_to_dae_double(bind_mat, ob->obmat);
 
426
 
 
427
        addBindShapeTransform(bind_mat);
 
428
}
 
429
 
 
430
std::string ArmatureExporter::add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
 
431
{
 
432
        std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
 
433
 
 
434
        int totjoint = 0;
 
435
        bDeformGroup *def;
 
436
        for (def = (bDeformGroup*)defbase->first; def; def = def->next) {
 
437
                if (is_bone_defgroup(ob_arm, def))
 
438
                        totjoint++;
 
439
        }
 
440
 
 
441
        COLLADASW::NameSource source(mSW);
 
442
        source.setId(source_id);
 
443
        source.setArrayId(source_id + ARRAY_ID_SUFFIX);
 
444
        source.setAccessorCount(totjoint);
 
445
        source.setAccessorStride(1);
 
446
        
 
447
        COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
 
448
        param.push_back("JOINT");
 
449
 
 
450
        source.prepareToAppendValues();
 
451
 
 
452
        for (def = (bDeformGroup*)defbase->first; def; def = def->next) {
 
453
                Bone *bone = get_bone_from_defgroup(ob_arm, def);
 
454
                if (bone)
 
455
                        source.appendValues(get_joint_sid(bone, ob_arm));
 
456
        }
 
457
 
 
458
        source.finish();
 
459
 
 
460
        return source_id;
 
461
}
 
462
 
 
463
std::string ArmatureExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
 
464
{
 
465
        std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
 
466
 
 
467
        int totjoint = 0;
 
468
        for (bDeformGroup *def = (bDeformGroup*)defbase->first; def; def = def->next) {
 
469
                if (is_bone_defgroup(ob_arm, def))
 
470
                        totjoint++;
 
471
        }
 
472
 
 
473
        COLLADASW::FloatSourceF source(mSW);
 
474
        source.setId(source_id);
 
475
        source.setArrayId(source_id + ARRAY_ID_SUFFIX);
 
476
        source.setAccessorCount(totjoint); //BLI_countlist(defbase));
 
477
        source.setAccessorStride(16);
 
478
        
 
479
        source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
 
480
        COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
 
481
        param.push_back("TRANSFORM");
 
482
 
 
483
        source.prepareToAppendValues();
 
484
 
 
485
        bPose *pose = ob_arm->pose;
 
486
        bArmature *arm = (bArmature*)ob_arm->data;
 
487
 
 
488
        int flag = arm->flag;
 
489
 
 
490
        // put armature in rest position
 
491
        if (!(arm->flag & ARM_RESTPOS)) {
 
492
                arm->flag |= ARM_RESTPOS;
 
493
                where_is_pose(scene, ob_arm);
 
494
        }
 
495
 
 
496
        for (bDeformGroup *def = (bDeformGroup*)defbase->first; def; def = def->next) {
 
497
                if (is_bone_defgroup(ob_arm, def)) {
 
498
                        bPoseChannel *pchan = get_pose_channel(pose, def->name);
 
499
 
 
500
                        float mat[4][4];
 
501
                        float world[4][4];
 
502
                        float inv_bind_mat[4][4];
 
503
 
 
504
                        // SECOND_LIFE_COMPATIBILITY
 
505
                        if (export_settings->second_life)
 
506
                        {
 
507
                                // Only translations, no rotation vs armature
 
508
                                float temp[4][4];
 
509
                                unit_m4(temp);
 
510
                                copy_v3_v3(temp[3], pchan->bone->arm_mat[3]);
 
511
                                mult_m4_m4m4(world, ob_arm->obmat, temp);
 
512
                        }
 
513
                        else
 
514
                        {
 
515
                                // make world-space matrix, arm_mat is armature-space
 
516
                                mult_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat);
 
517
                        }
 
518
 
 
519
                        invert_m4_m4(mat, world);
 
520
                        converter.mat4_to_dae(inv_bind_mat, mat);
 
521
 
 
522
                        source.appendValues(inv_bind_mat);
 
523
                }
 
524
        }
 
525
 
 
526
        // back from rest positon
 
527
        if (!(flag & ARM_RESTPOS)) {
 
528
                arm->flag = flag;
 
529
                where_is_pose(scene, ob_arm);
 
530
        }
 
531
 
 
532
        source.finish();
 
533
 
 
534
        return source_id;
 
535
}
 
536
 
 
537
Bone *ArmatureExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup* def)
 
538
{
 
539
        bPoseChannel *pchan = get_pose_channel(ob_arm->pose, def->name);
 
540
        return pchan ? pchan->bone : NULL;
 
541
}
 
542
 
 
543
bool ArmatureExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup* def)
 
544
{
 
545
        return get_bone_from_defgroup(ob_arm, def) != NULL;
 
546
}
 
547
 
 
548
std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& controller_id, const std::list<float>& weights)
 
549
{
 
550
        std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
 
551
 
 
552
        COLLADASW::FloatSourceF source(mSW);
 
553
        source.setId(source_id);
 
554
        source.setArrayId(source_id + ARRAY_ID_SUFFIX);
 
555
        source.setAccessorCount(weights.size());
 
556
        source.setAccessorStride(1);
 
557
        
 
558
        COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
 
559
        param.push_back("WEIGHT");
 
560
 
 
561
        source.prepareToAppendValues();
 
562
 
 
563
        for (std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) {
 
564
                source.appendValues(*i);
 
565
        }
 
566
 
 
567
        source.finish();
 
568
 
 
569
        return source_id;
 
570
}
 
571
 
 
572
void ArmatureExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
 
573
                                                                                                  const std::list<int>& vcounts,
 
574
                                                                                                  const std::list<int>& joints)
 
575
{
 
576
        COLLADASW::VertexWeightsElement weightselem(mSW);
 
577
        COLLADASW::InputList &input = weightselem.getInputList();
 
578
 
 
579
        int offset = 0;
 
580
        input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
 
581
                                                                         COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++));
 
582
        input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT,
 
583
                                                                         COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++));
 
584
 
 
585
        weightselem.setCount(vcounts.size());
 
586
 
 
587
        // write number of deformers per vertex
 
588
        COLLADASW::PrimitivesBase::VCountList vcountlist;
 
589
 
 
590
        vcountlist.resize(vcounts.size());
 
591
        std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin());
 
592
 
 
593
        weightselem.prepareToAppendVCountValues();
 
594
        weightselem.appendVertexCount(vcountlist);
 
595
 
 
596
        weightselem.CloseVCountAndOpenVElement();
 
597
 
 
598
        // write deformer index - weight index pairs
 
599
        int weight_index = 0;
 
600
        for (std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i)
 
601
        {
 
602
                weightselem.appendValues(*i, weight_index++);
 
603
        }
 
604
 
 
605
        weightselem.finish();
 
606
}