~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

Viewing changes to source/blender/collada/DocumentExporter.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
 
 * $Id: DocumentExporter.cpp 29323 2010-06-07 20:37:56Z kazanbas $
3
 
 *
 
1
/*
4
2
 * ***** BEGIN GPL LICENSE BLOCK *****
5
3
 *
6
4
 * This program is free software; you can redistribute it and/or
21
19
 *
22
20
 * ***** END GPL LICENSE BLOCK *****
23
21
 */
 
22
 
 
23
/** \file blender/collada/DocumentExporter.cpp
 
24
 *  \ingroup collada
 
25
 */
 
26
 
24
27
#include <stdlib.h>
25
28
#include <stdio.h>
26
29
#include <math.h>
27
30
 
 
31
extern "C" 
 
32
{
28
33
#include "DNA_scene_types.h"
29
34
#include "DNA_object_types.h"
 
35
#include "DNA_group_types.h"
30
36
#include "DNA_meshdata_types.h"
31
37
#include "DNA_mesh_types.h"
32
38
#include "DNA_image_types.h"
33
39
#include "DNA_material_types.h"
34
40
#include "DNA_texture_types.h"
35
 
#include "DNA_camera_types.h"
36
 
#include "DNA_lamp_types.h"
37
41
#include "DNA_anim_types.h"
38
42
#include "DNA_action_types.h"
39
43
#include "DNA_curve_types.h"
40
44
#include "DNA_armature_types.h"
41
45
#include "DNA_modifier_types.h"
 
46
#include "DNA_userdef_types.h"
42
47
 
43
 
extern "C" 
44
 
{
45
48
#include "BKE_DerivedMesh.h"
46
49
#include "BKE_fcurve.h"
47
50
#include "BKE_animsys.h"
48
51
#include "BLI_path_util.h"
49
52
#include "BLI_fileops.h"
50
53
#include "ED_keyframing.h"
 
54
#ifdef WITH_BUILDINFO
 
55
extern char build_rev[];
 
56
#endif
51
57
}
52
58
 
53
59
#include "MEM_guardedalloc.h"
54
60
 
 
61
#include "BKE_blender.h" // version info
55
62
#include "BKE_scene.h"
56
63
#include "BKE_global.h"
57
64
#include "BKE_main.h"
66
73
#include "BLI_string.h"
67
74
#include "BLI_listbase.h"
68
75
 
 
76
#include "RNA_access.h"
 
77
 
69
78
#include "COLLADASWAsset.h"
70
79
#include "COLLADASWLibraryVisualScenes.h"
71
80
#include "COLLADASWNode.h"
72
 
#include "COLLADASWLibraryGeometries.h"
73
81
#include "COLLADASWSource.h"
74
82
#include "COLLADASWInstanceGeometry.h"
75
83
#include "COLLADASWInputList.h"
86
94
#include "COLLADASWSurfaceInitOption.h"
87
95
#include "COLLADASWSampler.h"
88
96
#include "COLLADASWScene.h"
89
 
//#include "COLLADASWSurface.h"
90
97
#include "COLLADASWTechnique.h"
91
98
#include "COLLADASWTexture.h"
92
99
#include "COLLADASWLibraryMaterials.h"
93
100
#include "COLLADASWBindMaterial.h"
94
 
#include "COLLADASWLibraryCameras.h"
95
 
#include "COLLADASWLibraryLights.h"
96
101
#include "COLLADASWInstanceCamera.h"
97
102
#include "COLLADASWInstanceLight.h"
98
 
#include "COLLADASWCameraOptic.h"
99
103
#include "COLLADASWConstants.h"
100
104
#include "COLLADASWLibraryControllers.h"
101
105
#include "COLLADASWInstanceController.h"
 
106
#include "COLLADASWInstanceNode.h"
102
107
#include "COLLADASWBaseInputElement.h"
103
108
 
104
109
#include "collada_internal.h"
105
110
#include "DocumentExporter.h"
 
111
#include "ExportSettings.h"
 
112
 
 
113
// can probably go after refactor is complete
 
114
#include "InstanceWriter.h"
 
115
#include "TransformWriter.h"
 
116
 
 
117
#include "SceneExporter.h"
 
118
#include "ArmatureExporter.h"
 
119
#include "AnimationExporter.h"
 
120
#include "CameraExporter.h"
 
121
#include "EffectExporter.h"
 
122
#include "GeometryExporter.h"
 
123
#include "ImageExporter.h"
 
124
#include "LightExporter.h"
 
125
#include "MaterialExporter.h"
106
126
 
107
127
#include <vector>
108
128
#include <algorithm> // std::find
109
129
 
110
 
// arithb.c now has QuatToAxisAngle too
111
 
#if 0
112
 
// This function assumes that quat is normalized.
113
 
// The following document was used as reference:
114
 
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
115
 
void quat_to_axis_angle( float *axis, float *angle,float *q)
116
 
{
117
 
        // quat to axis angle
118
 
        *angle = 2 * acos(q[0]);
119
 
        float divisor = sqrt(1 - q[0] * q[0]);
120
 
 
121
 
        // test to avoid divide by zero, divisor is always positive
122
 
        if (divisor < 0.001f ) {
123
 
                axis[0] = 1.0f;
124
 
                axis[1] = 0.0f;
125
 
                axis[2] = 0.0f;
126
 
        }
127
 
        else {
128
 
                axis[0] = q[1] / divisor;
129
 
                axis[1] = q[2] / divisor;
130
 
                axis[2] = q[3] / divisor;
131
 
        }
132
 
}
133
 
#endif
134
 
 
135
 
char *CustomData_get_layer_name(const struct CustomData *data, int type, int n)
 
130
char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n)
136
131
{
137
132
        int layer_index = CustomData_get_layer_index(data, type);
138
 
        if(layer_index < 0) return NULL;
 
133
        if (layer_index < 0) return NULL;
139
134
 
140
135
        return data->layers[layer_index+n].name;
141
136
}
142
137
 
143
 
char *CustomData_get_active_layer_name(const CustomData *data, int type)
 
138
char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
144
139
{
145
140
        /* get the layer index of the active layer of type */
146
141
        int layer_index = CustomData_get_active_layer_index(data, type);
147
 
        if(layer_index < 0) return NULL;
 
142
        if (layer_index < 0) return NULL;
148
143
 
149
144
        return data->layers[layer_index].name;
150
145
}
151
146
 
152
 
/**
153
 
Translation map.
154
 
Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be
155
 
included. Look at the IDREF XSD declaration for more.
156
 
Follows strictly the COLLADA XSD declaration which explicitly allows non-english chars,
157
 
like special chars (e.g. micro sign), umlauts and so on.
158
 
The COLLADA spec also allows additional chars for member access ('.'), these
159
 
must obviously be removed too, otherwise they would be heavily misinterpreted.
160
 
*/
161
 
const unsigned char translate_map[256] = {
162
 
        95, 95, 95, 95, 95, 95, 95, 95,
163
 
        95, 95, 95, 95, 95, 95, 95, 95,
164
 
        95, 95, 95, 95, 95, 95, 95, 95,
165
 
        95, 95, 95, 95, 95, 95, 95, 95,
166
 
        95, 95, 95, 95, 95, 95, 95, 95,
167
 
        95, 95, 95, 95, 95, 45, 95, 95,
168
 
        48, 49, 50, 51, 52, 53, 54, 55,
169
 
        56, 57, 95, 95, 95, 95, 95, 95,
170
 
        95, 65, 66, 67, 68, 69, 70, 71,
171
 
        72, 73, 74, 75, 76, 77, 78, 79,
172
 
        80, 81, 82, 83, 84, 85, 86, 87,
173
 
        88, 89, 90, 95, 95, 95, 95, 95,
174
 
        95, 97, 98, 99, 100, 101, 102, 103,
175
 
        104, 105, 106, 107, 108, 109, 110, 111,
176
 
        112, 113, 114, 115, 116, 117, 118, 119,
177
 
        120, 121, 122, 95, 95, 95, 95, 95,
178
 
        95, 95, 95, 95, 95, 95, 95, 95,
179
 
        95, 95, 95, 95, 95, 95, 95, 95,
180
 
        95, 95, 95, 95, 95, 95, 95, 95,
181
 
        95, 95, 95, 95, 95, 95, 95, 95,
182
 
        95, 95, 95, 95, 95, 95, 95, 95,
183
 
        95, 95, 95, 95, 95, 95, 95, 95,
184
 
        95, 95, 95, 95, 95, 95, 95, 183,
185
 
        95, 95, 95, 95, 95, 95, 95, 95,
186
 
        192, 193, 194, 195, 196, 197, 198, 199,
187
 
        200, 201, 202, 203, 204, 205, 206, 207,
188
 
        208, 209, 210, 211, 212, 213, 214, 95,
189
 
        216, 217, 218, 219, 220, 221, 222, 223,
190
 
        224, 225, 226, 227, 228, 229, 230, 231,
191
 
        232, 233, 234, 235, 236, 237, 238, 239,
192
 
        240, 241, 242, 243, 244, 245, 246, 95,
193
 
        248, 249, 250, 251, 252, 253, 254, 255};
194
 
 
195
 
/** Look at documentation of translate_map */
196
 
static std::string translate_id(const std::string &id)
197
 
{
198
 
        std::string id_translated = id;
199
 
        for (unsigned int i=0; i < id_translated.size(); i++)
200
 
        {
201
 
                id_translated[i] = translate_map[(unsigned int)id_translated[i]];
202
 
        }
203
 
        return id_translated;
204
 
}
205
 
 
206
 
static std::string id_name(void *id)
207
 
{
208
 
        return ((ID*)id)->name + 2;
209
 
}
210
 
 
211
 
static std::string get_geometry_id(Object *ob)
212
 
{
213
 
        return translate_id(id_name(ob)) + "-mesh";
214
 
}
215
 
 
216
 
static std::string get_light_id(Object *ob)
217
 
{
218
 
        return translate_id(id_name(ob)) + "-light";
219
 
}
220
 
 
221
 
static std::string get_camera_id(Object *ob)
222
 
{
223
 
        return translate_id(id_name(ob)) + "-camera";
224
 
}
225
 
 
226
 
std::string get_joint_id(Bone *bone, Object *ob_arm)
227
 
{
228
 
        return translate_id(id_name(ob_arm) + "_" + bone->name);
229
 
}
230
 
 
231
 
 
232
 
/*
233
 
  Utilities to avoid code duplication.
234
 
  Definition can take some time to understand, but they should be useful.
235
 
*/
236
 
 
237
 
// f should have
238
 
// void operator()(Object* ob)
239
 
template<class Functor>
240
 
void forEachMeshObjectInScene(Scene *sce, Functor &f)
241
 
{
242
 
        
243
 
        Base *base= (Base*) sce->base.first;
244
 
        while(base) {
245
 
                Object *ob = base->object;
246
 
                
247
 
                if (ob->type == OB_MESH && ob->data) {
248
 
                        f(ob);
249
 
                }
250
 
                base= base->next;
251
 
                
252
 
        }
253
 
}
254
 
 
255
 
template<class Functor>
256
 
void forEachObjectInScene(Scene *sce, Functor &f)
257
 
{
258
 
        Base *base= (Base*) sce->base.first;
259
 
        while(base) {
260
 
                Object *ob = base->object;
261
 
                        
262
 
                f(ob);
263
 
 
264
 
                base= base->next;
265
 
        }
266
 
}
267
 
 
268
 
template<class Functor>
269
 
void forEachCameraObjectInScene(Scene *sce, Functor &f)
270
 
{
271
 
        Base *base= (Base*) sce->base.first;
272
 
        while(base) {
273
 
                Object *ob = base->object;
274
 
                        
275
 
                if (ob->type == OB_CAMERA && ob->data) {
276
 
                        f(ob, sce);
277
 
                }
278
 
                base= base->next;
279
 
        }
280
 
}
281
 
 
282
 
template<class Functor>
283
 
void forEachLampObjectInScene(Scene *sce, Functor &f)
284
 
{
285
 
        Base *base= (Base*) sce->base.first;
286
 
        while(base) {
287
 
                Object *ob = base->object;
288
 
                        
289
 
                if (ob->type == OB_LAMP && ob->data) {
290
 
                        f(ob);
291
 
                }
292
 
                base= base->next;
293
 
        }
294
 
}
295
 
 
296
 
// used in forEachMaterialInScene
297
 
template <class MaterialFunctor>
298
 
class ForEachMaterialFunctor
299
 
{
300
 
        std::vector<std::string> mMat; // contains list of material names, to avoid duplicate calling of f
301
 
        MaterialFunctor *f;
302
 
public:
303
 
        ForEachMaterialFunctor(MaterialFunctor *f) : f(f) { }
304
 
        void operator ()(Object *ob)
305
 
        {
306
 
                int a;
307
 
                for(a = 0; a < ob->totcol; a++) {
308
 
 
309
 
                        Material *ma = give_current_material(ob, a+1);
310
 
 
311
 
                        if (!ma) continue;
312
 
 
313
 
                        std::string translated_id = translate_id(id_name(ma));
314
 
                        if (find(mMat.begin(), mMat.end(), translated_id) == mMat.end()) {
315
 
                                (*this->f)(ma, ob);
316
 
 
317
 
                                mMat.push_back(translated_id);
318
 
                        }
319
 
                }
320
 
        }
321
 
};
322
 
 
323
 
// calls f for each unique material linked to each object in sce
324
 
// f should have
325
 
// void operator()(Material* ma)
326
 
template<class Functor>
327
 
void forEachMaterialInScene(Scene *sce, Functor &f)
328
 
{
329
 
        ForEachMaterialFunctor<Functor> matfunc(&f);
330
 
        forEachMeshObjectInScene(sce, matfunc);
331
 
}
332
 
 
333
 
// OB_MESH is assumed
334
 
std::string getActiveUVLayerName(Object *ob)
335
 
{
336
 
        Mesh *me = (Mesh*)ob->data;
337
 
 
338
 
        int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
339
 
        if (num_layers)
340
 
                return std::string(CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
341
 
                
342
 
        return "";
343
 
}
344
 
 
345
 
// TODO: optimize UV sets by making indexed list with duplicates removed
346
 
class GeometryExporter : COLLADASW::LibraryGeometries
347
 
{
348
 
        struct Face
349
 
        {
350
 
                unsigned int v1, v2, v3, v4;
351
 
        };
352
 
 
353
 
        struct Normal
354
 
        {
355
 
                float x, y, z;
356
 
        };
357
 
 
358
 
        Scene *mScene;
359
 
 
360
 
public:
361
 
        GeometryExporter(COLLADASW::StreamWriter *sw) : COLLADASW::LibraryGeometries(sw) {}
362
 
 
363
 
        void exportGeom(Scene *sce)
364
 
        {
365
 
                openLibrary();
366
 
 
367
 
                mScene = sce;
368
 
                forEachMeshObjectInScene(sce, *this);
369
 
 
370
 
                closeLibrary();
371
 
        }
372
 
 
373
 
        void operator()(Object *ob)
374
 
        {
375
 
                // XXX don't use DerivedMesh, Mesh instead?
376
 
 
377
 
#if 0           
378
 
                DerivedMesh *dm = mesh_get_derived_final(mScene, ob, CD_MASK_BAREMESH);
379
 
#endif
380
 
                Mesh *me = (Mesh*)ob->data;
381
 
                std::string geom_id = get_geometry_id(ob);
382
 
                std::vector<Normal> nor;
383
 
                std::vector<Face> norind;
384
 
 
385
 
                bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL);
386
 
 
387
 
                create_normals(nor, norind, me);
388
 
 
389
 
                // openMesh(geoId, geoName, meshId)
390
 
                openMesh(geom_id);
391
 
                
392
 
                // writes <source> for vertex coords
393
 
                createVertsSource(geom_id, me);
394
 
                
395
 
                // writes <source> for normal coords
396
 
                createNormalsSource(geom_id, me, nor);
397
 
 
398
 
                bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE);
399
 
                
400
 
                // writes <source> for uv coords if mesh has uv coords
401
 
                if (has_uvs)
402
 
                        createTexcoordsSource(geom_id, me);
403
 
 
404
 
                if (has_color)
405
 
                        createVertexColorSource(geom_id, me);
406
 
 
407
 
                // <vertices>
408
 
                COLLADASW::Vertices verts(mSW);
409
 
                verts.setId(getIdBySemantics(geom_id, COLLADASW::VERTEX));
410
 
                COLLADASW::InputList &input_list = verts.getInputList();
411
 
                COLLADASW::Input input(COLLADASW::POSITION, getUrlBySemantics(geom_id, COLLADASW::POSITION));
412
 
                input_list.push_back(input);
413
 
                verts.add();
414
 
 
415
 
                // XXX slow             
416
 
                if (ob->totcol) {
417
 
                        for(int a = 0; a < ob->totcol; a++)     {
418
 
                                // account for NULL materials, this should not normally happen?
419
 
                                Material *ma = give_current_material(ob, a + 1);
420
 
                                createPolylist(ma != NULL, a, has_uvs, has_color, ob, geom_id, norind);
421
 
                        }
422
 
                }
423
 
                else {
424
 
                        createPolylist(false, 0, has_uvs, has_color, ob, geom_id, norind);
425
 
                }
426
 
                
427
 
                closeMesh();
428
 
                closeGeometry();
429
 
                
430
 
#if 0
431
 
                dm->release(dm);
432
 
#endif
433
 
        }
434
 
 
435
 
        // powerful because it handles both cases when there is material and when there's not
436
 
        void createPolylist(bool has_material,
437
 
                                                int material_index,
438
 
                                                bool has_uvs,
439
 
                                                bool has_color,
440
 
                                                Object *ob,
441
 
                                                std::string& geom_id,
442
 
                                                std::vector<Face>& norind)
443
 
        {
444
 
                Mesh *me = (Mesh*)ob->data;
445
 
                MFace *mfaces = me->mface;
446
 
                int totfaces = me->totface;
447
 
 
448
 
                // <vcount>
449
 
                int i;
450
 
                int faces_in_polylist = 0;
451
 
                std::vector<unsigned long> vcount_list;
452
 
 
453
 
                // count faces with this material
454
 
                for (i = 0; i < totfaces; i++) {
455
 
                        MFace *f = &mfaces[i];
456
 
                        
457
 
                        if ((has_material && f->mat_nr == material_index) || !has_material) {
458
 
                                faces_in_polylist++;
459
 
                                if (f->v4 == 0) {
460
 
                                        vcount_list.push_back(3);
461
 
                                }
462
 
                                else {
463
 
                                        vcount_list.push_back(4);
464
 
                                }
465
 
                        }
466
 
                }
467
 
 
468
 
                // no faces using this material
469
 
                if (faces_in_polylist == 0) {
470
 
                        return;
471
 
                }
472
 
                        
473
 
                Material *ma = has_material ? give_current_material(ob, material_index + 1) : NULL;
474
 
                COLLADASW::Polylist polylist(mSW);
475
 
                        
476
 
                // sets count attribute in <polylist>
477
 
                polylist.setCount(faces_in_polylist);
478
 
                        
479
 
                // sets material name
480
 
                if (has_material) {
481
 
                        polylist.setMaterial(translate_id(id_name(ma)));
482
 
                }
483
 
                                
484
 
                COLLADASW::InputList &til = polylist.getInputList();
485
 
                        
486
 
                // creates <input> in <polylist> for vertices 
487
 
                COLLADASW::Input input1(COLLADASW::VERTEX, getUrlBySemantics(geom_id, COLLADASW::VERTEX), 0);
488
 
                        
489
 
                // creates <input> in <polylist> for normals
490
 
                COLLADASW::Input input2(COLLADASW::NORMAL, getUrlBySemantics(geom_id, COLLADASW::NORMAL), 1);
491
 
                        
492
 
                til.push_back(input1);
493
 
                til.push_back(input2);
494
 
                        
495
 
                // if mesh has uv coords writes <input> for TEXCOORD
496
 
                int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
497
 
 
498
 
                for (i = 0; i < num_layers; i++) {
499
 
                        // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
500
 
                        COLLADASW::Input input3(COLLADASW::TEXCOORD,
501
 
                                                                        makeUrl(makeTexcoordSourceId(geom_id, i)),
502
 
                                                                        2, // offset always 2, this is only until we have optimized UV sets
503
 
                                                                        i  // set number equals UV layer index
504
 
                                                                        );
505
 
                        til.push_back(input3);
506
 
                }
507
 
 
508
 
                if (has_color) {
509
 
                        COLLADASW::Input input4(COLLADASW::COLOR, getUrlBySemantics(geom_id, COLLADASW::COLOR), has_uvs ? 3 : 2);
510
 
                        til.push_back(input4);
511
 
                }
512
 
                        
513
 
                // sets <vcount>
514
 
                polylist.setVCountList(vcount_list);
515
 
                        
516
 
                // performs the actual writing
517
 
                polylist.prepareToAppendValues();
518
 
                        
519
 
                // <p>
520
 
                int texindex = 0;
521
 
                for (i = 0; i < totfaces; i++) {
522
 
                        MFace *f = &mfaces[i];
523
 
 
524
 
                        if ((has_material && f->mat_nr == material_index) || !has_material) {
525
 
 
526
 
                                unsigned int *v = &f->v1;
527
 
                                unsigned int *n = &norind[i].v1;
528
 
                                for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) {
529
 
                                        polylist.appendValues(v[j]);
530
 
                                        polylist.appendValues(n[j]);
531
 
 
532
 
                                        if (has_uvs)
533
 
                                                polylist.appendValues(texindex + j);
534
 
 
535
 
                                        if (has_color)
536
 
                                                polylist.appendValues(texindex + j);
537
 
                                }
538
 
                        }
539
 
 
540
 
                        texindex += 3;
541
 
                        if (f->v4 != 0)
542
 
                                texindex++;
543
 
                }
544
 
                        
545
 
                polylist.finish();
546
 
        }
547
 
        
548
 
        // creates <source> for positions
549
 
        void createVertsSource(std::string geom_id, Mesh *me)
550
 
        {
551
 
#if 0
552
 
                int totverts = dm->getNumVerts(dm);
553
 
                MVert *verts = dm->getVertArray(dm);
554
 
#endif
555
 
                int totverts = me->totvert;
556
 
                MVert *verts = me->mvert;
557
 
                
558
 
                COLLADASW::FloatSourceF source(mSW);
559
 
                source.setId(getIdBySemantics(geom_id, COLLADASW::POSITION));
560
 
                source.setArrayId(getIdBySemantics(geom_id, COLLADASW::POSITION) +
561
 
                                                  ARRAY_ID_SUFFIX);
562
 
                source.setAccessorCount(totverts);
563
 
                source.setAccessorStride(3);
564
 
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
565
 
                param.push_back("X");
566
 
                param.push_back("Y");
567
 
                param.push_back("Z");
568
 
                /*main function, it creates <source id = "">, <float_array id = ""
569
 
                  count = ""> */
570
 
                source.prepareToAppendValues();
571
 
                //appends data to <float_array>
572
 
                int i = 0;
573
 
                for (i = 0; i < totverts; i++) {
574
 
                        source.appendValues(verts[i].co[0], verts[i].co[1], verts[i].co[2]);                    
575
 
                }
576
 
                
577
 
                source.finish();
578
 
        
579
 
        }
580
 
 
581
 
        void createVertexColorSource(std::string geom_id, Mesh *me)
582
 
        {
583
 
                if (!CustomData_has_layer(&me->fdata, CD_MCOL))
584
 
                        return;
585
 
 
586
 
                MFace *f;
587
 
                int totcolor = 0, i, j;
588
 
 
589
 
                for (i = 0, f = me->mface; i < me->totface; i++, f++)
590
 
                        totcolor += f->v4 ? 4 : 3;
591
 
 
592
 
                COLLADASW::FloatSourceF source(mSW);
593
 
                source.setId(getIdBySemantics(geom_id, COLLADASW::COLOR));
594
 
                source.setArrayId(getIdBySemantics(geom_id, COLLADASW::COLOR) + ARRAY_ID_SUFFIX);
595
 
                source.setAccessorCount(totcolor);
596
 
                source.setAccessorStride(3);
597
 
 
598
 
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
599
 
                param.push_back("R");
600
 
                param.push_back("G");
601
 
                param.push_back("B");
602
 
 
603
 
                source.prepareToAppendValues();
604
 
 
605
 
                int index = CustomData_get_active_layer_index(&me->fdata, CD_MCOL);
606
 
 
607
 
                MCol *mcol = (MCol*)me->fdata.layers[index].data;
608
 
                MCol *c = mcol;
609
 
 
610
 
                for (i = 0, f = me->mface; i < me->totface; i++, c += 4, f++)
611
 
                        for (j = 0; j < (f->v4 ? 4 : 3); j++)
612
 
                                source.appendValues(c[j].b / 255.0f, c[j].g / 255.0f, c[j].r / 255.0f);
613
 
                
614
 
                source.finish();
615
 
        }
616
 
 
617
 
        std::string makeTexcoordSourceId(std::string& geom_id, int layer_index)
618
 
        {
619
 
                char suffix[20];
620
 
                sprintf(suffix, "-%d", layer_index);
621
 
                return getIdBySemantics(geom_id, COLLADASW::TEXCOORD) + suffix;
622
 
        }
623
 
 
624
 
        //creates <source> for texcoords
625
 
        void createTexcoordsSource(std::string geom_id, Mesh *me)
626
 
        {
627
 
#if 0
628
 
                int totfaces = dm->getNumFaces(dm);
629
 
                MFace *mfaces = dm->getFaceArray(dm);
630
 
#endif
631
 
                int totfaces = me->totface;
632
 
                MFace *mfaces = me->mface;
633
 
 
634
 
                int totuv = 0;
635
 
                int i;
636
 
 
637
 
                // count totuv
638
 
                for (i = 0; i < totfaces; i++) {
639
 
                        MFace *f = &mfaces[i];
640
 
                        if (f->v4 == 0) {
641
 
                                totuv+=3;
642
 
                        }
643
 
                        else {
644
 
                                totuv+=4;
645
 
                        }
646
 
                }
647
 
 
648
 
                int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
649
 
 
650
 
                // write <source> for each layer
651
 
                // each <source> will get id like meshName + "map-channel-1"
652
 
                for (int a = 0; a < num_layers; a++) {
653
 
                        MTFace *tface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, a);
654
 
                        // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, a);
655
 
                        
656
 
                        COLLADASW::FloatSourceF source(mSW);
657
 
                        std::string layer_id = makeTexcoordSourceId(geom_id, a);
658
 
                        source.setId(layer_id);
659
 
                        source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
660
 
                        
661
 
                        source.setAccessorCount(totuv);
662
 
                        source.setAccessorStride(2);
663
 
                        COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
664
 
                        param.push_back("S");
665
 
                        param.push_back("T");
666
 
                        
667
 
                        source.prepareToAppendValues();
668
 
                        
669
 
                        for (i = 0; i < totfaces; i++) {
670
 
                                MFace *f = &mfaces[i];
671
 
                                
672
 
                                for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) {
673
 
                                        source.appendValues(tface[i].uv[j][0],
674
 
                                                                                tface[i].uv[j][1]);
675
 
                                }
676
 
                        }
677
 
                        
678
 
                        source.finish();
679
 
                }
680
 
        }
681
 
 
682
 
 
683
 
        //creates <source> for normals
684
 
        void createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal>& nor)
685
 
        {
686
 
#if 0
687
 
                int totverts = dm->getNumVerts(dm);
688
 
                MVert *verts = dm->getVertArray(dm);
689
 
#endif
690
 
 
691
 
                COLLADASW::FloatSourceF source(mSW);
692
 
                source.setId(getIdBySemantics(geom_id, COLLADASW::NORMAL));
693
 
                source.setArrayId(getIdBySemantics(geom_id, COLLADASW::NORMAL) +
694
 
                                                  ARRAY_ID_SUFFIX);
695
 
                source.setAccessorCount(nor.size());
696
 
                source.setAccessorStride(3);
697
 
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
698
 
                param.push_back("X");
699
 
                param.push_back("Y");
700
 
                param.push_back("Z");
701
 
                
702
 
                source.prepareToAppendValues();
703
 
 
704
 
                std::vector<Normal>::iterator it;
705
 
                for (it = nor.begin(); it != nor.end(); it++) {
706
 
                        Normal& n = *it;
707
 
                        source.appendValues(n.x, n.y, n.z);
708
 
                }
709
 
 
710
 
                source.finish();
711
 
        }
712
 
 
713
 
        void create_normals(std::vector<Normal> &nor, std::vector<Face> &ind, Mesh *me)
714
 
        {
715
 
                int i, j, v;
716
 
                MVert *vert = me->mvert;
717
 
                std::map<unsigned int, unsigned int> nshar;
718
 
 
719
 
                for (i = 0; i < me->totface; i++) {
720
 
                        MFace *fa = &me->mface[i];
721
 
                        Face f;
722
 
                        unsigned int *nn = &f.v1;
723
 
                        unsigned int *vv = &fa->v1;
724
 
 
725
 
                        memset(&f, 0, sizeof(f));
726
 
                        v = fa->v4 == 0 ? 3 : 4;
727
 
 
728
 
                        if (!(fa->flag & ME_SMOOTH)) {
729
 
                                Normal n;
730
 
                                if (v == 4)
731
 
                                        normal_quad_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co, vert[fa->v4].co);
732
 
                                else
733
 
                                        normal_tri_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co);
734
 
                                nor.push_back(n);
735
 
                        }
736
 
 
737
 
                        for (j = 0; j < v; j++) {
738
 
                                if (fa->flag & ME_SMOOTH) {
739
 
                                        if (nshar.find(*vv) != nshar.end())
740
 
                                                *nn = nshar[*vv];
741
 
                                        else {
742
 
                                                Normal n = {
743
 
                                                        vert[*vv].no[0]/32767.0,
744
 
                                                        vert[*vv].no[1]/32767.0,
745
 
                                                        vert[*vv].no[2]/32767.0
746
 
                                                };
747
 
                                                nor.push_back(n);
748
 
                                                *nn = nor.size() - 1;
749
 
                                                nshar[*vv] = *nn;
750
 
                                        }
751
 
                                        vv++;
752
 
                                }
753
 
                                else {
754
 
                                        *nn = nor.size() - 1;
755
 
                                }
756
 
                                nn++;
757
 
                        }
758
 
 
759
 
                        ind.push_back(f);
760
 
                }
761
 
        }
762
 
        
763
 
        std::string getIdBySemantics(std::string geom_id, COLLADASW::Semantics type, std::string other_suffix = "") {
764
 
                return geom_id + getSuffixBySemantic(type) + other_suffix;
765
 
        }
766
 
        
767
 
        
768
 
        COLLADASW::URI getUrlBySemantics(std::string geom_id, COLLADASW::Semantics type, std::string other_suffix = "") {
769
 
                
770
 
                std::string id(getIdBySemantics(geom_id, type, other_suffix));
771
 
                return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
772
 
                
773
 
        }
774
 
 
775
 
        COLLADASW::URI makeUrl(std::string id)
776
 
        {
777
 
                return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
778
 
        }
779
 
        
780
 
 
781
 
        /*      int getTriCount(MFace *faces, int totface) {
782
 
                int i;
783
 
                int tris = 0;
784
 
                for (i = 0; i < totface; i++) {
785
 
                        // if quad
786
 
                        if (faces[i].v4 != 0)
787
 
                                tris += 2;
788
 
                        else
789
 
                                tris++;
790
 
                }
791
 
 
792
 
                return tris;
793
 
                }*/
794
 
};
795
 
 
796
 
class TransformWriter : protected TransformBase
797
 
{
798
 
protected:
799
 
        void add_node_transform(COLLADASW::Node& node, float mat[][4], float parent_mat[][4])
800
 
        {
801
 
                float loc[3], rot[3], scale[3];
802
 
                float local[4][4];
803
 
 
804
 
                if (parent_mat) {
805
 
                        float invpar[4][4];
806
 
                        invert_m4_m4(invpar, parent_mat);
807
 
                        mul_m4_m4m4(local, mat, invpar);
808
 
                }
809
 
                else {
810
 
                        copy_m4_m4(local, mat);
811
 
                }
812
 
 
813
 
                TransformBase::decompose(local, loc, rot, NULL, scale);
814
 
                
815
 
                add_transform(node, loc, rot, scale);
816
 
        }
817
 
 
818
 
        void add_node_transform_ob(COLLADASW::Node& node, Object *ob)
819
 
        {
820
 
                float rot[3], loc[3], scale[3];
821
 
 
822
 
                if (ob->parent) {
823
 
                        float C[4][4], tmat[4][4], imat[4][4], mat[4][4];
824
 
 
825
 
                        // factor out scale from obmat
826
 
 
827
 
                        copy_v3_v3(scale, ob->size);
828
 
 
829
 
                        ob->size[0] = ob->size[1] = ob->size[2] = 1.0f;
830
 
                        object_to_mat4(ob, C);
831
 
                        copy_v3_v3(ob->size, scale);
832
 
 
833
 
                        mul_serie_m4(tmat, ob->parent->obmat, ob->parentinv, C, NULL, NULL, NULL, NULL, NULL);
834
 
 
835
 
                        // calculate local mat
836
 
 
837
 
                        invert_m4_m4(imat, ob->parent->obmat);
838
 
                        mul_m4_m4m4(mat, tmat, imat);
839
 
 
840
 
                        // done
841
 
 
842
 
                        mat4_to_eul(rot, mat);
843
 
                        copy_v3_v3(loc, mat[3]);
844
 
                }
845
 
                else {
846
 
                        copy_v3_v3(loc, ob->loc);
847
 
                        copy_v3_v3(rot, ob->rot);
848
 
                        copy_v3_v3(scale, ob->size);
849
 
                }
850
 
 
851
 
                add_transform(node, loc, rot, scale);
852
 
        }
853
 
 
854
 
        void add_node_transform_identity(COLLADASW::Node& node)
855
 
        {
856
 
                float loc[] = {0.0f, 0.0f, 0.0f}, scale[] = {1.0f, 1.0f, 1.0f}, rot[] = {0.0f, 0.0f, 0.0f};
857
 
                add_transform(node, loc, rot, scale);
858
 
        }
859
 
 
860
 
private:
861
 
        void add_transform(COLLADASW::Node& node, float loc[3], float rot[3], float scale[3])
862
 
        {
863
 
                node.addTranslate("location", loc[0], loc[1], loc[2]);
864
 
                node.addRotateZ("rotationZ", COLLADABU::Math::Utils::radToDegF(rot[2]));
865
 
                node.addRotateY("rotationY", COLLADABU::Math::Utils::radToDegF(rot[1]));
866
 
                node.addRotateX("rotationX", COLLADABU::Math::Utils::radToDegF(rot[0]));
867
 
                node.addScale("scale", scale[0], scale[1], scale[2]);
868
 
        }
869
 
};
870
 
 
871
 
class InstanceWriter
872
 
{
873
 
protected:
874
 
        void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob)
875
 
        {
876
 
                for(int a = 0; a < ob->totcol; a++)     {
877
 
                        Material *ma = give_current_material(ob, a+1);
878
 
                                
879
 
                        COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
880
 
 
881
 
                        if (ma) {
882
 
                                std::string matid(id_name(ma));
883
 
                                matid = translate_id(matid);
884
 
                                COLLADASW::InstanceMaterial im(matid, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
885
 
                                
886
 
                                // create <bind_vertex_input> for each uv layer
887
 
                                Mesh *me = (Mesh*)ob->data;
888
 
                                int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
889
 
                                
890
 
                                for (int b = 0; b < totlayer; b++) {
891
 
                                        char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
892
 
                                        im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", b));
893
 
                                }
894
 
                                
895
 
                                iml.push_back(im);
896
 
                        }
897
 
                }
898
 
        }
899
 
};
900
 
 
901
 
// XXX exporter writes wrong data for shared armatures.  A separate
902
 
// controller should be written for each armature-mesh binding how do
903
 
// we make controller ids then?
904
 
class ArmatureExporter: public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter
905
 
{
906
 
private:
907
 
        Scene *scene;
908
 
 
909
 
public:
910
 
        ArmatureExporter(COLLADASW::StreamWriter *sw) : COLLADASW::LibraryControllers(sw) {}
911
 
 
912
 
        // write bone nodes
913
 
        void add_armature_bones(Object *ob_arm, Scene *sce)
914
 
        {
915
 
                // write bone nodes
916
 
                bArmature *arm = (bArmature*)ob_arm->data;
917
 
                for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) {
918
 
                        // start from root bones
919
 
                        if (!bone->parent)
920
 
                                add_bone_node(bone, ob_arm);
921
 
                }
922
 
        }
923
 
 
924
 
        bool is_skinned_mesh(Object *ob)
925
 
        {
926
 
                return get_assigned_armature(ob) != NULL;
927
 
        }
928
 
 
929
 
        void add_instance_controller(Object *ob)
930
 
        {
931
 
                Object *ob_arm = get_assigned_armature(ob);
932
 
                bArmature *arm = (bArmature*)ob_arm->data;
933
 
 
934
 
                const std::string& controller_id = get_controller_id(ob_arm, ob);
935
 
 
936
 
                COLLADASW::InstanceController ins(mSW);
937
 
                ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
938
 
 
939
 
                // write root bone URLs
940
 
                Bone *bone;
941
 
                for (bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) {
942
 
                        if (!bone->parent)
943
 
                                ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm)));
944
 
                }
945
 
 
946
 
                InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob);
947
 
                        
948
 
                ins.add();
949
 
        }
950
 
 
951
 
        void export_controllers(Scene *sce)
952
 
        {
953
 
                scene = sce;
954
 
 
955
 
                openLibrary();
956
 
 
957
 
                forEachMeshObjectInScene(sce, *this);
958
 
 
959
 
                closeLibrary();
960
 
        }
961
 
 
962
 
        void operator()(Object *ob)
963
 
        {
964
 
                Object *ob_arm = get_assigned_armature(ob);
965
 
 
966
 
                if (ob_arm /*&& !already_written(ob_arm)*/)
967
 
                        export_controller(ob, ob_arm);
968
 
        }
969
 
 
970
 
private:
971
 
 
972
 
        UnitConverter converter;
973
 
 
974
 
#if 0
975
 
        std::vector<Object*> written_armatures;
976
 
 
977
 
        bool already_written(Object *ob_arm)
978
 
        {
979
 
                return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end();
980
 
        }
981
 
 
982
 
        void wrote(Object *ob_arm)
983
 
        {
984
 
                written_armatures.push_back(ob_arm);
985
 
        }
986
 
 
987
 
        void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce)
988
 
        {
989
 
                objects.clear();
990
 
 
991
 
                Base *base= (Base*) sce->base.first;
992
 
                while(base) {
993
 
                        Object *ob = base->object;
994
 
                        
995
 
                        if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) {
996
 
                                objects.push_back(ob);
997
 
                        }
998
 
 
999
 
                        base= base->next;
1000
 
                }
1001
 
        }
1002
 
#endif
1003
 
 
1004
 
        Object *get_assigned_armature(Object *ob)
1005
 
        {
1006
 
                Object *ob_arm = NULL;
1007
 
 
1008
 
                if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
1009
 
                        ob_arm = ob->parent;
1010
 
                }
1011
 
                else {
1012
 
                        ModifierData *mod = (ModifierData*)ob->modifiers.first;
1013
 
                        while (mod) {
1014
 
                                if (mod->type == eModifierType_Armature) {
1015
 
                                        ob_arm = ((ArmatureModifierData*)mod)->object;
1016
 
                                }
1017
 
 
1018
 
                                mod = mod->next;
1019
 
                        }
1020
 
                }
1021
 
 
1022
 
                return ob_arm;
1023
 
        }
1024
 
 
1025
 
        std::string get_joint_sid(Bone *bone, Object *ob_arm)
1026
 
        {
1027
 
                return get_joint_id(bone, ob_arm);
1028
 
        }
1029
 
 
1030
 
        // parent_mat is armature-space
1031
 
        void add_bone_node(Bone *bone, Object *ob_arm)
1032
 
        {
1033
 
                std::string node_id = get_joint_id(bone, ob_arm);
1034
 
                std::string node_name = std::string(bone->name);
1035
 
                std::string node_sid = get_joint_sid(bone, ob_arm);
1036
 
 
1037
 
                COLLADASW::Node node(mSW);
1038
 
 
1039
 
                node.setType(COLLADASW::Node::JOINT);
1040
 
                node.setNodeId(node_id);
1041
 
                node.setNodeName(node_name);
1042
 
                node.setNodeSid(node_sid);
1043
 
 
1044
 
                node.start();
1045
 
 
1046
 
                add_bone_transform(ob_arm, bone, node);
1047
 
 
1048
 
                for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next) {
1049
 
                        add_bone_node(child, ob_arm);
1050
 
                }
1051
 
 
1052
 
                node.end();
1053
 
        }
1054
 
 
1055
 
        void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node)
1056
 
        {
1057
 
                bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
1058
 
 
1059
 
                float mat[4][4];
1060
 
 
1061
 
                if (bone->parent) {
1062
 
                        // get bone-space matrix from armature-space
1063
 
                        bPoseChannel *parchan = get_pose_channel(ob_arm->pose, bone->parent->name);
1064
 
 
1065
 
                        float invpar[4][4];
1066
 
                        invert_m4_m4(invpar, parchan->pose_mat);
1067
 
                        mul_m4_m4m4(mat, pchan->pose_mat, invpar);
1068
 
                }
1069
 
                else {
1070
 
                        // get world-space from armature-space
1071
 
                        mul_m4_m4m4(mat, pchan->pose_mat, ob_arm->obmat);
1072
 
                }
1073
 
 
1074
 
                TransformWriter::add_node_transform(node, mat, NULL);
1075
 
        }
1076
 
 
1077
 
        std::string get_controller_id(Object *ob_arm, Object *ob)
1078
 
        {
1079
 
                return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
1080
 
        }
1081
 
 
1082
 
        // ob should be of type OB_MESH
1083
 
        // both args are required
1084
 
        void export_controller(Object* ob, Object *ob_arm)
1085
 
        {
1086
 
                // joint names
1087
 
                // joint inverse bind matrices
1088
 
                // vertex weights
1089
 
 
1090
 
                // input:
1091
 
                // joint names: ob -> vertex group names
1092
 
                // vertex group weights: me->dvert -> groups -> index, weight
1093
 
 
1094
 
                /*
1095
 
                me->dvert:
1096
 
 
1097
 
                typedef struct MDeformVert {
1098
 
                        struct MDeformWeight *dw;
1099
 
                        int totweight;
1100
 
                        int flag;       // flag only in use for weightpaint now
1101
 
                } MDeformVert;
1102
 
 
1103
 
                typedef struct MDeformWeight {
1104
 
                        int                             def_nr;
1105
 
                        float                   weight;
1106
 
                } MDeformWeight;
1107
 
                */
1108
 
 
1109
 
                Mesh *me = (Mesh*)ob->data;
1110
 
                if (!me->dvert) return;
1111
 
 
1112
 
                std::string controller_name = id_name(ob_arm);
1113
 
                std::string controller_id = get_controller_id(ob_arm, ob);
1114
 
 
1115
 
                openSkin(controller_id, controller_name,
1116
 
                                 COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob)));
1117
 
 
1118
 
                add_bind_shape_mat(ob);
1119
 
 
1120
 
                std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id);
1121
 
                std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id);
1122
 
                std::string weights_source_id = add_weights_source(me, controller_id);
1123
 
 
1124
 
                add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
1125
 
                add_vertex_weights_element(weights_source_id, joints_source_id, me, ob_arm, &ob->defbase);
1126
 
 
1127
 
                closeSkin();
1128
 
                closeController();
1129
 
        }
1130
 
 
1131
 
        void add_joints_element(ListBase *defbase,
1132
 
                                                        const std::string& joints_source_id, const std::string& inv_bind_mat_source_id)
1133
 
        {
1134
 
                COLLADASW::JointsElement joints(mSW);
1135
 
                COLLADASW::InputList &input = joints.getInputList();
1136
 
 
1137
 
                input.push_back(COLLADASW::Input(COLLADASW::JOINT, // constant declared in COLLADASWInputList.h
1138
 
                                                                   COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id)));
1139
 
                input.push_back(COLLADASW::Input(COLLADASW::BINDMATRIX,
1140
 
                                                                   COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id)));
1141
 
                joints.add();
1142
 
        }
1143
 
 
1144
 
        void add_bind_shape_mat(Object *ob)
1145
 
        {
1146
 
                double bind_mat[4][4];
1147
 
 
1148
 
                converter.mat4_to_dae_double(bind_mat, ob->obmat);
1149
 
 
1150
 
                addBindShapeTransform(bind_mat);
1151
 
        }
1152
 
 
1153
 
        std::string add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
1154
 
        {
1155
 
                std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
1156
 
 
1157
 
                int totjoint = 0;
1158
 
                bDeformGroup *def;
1159
 
                for (def = (bDeformGroup*)defbase->first; def; def = def->next) {
1160
 
                        if (is_bone_defgroup(ob_arm, def))
1161
 
                                totjoint++;
1162
 
                }
1163
 
 
1164
 
                COLLADASW::NameSource source(mSW);
1165
 
                source.setId(source_id);
1166
 
                source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1167
 
                source.setAccessorCount(totjoint);
1168
 
                source.setAccessorStride(1);
1169
 
                
1170
 
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1171
 
                param.push_back("JOINT");
1172
 
 
1173
 
                source.prepareToAppendValues();
1174
 
 
1175
 
                for (def = (bDeformGroup*)defbase->first; def; def = def->next) {
1176
 
                        Bone *bone = get_bone_from_defgroup(ob_arm, def);
1177
 
                        if (bone)
1178
 
                                source.appendValues(get_joint_sid(bone, ob_arm));
1179
 
                }
1180
 
 
1181
 
                source.finish();
1182
 
 
1183
 
                return source_id;
1184
 
        }
1185
 
 
1186
 
        std::string add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
1187
 
        {
1188
 
                std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
1189
 
 
1190
 
                COLLADASW::FloatSourceF source(mSW);
1191
 
                source.setId(source_id);
1192
 
                source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1193
 
                source.setAccessorCount(BLI_countlist(defbase));
1194
 
                source.setAccessorStride(16);
1195
 
                
1196
 
                source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
1197
 
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1198
 
                param.push_back("TRANSFORM");
1199
 
 
1200
 
                source.prepareToAppendValues();
1201
 
 
1202
 
                bPose *pose = ob_arm->pose;
1203
 
                bArmature *arm = (bArmature*)ob_arm->data;
1204
 
 
1205
 
                int flag = arm->flag;
1206
 
 
1207
 
                // put armature in rest position
1208
 
                if (!(arm->flag & ARM_RESTPOS)) {
1209
 
                        arm->flag |= ARM_RESTPOS;
1210
 
                        where_is_pose(scene, ob_arm);
1211
 
                }
1212
 
 
1213
 
                for (bDeformGroup *def = (bDeformGroup*)defbase->first; def; def = def->next) {
1214
 
                        if (is_bone_defgroup(ob_arm, def)) {
1215
 
 
1216
 
                                bPoseChannel *pchan = get_pose_channel(pose, def->name);
1217
 
 
1218
 
                                float mat[4][4];
1219
 
                                float world[4][4];
1220
 
                                float inv_bind_mat[4][4];
1221
 
 
1222
 
                                // make world-space matrix, pose_mat is armature-space
1223
 
                                mul_m4_m4m4(world, pchan->pose_mat, ob_arm->obmat);
1224
 
                                
1225
 
                                invert_m4_m4(mat, world);
1226
 
                                converter.mat4_to_dae(inv_bind_mat, mat);
1227
 
 
1228
 
                                source.appendValues(inv_bind_mat);
1229
 
                        }
1230
 
                }
1231
 
 
1232
 
                // back from rest positon
1233
 
                if (!(flag & ARM_RESTPOS)) {
1234
 
                        arm->flag = flag;
1235
 
                        where_is_pose(scene, ob_arm);
1236
 
                }
1237
 
 
1238
 
                source.finish();
1239
 
 
1240
 
                return source_id;
1241
 
        }
1242
 
 
1243
 
        Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup* def)
1244
 
        {
1245
 
                bPoseChannel *pchan = get_pose_channel(ob_arm->pose, def->name);
1246
 
                return pchan ? pchan->bone : NULL;
1247
 
        }
1248
 
 
1249
 
        bool is_bone_defgroup(Object *ob_arm, bDeformGroup* def)
1250
 
        {
1251
 
                return get_bone_from_defgroup(ob_arm, def) != NULL;
1252
 
        }
1253
 
 
1254
 
        std::string add_weights_source(Mesh *me, const std::string& controller_id)
1255
 
        {
1256
 
                std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
1257
 
 
1258
 
                int i;
1259
 
                int totweight = 0;
1260
 
 
1261
 
                for (i = 0; i < me->totvert; i++) {
1262
 
                        totweight += me->dvert[i].totweight;
1263
 
                }
1264
 
 
1265
 
                COLLADASW::FloatSourceF source(mSW);
1266
 
                source.setId(source_id);
1267
 
                source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1268
 
                source.setAccessorCount(totweight);
1269
 
                source.setAccessorStride(1);
1270
 
                
1271
 
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1272
 
                param.push_back("WEIGHT");
1273
 
 
1274
 
                source.prepareToAppendValues();
1275
 
 
1276
 
                // NOTE: COLLADA spec says weights should be normalized
1277
 
 
1278
 
                for (i = 0; i < me->totvert; i++) {
1279
 
                        MDeformVert *vert = &me->dvert[i];
1280
 
                        for (int j = 0; j < vert->totweight; j++) {
1281
 
                                source.appendValues(vert->dw[j].weight);
1282
 
                        }
1283
 
                }
1284
 
 
1285
 
                source.finish();
1286
 
 
1287
 
                return source_id;
1288
 
        }
1289
 
 
1290
 
        void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, Mesh *me,
1291
 
                                                                        Object *ob_arm, ListBase *defbase)
1292
 
        {
1293
 
                COLLADASW::VertexWeightsElement weights(mSW);
1294
 
                COLLADASW::InputList &input = weights.getInputList();
1295
 
 
1296
 
                int offset = 0;
1297
 
                input.push_back(COLLADASW::Input(COLLADASW::JOINT, // constant declared in COLLADASWInputList.h
1298
 
                                                                                 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++));
1299
 
        input.push_back(COLLADASW::Input(COLLADASW::WEIGHT,
1300
 
                                                                                 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++));
1301
 
 
1302
 
                weights.setCount(me->totvert);
1303
 
 
1304
 
                // write number of deformers per vertex
1305
 
                COLLADASW::PrimitivesBase::VCountList vcount;
1306
 
                int i;
1307
 
                for (i = 0; i < me->totvert; i++) {
1308
 
                        vcount.push_back(me->dvert[i].totweight);
1309
 
                }
1310
 
 
1311
 
                weights.prepareToAppendVCountValues();
1312
 
                weights.appendVertexCount(vcount);
1313
 
 
1314
 
                // def group index -> joint index
1315
 
                std::map<int, int> joint_index_by_def_index;
1316
 
                bDeformGroup *def;
1317
 
                int j;
1318
 
                for (def = (bDeformGroup*)defbase->first, i = 0, j = 0; def; def = def->next, i++) {
1319
 
                        if (is_bone_defgroup(ob_arm, def))
1320
 
                                joint_index_by_def_index[i] = j++;
1321
 
                        else
1322
 
                                joint_index_by_def_index[i] = -1;
1323
 
                }
1324
 
 
1325
 
                weights.CloseVCountAndOpenVElement();
1326
 
 
1327
 
                // write deformer index - weight index pairs
1328
 
                int weight_index = 0;
1329
 
                for (i = 0; i < me->totvert; i++) {
1330
 
                        MDeformVert *dvert = &me->dvert[i];
1331
 
                        for (int j = 0; j < dvert->totweight; j++) {
1332
 
                                weights.appendValues(joint_index_by_def_index[dvert->dw[j].def_nr]);
1333
 
                                weights.appendValues(weight_index++);
1334
 
                        }
1335
 
                }
1336
 
 
1337
 
                weights.finish();
1338
 
        }
1339
 
};
1340
 
 
1341
 
class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter, protected InstanceWriter
1342
 
{
1343
 
        ArmatureExporter *arm_exporter;
1344
 
public:
1345
 
        SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm) : COLLADASW::LibraryVisualScenes(sw),
1346
 
                                                                                                                                                arm_exporter(arm) {}
1347
 
        
1348
 
        void exportScene(Scene *sce) {
1349
 
                // <library_visual_scenes> <visual_scene>
1350
 
                std::string id_naming = id_name(sce);
1351
 
                openVisualScene(translate_id(id_naming), id_naming);
1352
 
 
1353
 
                // write <node>s
1354
 
                //forEachMeshObjectInScene(sce, *this);
1355
 
                //forEachCameraObjectInScene(sce, *this);
1356
 
                //forEachLampObjectInScene(sce, *this);
1357
 
                exportHierarchy(sce);
1358
 
 
1359
 
                // </visual_scene> </library_visual_scenes>
1360
 
                closeVisualScene();
1361
 
 
1362
 
                closeLibrary();
1363
 
        }
1364
 
 
1365
 
        void exportHierarchy(Scene *sce)
1366
 
        {
1367
 
                Base *base= (Base*) sce->base.first;
1368
 
                while(base) {
1369
 
                        Object *ob = base->object;
1370
 
 
1371
 
                        if (!ob->parent) {
1372
 
                                switch(ob->type) {
1373
 
                                case OB_MESH:
1374
 
                                case OB_CAMERA:
1375
 
                                case OB_LAMP:
1376
 
                                case OB_EMPTY:
1377
 
                                case OB_ARMATURE:
1378
 
                                        // write nodes....
1379
 
                                        writeNodes(ob, sce);
1380
 
                                        break;
1381
 
                                }
1382
 
                        }
1383
 
 
1384
 
                        base= base->next;
1385
 
                }
1386
 
        }
1387
 
 
1388
 
 
1389
 
        // called for each object
1390
 
        //void operator()(Object *ob) {
1391
 
        void writeNodes(Object *ob, Scene *sce)
1392
 
        {
1393
 
                COLLADASW::Node node(mSW);
1394
 
                node.setNodeId(translate_id(id_name(ob)));
1395
 
                node.setType(COLLADASW::Node::NODE);
1396
 
 
1397
 
                node.start();
1398
 
 
1399
 
                bool is_skinned_mesh = arm_exporter->is_skinned_mesh(ob);
1400
 
 
1401
 
                if (ob->type == OB_MESH && is_skinned_mesh)
1402
 
                        // for skinned mesh we write obmat in <bind_shape_matrix>
1403
 
                        TransformWriter::add_node_transform_identity(node);
1404
 
                else
1405
 
                        TransformWriter::add_node_transform_ob(node, ob);
1406
 
                
1407
 
                // <instance_geometry>
1408
 
                if (ob->type == OB_MESH) {
1409
 
                        if (is_skinned_mesh) {
1410
 
                                arm_exporter->add_instance_controller(ob);
1411
 
                        }
1412
 
                        else {
1413
 
                                COLLADASW::InstanceGeometry instGeom(mSW);
1414
 
                                instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob)));
1415
 
 
1416
 
                                InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob);
1417
 
                        
1418
 
                                instGeom.add();
1419
 
                        }
1420
 
                }
1421
 
 
1422
 
                // <instance_controller>
1423
 
                else if (ob->type == OB_ARMATURE) {
1424
 
                        arm_exporter->add_armature_bones(ob, sce);
1425
 
 
1426
 
                        // XXX this looks unstable...
1427
 
                        node.end();
1428
 
                }
1429
 
                
1430
 
                // <instance_camera>
1431
 
                else if (ob->type == OB_CAMERA) {
1432
 
                        COLLADASW::InstanceCamera instCam(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_camera_id(ob)));
1433
 
                        instCam.add();
1434
 
                }
1435
 
                
1436
 
                // <instance_light>
1437
 
                else if (ob->type == OB_LAMP) {
1438
 
                        COLLADASW::InstanceLight instLa(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_light_id(ob)));
1439
 
                        instLa.add();
1440
 
                }
1441
 
 
1442
 
                // empty object
1443
 
                else if (ob->type == OB_EMPTY) {
1444
 
                }
1445
 
 
1446
 
                // write nodes for child objects
1447
 
                Base *b = (Base*) sce->base.first;
1448
 
                while(b) {
1449
 
                        // cob - child object
1450
 
                        Object *cob = b->object;
1451
 
 
1452
 
                        if (cob->parent == ob) {
1453
 
                                switch(cob->type) {
1454
 
                                case OB_MESH:
1455
 
                                case OB_CAMERA:
1456
 
                                case OB_LAMP:
1457
 
                                case OB_EMPTY:
1458
 
                                case OB_ARMATURE:
1459
 
                                        // write node...
1460
 
                                        writeNodes(cob, sce);
1461
 
                                        break;
1462
 
                                }
1463
 
                        }
1464
 
 
1465
 
                        b = b->next;
1466
 
                }
1467
 
 
1468
 
                if (ob->type != OB_ARMATURE)
1469
 
                        node.end();
1470
 
        }
1471
 
};
1472
 
 
1473
 
class ImagesExporter: COLLADASW::LibraryImages
1474
 
{
1475
 
        const char *mfilename;
1476
 
        std::vector<std::string> mImages; // contains list of written images, to avoid duplicates
1477
 
public:
1478
 
        ImagesExporter(COLLADASW::StreamWriter *sw, const char* filename) : COLLADASW::LibraryImages(sw), mfilename(filename)
1479
 
        {}
1480
 
        
1481
 
        void exportImages(Scene *sce)
1482
 
        {
1483
 
                openLibrary();
1484
 
 
1485
 
                forEachMaterialInScene(sce, *this);
1486
 
 
1487
 
                closeLibrary();
1488
 
        }
1489
 
 
1490
 
        void operator()(Material *ma, Object *ob)
1491
 
        {
1492
 
                int a;
1493
 
                for (a = 0; a < MAX_MTEX; a++) {
1494
 
                        MTex *mtex = ma->mtex[a];
1495
 
                        if (mtex && mtex->tex && mtex->tex->ima) {
1496
 
 
1497
 
                                Image *image = mtex->tex->ima;
1498
 
                                std::string name(id_name(image));
1499
 
                                name = translate_id(name);
1500
 
                                char rel[FILE_MAX];
1501
 
                                char abs[FILE_MAX];
1502
 
                                char src[FILE_MAX];
1503
 
                                char dir[FILE_MAX];
1504
 
                                
1505
 
                                BLI_split_dirfile(mfilename, dir, NULL);
1506
 
 
1507
 
                                BKE_rebase_path(abs, sizeof(abs), rel, sizeof(rel), G.sce, image->name, dir);
1508
 
 
1509
 
                                if (abs[0] != '\0') {
1510
 
 
1511
 
                                        // make absolute source path
1512
 
                                        BLI_strncpy(src, image->name, sizeof(src));
1513
 
                                        BLI_path_abs(src, G.sce);
1514
 
 
1515
 
                                        // make dest directory if it doesn't exist
1516
 
                                        BLI_make_existing_file(abs);
1517
 
                                
1518
 
                                        if (BLI_copy_fileops(src, abs) != 0) {
1519
 
                                                fprintf(stderr, "Cannot copy image to file's directory. \n");
1520
 
                                        }
1521
 
                                } 
1522
 
                                
1523
 
                                if (find(mImages.begin(), mImages.end(), name) == mImages.end()) {
1524
 
                                        COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(rel)), name);
1525
 
                                        img.add(mSW);
1526
 
 
1527
 
                                        mImages.push_back(name);
1528
 
                                }
1529
 
                        }
1530
 
                }
1531
 
        }
1532
 
};
1533
 
 
1534
 
class EffectsExporter: COLLADASW::LibraryEffects
1535
 
{
1536
 
public:
1537
 
        EffectsExporter(COLLADASW::StreamWriter *sw) : COLLADASW::LibraryEffects(sw){}
1538
 
        void exportEffects(Scene *sce)
1539
 
        {
1540
 
                openLibrary();
1541
 
 
1542
 
                forEachMaterialInScene(sce, *this);
1543
 
 
1544
 
                closeLibrary();
1545
 
        }
1546
 
 
1547
 
        void operator()(Material *ma, Object *ob)
1548
 
        {
1549
 
                // create a list of indices to textures of type TEX_IMAGE
1550
 
                std::vector<int> tex_indices;
1551
 
                createTextureIndices(ma, tex_indices);
1552
 
 
1553
 
                openEffect(translate_id(id_name(ma)) + "-effect");
1554
 
                
1555
 
                COLLADASW::EffectProfile ep(mSW);
1556
 
                ep.setProfileType(COLLADASW::EffectProfile::COMMON);
1557
 
                ep.openProfile();
1558
 
                // set shader type - one of three blinn, phong or lambert
1559
 
                if (ma->spec_shader == MA_SPEC_BLINN) {
1560
 
                        ep.setShaderType(COLLADASW::EffectProfile::BLINN);
1561
 
                        // shininess
1562
 
                        ep.setShininess(ma->spec);
1563
 
                }
1564
 
                else if (ma->spec_shader == MA_SPEC_PHONG) {
1565
 
                        ep.setShaderType(COLLADASW::EffectProfile::PHONG);
1566
 
                        // shininess
1567
 
                        // XXX not sure, stolen this from previous Collada plugin
1568
 
                        ep.setShininess(ma->har / 4);
1569
 
                }
1570
 
                else {
1571
 
                        // XXX write warning "Current shader type is not supported" 
1572
 
                        ep.setShaderType(COLLADASW::EffectProfile::LAMBERT);
1573
 
                }
1574
 
                // index of refraction
1575
 
                if (ma->mode & MA_RAYTRANSP) {
1576
 
                        ep.setIndexOfRefraction(ma->ang);
1577
 
                }
1578
 
                else {
1579
 
                        ep.setIndexOfRefraction(1.0f);
1580
 
                }
1581
 
        
1582
 
                COLLADASW::ColorOrTexture cot;
1583
 
 
1584
 
                // transparency
1585
 
                // Tod: because we are in A_ONE mode transparency is calculated like this:
1586
 
                ep.setTransparency(1.0f);
1587
 
                cot = getcol(0.0f, 0.0f, 0.0f, ma->alpha);
1588
 
                ep.setTransparent(cot);
1589
 
 
1590
 
                // emission
1591
 
                cot=getcol(ma->emit, ma->emit, ma->emit, 1.0f);
1592
 
                ep.setEmission(cot);
1593
 
 
1594
 
                // diffuse 
1595
 
                cot = getcol(ma->r, ma->g, ma->b, 1.0f);
1596
 
                ep.setDiffuse(cot);
1597
 
 
1598
 
                // ambient
1599
 
                cot = getcol(ma->ambr, ma->ambg, ma->ambb, 1.0f);
1600
 
                ep.setAmbient(cot);
1601
 
 
1602
 
                // reflective, reflectivity
1603
 
                if (ma->mode & MA_RAYMIRROR) {
1604
 
                        cot = getcol(ma->mirr, ma->mirg, ma->mirb, 1.0f);
1605
 
                        ep.setReflective(cot);
1606
 
                        ep.setReflectivity(ma->ray_mirror);
1607
 
                }
1608
 
                else {
1609
 
                        cot = getcol(ma->specr, ma->specg, ma->specb, 1.0f);
1610
 
                        ep.setReflective(cot);
1611
 
                        ep.setReflectivity(ma->spec);
1612
 
                }
1613
 
 
1614
 
                // specular
1615
 
                if (ep.getShaderType() != COLLADASW::EffectProfile::LAMBERT) {
1616
 
                        cot = getcol(ma->specr, ma->specg, ma->specb, 1.0f);
1617
 
                        ep.setSpecular(cot);
1618
 
                }       
1619
 
 
1620
 
                // XXX make this more readable if possible
1621
 
 
1622
 
                // create <sampler> and <surface> for each image
1623
 
                COLLADASW::Sampler samplers[MAX_MTEX];
1624
 
                //COLLADASW::Surface surfaces[MAX_MTEX];
1625
 
                //void *samp_surf[MAX_MTEX][2];
1626
 
                void *samp_surf[MAX_MTEX][1];
1627
 
                
1628
 
                // image to index to samp_surf map
1629
 
                // samp_surf[index] stores 2 pointers, sampler and surface
1630
 
                std::map<std::string, int> im_samp_map;
1631
 
 
1632
 
                unsigned int a, b;
1633
 
                for (a = 0, b = 0; a < tex_indices.size(); a++) {
1634
 
                        MTex *t = ma->mtex[tex_indices[a]];
1635
 
                        Image *ima = t->tex->ima;
1636
 
                        
1637
 
                        std::string key(id_name(ima));
1638
 
                        key = translate_id(key);
1639
 
 
1640
 
                        // create only one <sampler>/<surface> pair for each unique image
1641
 
                        if (im_samp_map.find(key) == im_samp_map.end()) {
1642
 
                                //<newparam> <surface> <init_from>
1643
 
                        //      COLLADASW::Surface surface(COLLADASW::Surface::SURFACE_TYPE_2D,
1644
 
//                                                                                 key + COLLADASW::Surface::SURFACE_SID_SUFFIX);
1645
 
//                              COLLADASW::SurfaceInitOption sio(COLLADASW::SurfaceInitOption::INIT_FROM);
1646
 
//                              sio.setImageReference(key);
1647
 
//                              surface.setInitOption(sio);
1648
 
                                
1649
 
                                //<newparam> <sampler> <source>
1650
 
                                COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
1651
 
                                                                                   key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
1652
 
                                                                                   key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
1653
 
                                sampler.setImageId(key);
1654
 
                                // copy values to arrays since they will live longer
1655
 
                                samplers[a] = sampler;
1656
 
                                //surfaces[a] = surface;
1657
 
                                
1658
 
                                // store pointers so they can be used later when we create <texture>s
1659
 
                                samp_surf[b][0] = &samplers[a];
1660
 
                                //samp_surf[b][1] = &surfaces[a];
1661
 
                                
1662
 
                                im_samp_map[key] = b;
1663
 
                                b++;
1664
 
                        }
1665
 
                }
1666
 
 
1667
 
                // used as fallback when MTex->uvname is "" (this is pretty common)
1668
 
                // it is indeed the correct value to use in that case
1669
 
                std::string active_uv(getActiveUVLayerName(ob));
1670
 
 
1671
 
                // write textures
1672
 
                // XXX very slow
1673
 
                for (a = 0; a < tex_indices.size(); a++) {
1674
 
                        MTex *t = ma->mtex[tex_indices[a]];
1675
 
                        Image *ima = t->tex->ima;
1676
 
 
1677
 
                        // we assume map input is always TEXCO_UV
1678
 
 
1679
 
                        std::string key(id_name(ima));
1680
 
                        key = translate_id(key);
1681
 
                        int i = im_samp_map[key];
1682
 
                        COLLADASW::Sampler *sampler = (COLLADASW::Sampler*)samp_surf[i][0];
1683
 
                        //COLLADASW::Surface *surface = (COLLADASW::Surface*)samp_surf[i][1];
1684
 
 
1685
 
                        std::string uvname = strlen(t->uvname) ? t->uvname : active_uv;
1686
 
 
1687
 
                        // color
1688
 
                        if (t->mapto & MAP_COL) {
1689
 
                                ep.setDiffuse(createTexture(ima, uvname, sampler));
1690
 
                        }
1691
 
                        // ambient
1692
 
                        if (t->mapto & MAP_AMB) {
1693
 
                                ep.setAmbient(createTexture(ima, uvname, sampler));
1694
 
                        }
1695
 
                        // specular
1696
 
                        if (t->mapto & MAP_SPEC) {
1697
 
                                ep.setSpecular(createTexture(ima, uvname, sampler));
1698
 
                        }
1699
 
                        // emission
1700
 
                        if (t->mapto & MAP_EMIT) {
1701
 
                                ep.setEmission(createTexture(ima, uvname, sampler));
1702
 
                        }
1703
 
                        // reflective
1704
 
                        if (t->mapto & MAP_REF) {
1705
 
                                ep.setReflective(createTexture(ima, uvname, sampler));
1706
 
                        }
1707
 
                        // alpha
1708
 
                        if (t->mapto & MAP_ALPHA) {
1709
 
                                ep.setTransparent(createTexture(ima, uvname, sampler));
1710
 
                        }
1711
 
                        // extension:
1712
 
                        // Normal map --> Must be stored with <extra> tag as different technique, 
1713
 
                        // since COLLADA doesn't support normal maps, even in current COLLADA 1.5.
1714
 
                        if (t->mapto & MAP_NORM) {
1715
 
                                COLLADASW::Texture texture(key);
1716
 
                                texture.setTexcoord(uvname);
1717
 
                                texture.setSampler(*sampler);
1718
 
                                // technique FCOLLADA, with the <bump> tag, is most likely the best understood,
1719
 
                                // most widespread de-facto standard.
1720
 
                                texture.setProfileName("FCOLLADA");
1721
 
                                texture.setChildElementName("bump");                            
1722
 
#ifdef WIN32    // currently, Windows builds are using revision 746 of OpenCollada while Linux and Mac are using an older revision 721
1723
 
                                ep.addExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture));
1724
 
#else
1725
 
                                ep.setExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture));
1726
 
#endif
1727
 
                        }
1728
 
                }
1729
 
                // performs the actual writing
1730
 
                ep.addProfileElements();
1731
 
                bool twoSided = false;
1732
 
                if (ob->type == OB_MESH && ob->data) {
1733
 
                        Mesh *me = (Mesh*)ob->data;
1734
 
                        if (me->flag & ME_TWOSIDED)
1735
 
                                twoSided = true;
1736
 
                }
1737
 
                if (twoSided)
1738
 
                        ep.addExtraTechniqueParameter("GOOGLEEARTH", "double_sided", 1);
1739
 
                ep.addExtraTechniques(mSW);
1740
 
 
1741
 
                ep.closeProfile();
1742
 
                if (twoSided)
1743
 
                        mSW->appendTextBlock("<extra><technique profile=\"MAX3D\"><double_sided>1</double_sided></technique></extra>");
1744
 
                closeEffect();  
1745
 
        }
1746
 
        
1747
 
        COLLADASW::ColorOrTexture createTexture(Image *ima,
1748
 
                                                                                        std::string& uv_layer_name,
1749
 
                                                                                        COLLADASW::Sampler *sampler
1750
 
                                                                                        /*COLLADASW::Surface *surface*/)
1751
 
        {
1752
 
                
1753
 
                COLLADASW::Texture texture(translate_id(id_name(ima)));
1754
 
                texture.setTexcoord(uv_layer_name);
1755
 
                //texture.setSurface(*surface);
1756
 
                texture.setSampler(*sampler);
1757
 
                
1758
 
                COLLADASW::ColorOrTexture cot(texture);
1759
 
                return cot;
1760
 
        }
1761
 
        
1762
 
        COLLADASW::ColorOrTexture getcol(float r, float g, float b, float a)
1763
 
        {
1764
 
                COLLADASW::Color color(r,g,b,a);
1765
 
                COLLADASW::ColorOrTexture cot(color);
1766
 
                return cot;
1767
 
        }
1768
 
        
1769
 
        //returns the array of mtex indices which have image 
1770
 
        //need this for exporting textures
1771
 
        void createTextureIndices(Material *ma, std::vector<int> &indices)
1772
 
        {
1773
 
                indices.clear();
1774
 
 
1775
 
                for (int a = 0; a < MAX_MTEX; a++) {
1776
 
                        if (ma->mtex[a] &&
1777
 
                                ma->mtex[a]->tex->type == TEX_IMAGE &&
1778
 
                                ma->mtex[a]->texco == TEXCO_UV){
1779
 
                                indices.push_back(a);
1780
 
                        }
1781
 
                }
1782
 
        }
1783
 
};
1784
 
 
1785
 
class MaterialsExporter: COLLADASW::LibraryMaterials
1786
 
{
1787
 
public:
1788
 
        MaterialsExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryMaterials(sw){}
1789
 
        void exportMaterials(Scene *sce)
1790
 
        {
1791
 
                openLibrary();
1792
 
 
1793
 
                forEachMaterialInScene(sce, *this);
1794
 
 
1795
 
                closeLibrary();
1796
 
        }
1797
 
 
1798
 
        void operator()(Material *ma, Object *ob)
1799
 
        {
1800
 
                std::string name(id_name(ma));
1801
 
 
1802
 
                openMaterial(translate_id(name), name);
1803
 
 
1804
 
                std::string efid = translate_id(name) + "-effect";
1805
 
                addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, efid));
1806
 
 
1807
 
                closeMaterial();
1808
 
        }
1809
 
};
1810
 
 
1811
 
class CamerasExporter: COLLADASW::LibraryCameras
1812
 
{
1813
 
public:
1814
 
        CamerasExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryCameras(sw){}
1815
 
        void exportCameras(Scene *sce)
1816
 
        {
1817
 
                openLibrary();
1818
 
                
1819
 
                forEachCameraObjectInScene(sce, *this);
1820
 
                
1821
 
                closeLibrary();
1822
 
        }
1823
 
        void operator()(Object *ob, Scene *sce)
1824
 
        {
1825
 
                // XXX add other params later
1826
 
                Camera *cam = (Camera*)ob->data;
1827
 
                std::string cam_id(get_camera_id(ob));
1828
 
                std::string cam_name(id_name(cam));
1829
 
                
1830
 
                if (cam->type == CAM_PERSP) {
1831
 
                        COLLADASW::PerspectiveOptic persp(mSW);
1832
 
                        persp.setXFov(1.0);
1833
 
                        persp.setAspectRatio(0.1);
1834
 
                        persp.setZFar(cam->clipend);
1835
 
                        persp.setZNear(cam->clipsta);
1836
 
                        COLLADASW::Camera ccam(mSW, &persp, cam_id, cam_name);
1837
 
                        addCamera(ccam);
1838
 
                }
1839
 
                else {
1840
 
                        COLLADASW::OrthographicOptic ortho(mSW);
1841
 
                        ortho.setXMag(1.0);
1842
 
                        ortho.setAspectRatio(0.1);
1843
 
                        ortho.setZFar(cam->clipend);
1844
 
                        ortho.setZNear(cam->clipsta);
1845
 
                        COLLADASW::Camera ccam(mSW, &ortho, cam_id, cam_name);
1846
 
                        addCamera(ccam);
1847
 
                }
1848
 
        }       
1849
 
};
1850
 
 
1851
 
class LightsExporter: COLLADASW::LibraryLights
1852
 
{
1853
 
public:
1854
 
        LightsExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryLights(sw){}
1855
 
        void exportLights(Scene *sce)
1856
 
        {
1857
 
                openLibrary();
1858
 
                
1859
 
                forEachLampObjectInScene(sce, *this);
1860
 
                
1861
 
                closeLibrary();
1862
 
        }
1863
 
        void operator()(Object *ob)
1864
 
        {
1865
 
                Lamp *la = (Lamp*)ob->data;
1866
 
                std::string la_id(get_light_id(ob));
1867
 
                std::string la_name(id_name(la));
1868
 
                COLLADASW::Color col(la->r, la->g, la->b);
1869
 
                float e = la->energy;
1870
 
                
1871
 
                // sun
1872
 
                if (la->type == LA_SUN) {
1873
 
                        COLLADASW::DirectionalLight cla(mSW, la_id, la_name, e);
1874
 
                        cla.setColor(col);
1875
 
                        addLight(cla);
1876
 
                }
1877
 
                // hemi
1878
 
                else if (la->type == LA_HEMI) {
1879
 
                        COLLADASW::AmbientLight cla(mSW, la_id, la_name, e);
1880
 
                        cla.setColor(col);
1881
 
                        addLight(cla);
1882
 
                }
1883
 
                // spot
1884
 
                else if (la->type == LA_SPOT) {
1885
 
                        COLLADASW::SpotLight cla(mSW, la_id, la_name, e);
1886
 
                        cla.setColor(col);
1887
 
                        cla.setFallOffAngle(la->spotsize);
1888
 
                        cla.setFallOffExponent(la->spotblend);
1889
 
                        cla.setLinearAttenuation(la->att1);
1890
 
                        cla.setQuadraticAttenuation(la->att2);
1891
 
                        addLight(cla);
1892
 
                }
1893
 
                // lamp
1894
 
                else if (la->type == LA_LOCAL) {
1895
 
                        COLLADASW::PointLight cla(mSW, la_id, la_name, e);
1896
 
                        cla.setColor(col);
1897
 
                        cla.setLinearAttenuation(la->att1);
1898
 
                        cla.setQuadraticAttenuation(la->att2);
1899
 
                        addLight(cla);
1900
 
                }
1901
 
                // area lamp is not supported
1902
 
                // it will be exported as a local lamp
1903
 
                else {
1904
 
                        COLLADASW::PointLight cla(mSW, la_id, la_name, e);
1905
 
                        cla.setColor(col);
1906
 
                        cla.setLinearAttenuation(la->att1);
1907
 
                        cla.setQuadraticAttenuation(la->att2);
1908
 
                        addLight(cla);
1909
 
                }
1910
 
        }
1911
 
};
 
147
DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) {}
1912
148
 
1913
149
// TODO: it would be better to instantiate animations rather than create a new one per object
1914
150
// COLLADA allows this through multiple <channel>s in <animation>.
1915
151
// For this to work, we need to know objects that use a certain action.
1916
 
class AnimationExporter: COLLADASW::LibraryAnimations
1917
 
{
1918
 
        Scene *scene;
1919
 
 
1920
 
public:
1921
 
 
1922
 
        AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) {}
1923
 
 
1924
 
        void exportAnimations(Scene *sce)
1925
 
        {
1926
 
                this->scene = sce;
1927
 
 
1928
 
                openLibrary();
1929
 
                
1930
 
                forEachObjectInScene(sce, *this);
1931
 
                
1932
 
                closeLibrary();
1933
 
        }
1934
 
 
1935
 
        // called for each exported object
1936
 
        void operator() (Object *ob) 
1937
 
        {
1938
 
                if (!ob->adt || !ob->adt->action) return;
1939
 
                
1940
 
                FCurve *fcu = (FCurve*)ob->adt->action->curves.first;
1941
 
                
1942
 
                if (ob->type == OB_ARMATURE) {
1943
 
                        if (!ob->data) return;
1944
 
 
1945
 
                        bArmature *arm = (bArmature*)ob->data;
1946
 
                        for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next)
1947
 
                                write_bone_animation(ob, bone);
1948
 
                }
1949
 
                else {
1950
 
                        while (fcu) {
1951
 
                                // TODO "rotation_quaternion" is also possible for objects (although euler is default)
1952
 
                                if ((!strcmp(fcu->rna_path, "location") || !strcmp(fcu->rna_path, "scale")) ||
1953
 
                                        (!strcmp(fcu->rna_path, "rotation_euler") && ob->rotmode == ROT_MODE_EUL))
1954
 
                                        dae_animation(fcu, id_name(ob));
1955
 
 
1956
 
                                fcu = fcu->next;
1957
 
                        }
1958
 
                }
1959
 
        }
1960
 
 
1961
 
protected:
1962
 
 
1963
 
        void dae_animation(FCurve *fcu, std::string ob_name)
1964
 
        {
1965
 
                const char *axis_names[] = {"X", "Y", "Z"};
1966
 
                const char *axis_name = NULL;
1967
 
                char anim_id[200];
1968
 
                
1969
 
                if (fcu->array_index < 3)
1970
 
                        axis_name = axis_names[fcu->array_index];
1971
 
 
1972
 
                BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
1973
 
                                         fcu->rna_path, axis_names[fcu->array_index]);
1974
 
 
1975
 
                // check rna_path is one of: rotation, scale, location
1976
 
 
1977
 
                openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
1978
 
 
1979
 
                // create input source
1980
 
                std::string input_id = create_source_from_fcurve(Sampler::INPUT, fcu, anim_id, axis_name);
1981
 
 
1982
 
                // create output source
1983
 
                std::string output_id = create_source_from_fcurve(Sampler::OUTPUT, fcu, anim_id, axis_name);
1984
 
 
1985
 
                // create interpolations source
1986
 
                std::string interpolation_id = create_interpolation_source(fcu->totvert, anim_id, axis_name);
1987
 
 
1988
 
                std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
1989
 
                COLLADASW::LibraryAnimations::Sampler sampler(sampler_id);
1990
 
                std::string empty;
1991
 
                sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id));
1992
 
                sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id));
1993
 
 
1994
 
                // this input is required
1995
 
                sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
1996
 
 
1997
 
                addSampler(sampler);
1998
 
 
1999
 
                std::string target = translate_id(ob_name)
2000
 
                        + "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
2001
 
                addChannel(COLLADABU::URI(empty, sampler_id), target);
2002
 
 
2003
 
                closeAnimation();
2004
 
        }
2005
 
 
2006
 
        void write_bone_animation(Object *ob_arm, Bone *bone)
2007
 
        {
2008
 
                if (!ob_arm->adt)
2009
 
                        return;
2010
 
 
2011
 
                for (int i = 0; i < 3; i++)
2012
 
                        sample_and_write_bone_animation(ob_arm, bone, i);
2013
 
 
2014
 
                for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next)
2015
 
                        write_bone_animation(ob_arm, child);
2016
 
        }
2017
 
 
2018
 
        void sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
2019
 
        {
2020
 
                bArmature *arm = (bArmature*)ob_arm->data;
2021
 
                int flag = arm->flag;
2022
 
                std::vector<float> fra;
2023
 
                char prefix[256];
2024
 
 
2025
 
                BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
2026
 
 
2027
 
                bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
2028
 
                if (!pchan)
2029
 
                        return;
2030
 
 
2031
 
                switch (transform_type) {
2032
 
                case 0:
2033
 
                        find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
2034
 
                        break;
2035
 
                case 1:
2036
 
                        find_frames(ob_arm, fra, prefix, "scale");
2037
 
                        break;
2038
 
                case 2:
2039
 
                        find_frames(ob_arm, fra, prefix, "location");
2040
 
                        break;
2041
 
                default:
2042
 
                        return;
2043
 
                }
2044
 
 
2045
 
                // exit rest position
2046
 
                if (flag & ARM_RESTPOS) {
2047
 
                        arm->flag &= ~ARM_RESTPOS;
2048
 
                        where_is_pose(scene, ob_arm);
2049
 
                }
2050
 
 
2051
 
                if (fra.size()) {
2052
 
                        float *v = (float*)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
2053
 
                        sample_animation(v, fra, transform_type, bone, ob_arm);
2054
 
 
2055
 
                        if (transform_type == 0) {
2056
 
                                // write x, y, z curves separately if it is rotation
2057
 
                                float *c = (float*)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
2058
 
                                for (int i = 0; i < 3; i++) {
2059
 
                                        for (unsigned int j = 0; j < fra.size(); j++)
2060
 
                                                c[j] = v[j * 3 + i];
2061
 
 
2062
 
                                        dae_bone_animation(fra, c, transform_type, i, id_name(ob_arm), bone->name);
2063
 
                                }
2064
 
                                MEM_freeN(c);
2065
 
                        }
2066
 
                        else {
2067
 
                                // write xyz at once if it is location or scale
2068
 
                                dae_bone_animation(fra, v, transform_type, -1, id_name(ob_arm), bone->name);
2069
 
                        }
2070
 
 
2071
 
                        MEM_freeN(v);
2072
 
                }
2073
 
 
2074
 
                // restore restpos
2075
 
                if (flag & ARM_RESTPOS) 
2076
 
                        arm->flag = flag;
2077
 
                where_is_pose(scene, ob_arm);
2078
 
        }
2079
 
 
2080
 
        void sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm)
2081
 
        {
2082
 
                bPoseChannel *pchan, *parchan = NULL;
2083
 
                bPose *pose = ob_arm->pose;
2084
 
 
2085
 
                pchan = get_pose_channel(pose, bone->name);
2086
 
 
2087
 
                if (!pchan)
2088
 
                        return;
2089
 
 
2090
 
                parchan = pchan->parent;
2091
 
 
2092
 
                enable_fcurves(ob_arm->adt->action, bone->name);
2093
 
 
2094
 
                std::vector<float>::iterator it;
2095
 
                for (it = frames.begin(); it != frames.end(); it++) {
2096
 
                        float mat[4][4], ipar[4][4];
2097
 
 
2098
 
                        float ctime = bsystem_time(scene, ob_arm, *it, 0.0f);
2099
 
 
2100
 
                        BKE_animsys_evaluate_animdata(&ob_arm->id, ob_arm->adt, *it, ADT_RECALC_ANIM);
2101
 
                        where_is_pose_bone(scene, ob_arm, pchan, ctime, 1);
2102
 
 
2103
 
                        // compute bone local mat
2104
 
                        if (bone->parent) {
2105
 
                                invert_m4_m4(ipar, parchan->pose_mat);
2106
 
                                mul_m4_m4m4(mat, pchan->pose_mat, ipar);
2107
 
                        }
2108
 
                        else
2109
 
                                copy_m4_m4(mat, pchan->pose_mat);
2110
 
 
2111
 
                        switch (type) {
2112
 
                        case 0:
2113
 
                                mat4_to_eul(v, mat);
2114
 
                                break;
2115
 
                        case 1:
2116
 
                                mat4_to_size(v, mat);
2117
 
                                break;
2118
 
                        case 2:
2119
 
                                copy_v3_v3(v, mat[3]);
2120
 
                                break;
2121
 
                        }
2122
 
 
2123
 
                        v += 3;
2124
 
                }
2125
 
 
2126
 
                enable_fcurves(ob_arm->adt->action, NULL);
2127
 
        }
2128
 
 
2129
 
        // dae_bone_animation -> add_bone_animation
2130
 
        // (blend this into dae_bone_animation)
2131
 
        void dae_bone_animation(std::vector<float> &fra, float *v, int tm_type, int axis, std::string ob_name, std::string bone_name)
2132
 
        {
2133
 
                const char *axis_names[] = {"X", "Y", "Z"};
2134
 
                const char *axis_name = NULL;
2135
 
                char anim_id[200];
2136
 
                bool is_rot = tm_type == 0;
2137
 
                
2138
 
                if (!fra.size())
2139
 
                        return;
2140
 
 
2141
 
                char rna_path[200];
2142
 
                BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
2143
 
                                         tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
2144
 
 
2145
 
                if (axis > -1)
2146
 
                        axis_name = axis_names[axis];
2147
 
                
2148
 
                std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
2149
 
                
2150
 
                BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
2151
 
                                         (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str());
2152
 
 
2153
 
                openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
2154
 
 
2155
 
                // create input source
2156
 
                std::string input_id = create_source_from_vector(Sampler::INPUT, fra, is_rot, anim_id, axis_name);
2157
 
 
2158
 
                // create output source
2159
 
                std::string output_id;
2160
 
                if (axis == -1)
2161
 
                        output_id = create_xyz_source(v, fra.size(), anim_id);
2162
 
                else
2163
 
                        output_id = create_source_from_array(Sampler::OUTPUT, v, fra.size(), is_rot, anim_id, axis_name);
2164
 
 
2165
 
                // create interpolations source
2166
 
                std::string interpolation_id = create_interpolation_source(fra.size(), anim_id, axis_name);
2167
 
 
2168
 
                std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
2169
 
                COLLADASW::LibraryAnimations::Sampler sampler(sampler_id);
2170
 
                std::string empty;
2171
 
                sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id));
2172
 
                sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id));
2173
 
 
2174
 
                // TODO create in/out tangents source
2175
 
 
2176
 
                // this input is required
2177
 
                sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
2178
 
 
2179
 
                addSampler(sampler);
2180
 
 
2181
 
                std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
2182
 
                addChannel(COLLADABU::URI(empty, sampler_id), target);
2183
 
 
2184
 
                closeAnimation();
2185
 
        }
2186
 
 
2187
 
        float convert_time(float frame)
2188
 
        {
2189
 
                return FRA2TIME(frame);
2190
 
        }
2191
 
 
2192
 
        float convert_angle(float angle)
2193
 
        {
2194
 
                return COLLADABU::Math::Utils::radToDegF(angle);
2195
 
        }
2196
 
 
2197
 
        std::string get_semantic_suffix(Sampler::Semantic semantic)
2198
 
        {
2199
 
                switch(semantic) {
2200
 
                case Sampler::INPUT:
2201
 
                        return INPUT_SOURCE_ID_SUFFIX;
2202
 
                case Sampler::OUTPUT:
2203
 
                        return OUTPUT_SOURCE_ID_SUFFIX;
2204
 
                case Sampler::INTERPOLATION:
2205
 
                        return INTERPOLATION_SOURCE_ID_SUFFIX;
2206
 
                case Sampler::IN_TANGENT:
2207
 
                        return INTANGENT_SOURCE_ID_SUFFIX;
2208
 
                case Sampler::OUT_TANGENT:
2209
 
                        return OUTTANGENT_SOURCE_ID_SUFFIX;
2210
 
                default:
2211
 
                        break;
2212
 
                }
2213
 
                return "";
2214
 
        }
2215
 
 
2216
 
        void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
2217
 
                                                           Sampler::Semantic semantic, bool is_rot, const char *axis)
2218
 
        {
2219
 
                switch(semantic) {
2220
 
                case Sampler::INPUT:
2221
 
                        param.push_back("TIME");
2222
 
                        break;
2223
 
                case Sampler::OUTPUT:
2224
 
                        if (is_rot) {
2225
 
                                param.push_back("ANGLE");
2226
 
                        }
2227
 
                        else {
2228
 
                                if (axis) {
2229
 
                                        param.push_back(axis);
2230
 
                                }
2231
 
                                else {
2232
 
                                        param.push_back("X");
2233
 
                                        param.push_back("Y");
2234
 
                                        param.push_back("Z");
2235
 
                                }
2236
 
                        }
2237
 
                        break;
2238
 
                case Sampler::IN_TANGENT:
2239
 
                case Sampler::OUT_TANGENT:
2240
 
                        param.push_back("X");
2241
 
                        param.push_back("Y");
2242
 
                        break;
2243
 
                default:
2244
 
                        break;
2245
 
                }
2246
 
        }
2247
 
 
2248
 
        void get_source_values(BezTriple *bezt, Sampler::Semantic semantic, bool rotation, float *values, int *length)
2249
 
        {
2250
 
                switch (semantic) {
2251
 
                case Sampler::INPUT:
2252
 
                        *length = 1;
2253
 
                        values[0] = convert_time(bezt->vec[1][0]);
2254
 
                        break;
2255
 
                case Sampler::OUTPUT:
2256
 
                        *length = 1;
2257
 
                        if (rotation) {
2258
 
                                values[0] = convert_angle(bezt->vec[1][1]);
2259
 
                        }
2260
 
                        else {
2261
 
                                values[0] = bezt->vec[1][1];
2262
 
                        }
2263
 
                        break;
2264
 
                case Sampler::IN_TANGENT:
2265
 
                case Sampler::OUT_TANGENT:
2266
 
                        // XXX
2267
 
                        *length = 2;
2268
 
                        break;
2269
 
                default:
2270
 
                        *length = 0;
2271
 
                        break;
2272
 
                }
2273
 
        }
2274
 
 
2275
 
        std::string create_source_from_fcurve(Sampler::Semantic semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
2276
 
        {
2277
 
                std::string source_id = anim_id + get_semantic_suffix(semantic);
2278
 
 
2279
 
                //bool is_rotation = !strcmp(fcu->rna_path, "rotation");
2280
 
                bool is_rotation = false;
2281
 
                
2282
 
                if (strstr(fcu->rna_path, "rotation")) is_rotation = true;
2283
 
                
2284
 
                COLLADASW::FloatSourceF source(mSW);
2285
 
                source.setId(source_id);
2286
 
                source.setArrayId(source_id + ARRAY_ID_SUFFIX);
2287
 
                source.setAccessorCount(fcu->totvert);
2288
 
                source.setAccessorStride(1);
2289
 
                
2290
 
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
2291
 
                add_source_parameters(param, semantic, is_rotation, axis_name);
2292
 
 
2293
 
                source.prepareToAppendValues();
2294
 
 
2295
 
                for (unsigned int i = 0; i < fcu->totvert; i++) {
2296
 
                        float values[3]; // be careful!
2297
 
                        int length = 0;
2298
 
 
2299
 
                        get_source_values(&fcu->bezt[i], semantic, is_rotation, values, &length);
2300
 
                        for (int j = 0; j < length; j++)
2301
 
                                source.appendValues(values[j]);
2302
 
                }
2303
 
 
2304
 
                source.finish();
2305
 
 
2306
 
                return source_id;
2307
 
        }
2308
 
 
2309
 
        std::string create_source_from_array(Sampler::Semantic semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name)
2310
 
        {
2311
 
                std::string source_id = anim_id + get_semantic_suffix(semantic);
2312
 
 
2313
 
                COLLADASW::FloatSourceF source(mSW);
2314
 
                source.setId(source_id);
2315
 
                source.setArrayId(source_id + ARRAY_ID_SUFFIX);
2316
 
                source.setAccessorCount(tot);
2317
 
                source.setAccessorStride(1);
2318
 
                
2319
 
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
2320
 
                add_source_parameters(param, semantic, is_rot, axis_name);
2321
 
 
2322
 
                source.prepareToAppendValues();
2323
 
 
2324
 
                for (int i = 0; i < tot; i++) {
2325
 
                        float val = v[i];
2326
 
                        if (semantic == Sampler::INPUT)
2327
 
                                val = convert_time(val);
2328
 
                        else if (is_rot)
2329
 
                                val = convert_angle(val);
2330
 
                        source.appendValues(val);
2331
 
                }
2332
 
 
2333
 
                source.finish();
2334
 
 
2335
 
                return source_id;
2336
 
        }
2337
 
 
2338
 
        std::string create_source_from_vector(Sampler::Semantic semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name)
2339
 
        {
2340
 
                std::string source_id = anim_id + get_semantic_suffix(semantic);
2341
 
 
2342
 
                COLLADASW::FloatSourceF source(mSW);
2343
 
                source.setId(source_id);
2344
 
                source.setArrayId(source_id + ARRAY_ID_SUFFIX);
2345
 
                source.setAccessorCount(fra.size());
2346
 
                source.setAccessorStride(1);
2347
 
                
2348
 
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
2349
 
                add_source_parameters(param, semantic, is_rot, axis_name);
2350
 
 
2351
 
                source.prepareToAppendValues();
2352
 
 
2353
 
                std::vector<float>::iterator it;
2354
 
                for (it = fra.begin(); it != fra.end(); it++) {
2355
 
                        float val = *it;
2356
 
                        if (semantic == Sampler::INPUT)
2357
 
                                val = convert_time(val);
2358
 
                        else if (is_rot)
2359
 
                                val = convert_angle(val);
2360
 
                        source.appendValues(val);
2361
 
                }
2362
 
 
2363
 
                source.finish();
2364
 
 
2365
 
                return source_id;
2366
 
        }
2367
 
 
2368
 
        // only used for sources with OUTPUT semantic
2369
 
        std::string create_xyz_source(float *v, int tot, const std::string& anim_id)
2370
 
        {
2371
 
                Sampler::Semantic semantic = Sampler::OUTPUT;
2372
 
                std::string source_id = anim_id + get_semantic_suffix(semantic);
2373
 
 
2374
 
                COLLADASW::FloatSourceF source(mSW);
2375
 
                source.setId(source_id);
2376
 
                source.setArrayId(source_id + ARRAY_ID_SUFFIX);
2377
 
                source.setAccessorCount(tot);
2378
 
                source.setAccessorStride(3);
2379
 
                
2380
 
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
2381
 
                add_source_parameters(param, semantic, false, NULL);
2382
 
 
2383
 
                source.prepareToAppendValues();
2384
 
 
2385
 
                for (int i = 0; i < tot; i++) {
2386
 
                        source.appendValues(*v, *(v + 1), *(v + 2));
2387
 
                        v += 3;
2388
 
                }
2389
 
 
2390
 
                source.finish();
2391
 
 
2392
 
                return source_id;
2393
 
        }
2394
 
 
2395
 
        std::string create_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
2396
 
        {
2397
 
                std::string source_id = anim_id + get_semantic_suffix(Sampler::INTERPOLATION);
2398
 
 
2399
 
                COLLADASW::NameSource source(mSW);
2400
 
                source.setId(source_id);
2401
 
                source.setArrayId(source_id + ARRAY_ID_SUFFIX);
2402
 
                source.setAccessorCount(tot);
2403
 
                source.setAccessorStride(1);
2404
 
                
2405
 
                COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
2406
 
                param.push_back("INTERPOLATION");
2407
 
 
2408
 
                source.prepareToAppendValues();
2409
 
 
2410
 
                for (int i = 0; i < tot; i++) {
2411
 
                        source.appendValues(LINEAR_NAME);
2412
 
                }
2413
 
 
2414
 
                source.finish();
2415
 
 
2416
 
                return source_id;
2417
 
        }
2418
 
 
2419
 
        // for rotation, axis name is always appended and the value of append_axis is ignored
2420
 
        std::string get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
2421
 
        {
2422
 
                std::string tm_name;
2423
 
 
2424
 
                // when given rna_path, determine tm_type from it
2425
 
                if (rna_path) {
2426
 
                        char *name = extract_transform_name(rna_path);
2427
 
 
2428
 
                        if (strstr(name, "rotation"))
2429
 
                                tm_type = 0;
2430
 
                        else if (!strcmp(name, "scale"))
2431
 
                                tm_type = 1;
2432
 
                        else if (!strcmp(name, "location"))
2433
 
                                tm_type = 2;
2434
 
                        else
2435
 
                                tm_type = -1;
2436
 
                }
2437
 
 
2438
 
                switch (tm_type) {
2439
 
                case 0:
2440
 
                        return std::string("rotation") + std::string(axis_name) + ".ANGLE";
2441
 
                case 1:
2442
 
                        tm_name = "scale";
2443
 
                        break;
2444
 
                case 2:
2445
 
                        tm_name = "location";
2446
 
                        break;
2447
 
                default:
2448
 
                        tm_name = "";
2449
 
                        break;
2450
 
                }
2451
 
 
2452
 
                if (tm_name.size()) {
2453
 
                        if (append_axis)
2454
 
                                return tm_name + std::string(".") + std::string(axis_name);
2455
 
                        else
2456
 
                                return tm_name;
2457
 
                }
2458
 
 
2459
 
                return std::string("");
2460
 
        }
2461
 
 
2462
 
        char *extract_transform_name(char *rna_path)
2463
 
        {
2464
 
                char *dot = strrchr(rna_path, '.');
2465
 
                return dot ? (dot + 1) : rna_path;
2466
 
        }
2467
 
 
2468
 
        void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
2469
 
        {
2470
 
                FCurve *fcu= (FCurve*)ob->adt->action->curves.first;
2471
 
 
2472
 
                for (; fcu; fcu = fcu->next) {
2473
 
                        if (prefix && strncmp(prefix, fcu->rna_path, strlen(prefix)))
2474
 
                                continue;
2475
 
 
2476
 
                        char *name = extract_transform_name(fcu->rna_path);
2477
 
                        if (!strcmp(name, tm_name)) {
2478
 
                                for (unsigned int i = 0; i < fcu->totvert; i++) {
2479
 
                                        float f = fcu->bezt[i].vec[1][0];
2480
 
                                        if (std::find(fra.begin(), fra.end(), f) == fra.end())
2481
 
                                                fra.push_back(f);
2482
 
                                }
2483
 
                        }
2484
 
                }
2485
 
 
2486
 
                // keep the keys in ascending order
2487
 
                std::sort(fra.begin(), fra.end());
2488
 
        }
2489
 
 
2490
 
        void find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
2491
 
        {
2492
 
                if (rotmode > 0)
2493
 
                        find_frames(ob, fra, prefix, "rotation_euler");
2494
 
                else if (rotmode == ROT_MODE_QUAT)
2495
 
                        find_frames(ob, fra, prefix, "rotation_quaternion");
2496
 
                else if (rotmode == ROT_MODE_AXISANGLE)
2497
 
                        ;
2498
 
        }
2499
 
 
2500
 
        // enable fcurves driving a specific bone, disable all the rest
2501
 
        // if bone_name = NULL enable all fcurves
2502
 
        void enable_fcurves(bAction *act, char *bone_name)
2503
 
        {
2504
 
                FCurve *fcu;
2505
 
                char prefix[200];
2506
 
 
2507
 
                if (bone_name)
2508
 
                        BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
2509
 
 
2510
 
                for (fcu = (FCurve*)act->curves.first; fcu; fcu = fcu->next) {
2511
 
                        if (bone_name) {
2512
 
                                if (!strncmp(fcu->rna_path, prefix, strlen(prefix)))
2513
 
                                        fcu->flag &= ~FCURVE_DISABLED;
2514
 
                                else
2515
 
                                        fcu->flag |= FCURVE_DISABLED;
2516
 
                        }
2517
 
                        else {
2518
 
                                fcu->flag &= ~FCURVE_DISABLED;
2519
 
                        }
2520
 
                }
2521
 
        }
2522
 
};
2523
 
 
2524
 
void DocumentExporter::exportCurrentScene(Scene *sce, const char* filename)
2525
 
{
 
152
 
 
153
void DocumentExporter::exportCurrentScene(Scene *sce)
 
154
{
 
155
        PointerRNA sceneptr, unit_settings;
 
156
        PropertyRNA *system; /* unused , *scale; */
 
157
 
 
158
        clear_global_id_map();
 
159
        
2526
160
        COLLADABU::NativeString native_filename =
2527
 
                COLLADABU::NativeString(std::string(filename));
 
161
                COLLADABU::NativeString(std::string(this->export_settings->filepath));
2528
162
        COLLADASW::StreamWriter sw(native_filename);
2529
163
 
2530
 
        // open <Collada>
 
164
        // open <collada>
2531
165
        sw.startDocument();
2532
166
 
2533
167
        // <asset>
2534
168
        COLLADASW::Asset asset(&sw);
2535
 
        // XXX ask blender devs about this?
2536
 
        asset.setUnit("decimetre", 0.1);
 
169
 
 
170
        RNA_id_pointer_create(&(sce->id), &sceneptr);
 
171
        unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
 
172
        system = RNA_struct_find_property(&unit_settings, "system");
 
173
        //scale = RNA_struct_find_property(&unit_settings, "scale_length");
 
174
 
 
175
        std::string unitname = "meter";
 
176
        float linearmeasure = RNA_float_get(&unit_settings, "scale_length");
 
177
 
 
178
        switch(RNA_property_enum_get(&unit_settings, system)) {
 
179
                case USER_UNIT_NONE:
 
180
                case USER_UNIT_METRIC:
 
181
                        if (linearmeasure == 0.001f) {
 
182
                                unitname = "millimeter";
 
183
                        }
 
184
                        else if (linearmeasure == 0.01f) {
 
185
                                unitname = "centimeter";
 
186
                        }
 
187
                        else if (linearmeasure == 0.1f) {
 
188
                                unitname = "decimeter";
 
189
                        }
 
190
                        else if (linearmeasure == 1.0f) {
 
191
                                unitname = "meter";
 
192
                        }
 
193
                        else if (linearmeasure == 1000.0f) {
 
194
                                unitname = "kilometer";
 
195
                        }
 
196
                        break;
 
197
                case USER_UNIT_IMPERIAL:
 
198
                        if (linearmeasure == 0.0254f) {
 
199
                                unitname = "inch";
 
200
                        }
 
201
                        else if (linearmeasure == 0.3048f) {
 
202
                                unitname = "foot";
 
203
                        }
 
204
                        else if (linearmeasure == 0.9144f) {
 
205
                                unitname = "yard";
 
206
                        }
 
207
                        break;
 
208
                default:
 
209
                        break;
 
210
        }
 
211
 
 
212
        asset.setUnit(unitname, linearmeasure);
2537
213
        asset.setUpAxisType(COLLADASW::Asset::Z_UP);
 
214
        if (U.author[0] != '\0') {
 
215
                asset.getContributor().mAuthor = U.author;
 
216
        }
 
217
        else {
 
218
                asset.getContributor().mAuthor = "Blender User";
 
219
        }
 
220
        char version_buf[128];
 
221
#ifdef WITH_BUILDINFO
 
222
        sprintf(version_buf, "Blender %d.%02d.%d r%s", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION, build_rev);
 
223
#else
 
224
        sprintf(version_buf, "Blender %d.%02d.%d", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
 
225
#endif
 
226
        asset.getContributor().mAuthoringTool = version_buf;
2538
227
        asset.add();
2539
228
        
2540
229
        // <library_cameras>
2541
 
        CamerasExporter ce(&sw);
2542
 
        ce.exportCameras(sce);
 
230
        if (has_object_type(sce, OB_CAMERA)) {
 
231
                CamerasExporter ce(&sw, this->export_settings);
 
232
                ce.exportCameras(sce);
 
233
        }
2543
234
        
2544
235
        // <library_lights>
2545
 
        LightsExporter le(&sw);
2546
 
        le.exportLights(sce);
 
236
        if (has_object_type(sce, OB_LAMP)) {
 
237
                LightsExporter le(&sw, this->export_settings);
 
238
                le.exportLights(sce);
 
239
        }
2547
240
 
2548
241
        // <library_images>
2549
 
        ImagesExporter ie(&sw, filename);
 
242
        ImagesExporter ie(&sw, this->export_settings);
2550
243
        ie.exportImages(sce);
2551
244
        
2552
245
        // <library_effects>
2553
 
        EffectsExporter ee(&sw);
 
246
        EffectsExporter ee(&sw, this->export_settings);
2554
247
        ee.exportEffects(sce);
2555
248
        
2556
249
        // <library_materials>
2557
 
        MaterialsExporter me(&sw);
 
250
        MaterialsExporter me(&sw, this->export_settings);
2558
251
        me.exportMaterials(sce);
2559
252
 
2560
253
        // <library_geometries>
2561
 
        GeometryExporter ge(&sw);
2562
 
        ge.exportGeom(sce);
 
254
        if (has_object_type(sce, OB_MESH)) {
 
255
                GeometryExporter ge(&sw, this->export_settings);
 
256
                ge.exportGeom(sce);
 
257
        }
2563
258
 
2564
259
        // <library_animations>
2565
 
        AnimationExporter ae(&sw);
 
260
        AnimationExporter ae(&sw, this->export_settings);
2566
261
        ae.exportAnimations(sce);
2567
262
 
2568
263
        // <library_controllers>
2569
 
        ArmatureExporter arm_exporter(&sw);
2570
 
        arm_exporter.export_controllers(sce);
 
264
        ArmatureExporter arm_exporter(&sw, this->export_settings);
 
265
        if (has_object_type(sce, OB_ARMATURE)) {
 
266
                arm_exporter.export_controllers(sce);
 
267
        }
2571
268
 
2572
269
        // <library_visual_scenes>
2573
 
        SceneExporter se(&sw, &arm_exporter);
 
270
        SceneExporter se(&sw, &arm_exporter, this->export_settings);
2574
271
        se.exportScene(sce);
2575
272
        
2576
273
        // <scene>
2595
292
* AnimationExporter::sample_animation enables all curves on armature, this is undesirable for a user
2596
293
 
2597
294
 */
2598