merge with/from trunk at r35190
[blender.git] / source / blender / collada / DocumentExporter.cpp
index 5c059a4e9c9080811a4621048c4cda679ba69ca7..1a648f43097a7b25278d4ed2feb76fdb3b1eff53 100644 (file)
-/**
- * $Id$
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_image_types.h"
-#include "DNA_material_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_lamp_types.h"
-#include "DNA_anim_types.h"
-#include "DNA_action_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_modifier_types.h"
-
-extern "C" 
-{
-#include "BKE_DerivedMesh.h"
-#include "BKE_fcurve.h"
-#include "BKE_animsys.h"
-#include "BLI_path_util.h"
-#include "BLI_fileops.h"
-#include "ED_keyframing.h"
-#ifdef NAN_BUILDINFO
-extern char build_rev[];
-#endif
-}
-
-#include "MEM_guardedalloc.h"
-
-#include "BKE_blender.h" // version info
-#include "BKE_scene.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
-#include "BKE_material.h"
-#include "BKE_action.h" // pose functions
-#include "BKE_armature.h"
-#include "BKE_image.h"
-#include "BKE_utildefines.h"
-#include "BKE_object.h"
-
-#include "BLI_math.h"
-#include "BLI_string.h"
-#include "BLI_listbase.h"
-
-#include "COLLADASWAsset.h"
-#include "COLLADASWLibraryVisualScenes.h"
-#include "COLLADASWNode.h"
-#include "COLLADASWLibraryGeometries.h"
-#include "COLLADASWSource.h"
-#include "COLLADASWInstanceGeometry.h"
-#include "COLLADASWInputList.h"
-#include "COLLADASWPrimitves.h"
-#include "COLLADASWVertices.h"
-#include "COLLADASWLibraryAnimations.h"
-#include "COLLADASWLibraryImages.h"
-#include "COLLADASWLibraryEffects.h"
-#include "COLLADASWImage.h"
-#include "COLLADASWEffectProfile.h"
-#include "COLLADASWColorOrTexture.h"
-#include "COLLADASWParamTemplate.h"
-#include "COLLADASWParamBase.h"
-#include "COLLADASWSurfaceInitOption.h"
-#include "COLLADASWSampler.h"
-#include "COLLADASWScene.h"
-//#include "COLLADASWSurface.h"
-#include "COLLADASWTechnique.h"
-#include "COLLADASWTexture.h"
-#include "COLLADASWLibraryMaterials.h"
-#include "COLLADASWBindMaterial.h"
-#include "COLLADASWLibraryCameras.h"
-#include "COLLADASWLibraryLights.h"
-#include "COLLADASWInstanceCamera.h"
-#include "COLLADASWInstanceLight.h"
-#include "COLLADASWCameraOptic.h"
-#include "COLLADASWConstants.h"
-#include "COLLADASWLibraryControllers.h"
-#include "COLLADASWInstanceController.h"
-#include "COLLADASWBaseInputElement.h"
-
-#include "collada_internal.h"
-#include "DocumentExporter.h"
-
-#include <vector>
-#include <algorithm> // std::find
-
-// arithb.c now has QuatToAxisAngle too
-#if 0
-// This function assumes that quat is normalized.
-// The following document was used as reference:
-// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
-void quat_to_axis_angle( float *axis, float *angle,float *q)
-{
-       // quat to axis angle
-       *angle = 2 * acos(q[0]);
-       float divisor = sqrt(1 - q[0] * q[0]);
-
-       // test to avoid divide by zero, divisor is always positive
-       if (divisor < 0.001f ) {
-               axis[0] = 1.0f;
-               axis[1] = 0.0f;
-               axis[2] = 0.0f;
-       }
-       else {
-               axis[0] = q[1] / divisor;
-               axis[1] = q[2] / divisor;
-               axis[2] = q[3] / divisor;
-       }
-}
-#endif
-
-char *CustomData_get_layer_name(const struct CustomData *data, int type, int n)
-{
-       int layer_index = CustomData_get_layer_index(data, type);
-       if(layer_index < 0) return NULL;
-
-       return data->layers[layer_index+n].name;
-}
-
-char *CustomData_get_active_layer_name(const CustomData *data, int type)
-{
-       /* get the layer index of the active layer of type */
-       int layer_index = CustomData_get_active_layer_index(data, type);
-       if(layer_index < 0) return NULL;
-
-       return data->layers[layer_index].name;
-}
-
-/**
-Translation map.
-Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be
-included. Look at the IDREF XSD declaration for more.
-Follows strictly the COLLADA XSD declaration which explicitly allows non-english chars,
-like special chars (e.g. micro sign), umlauts and so on.
-The COLLADA spec also allows additional chars for member access ('.'), these
-must obviously be removed too, otherwise they would be heavily misinterpreted.
-*/
-const unsigned char translate_map[256] = {
-       95, 95, 95, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 45, 95, 95,
-       48, 49, 50, 51, 52, 53, 54, 55,
-       56, 57, 95, 95, 95, 95, 95, 95,
-       95, 65, 66, 67, 68, 69, 70, 71,
-       72, 73, 74, 75, 76, 77, 78, 79,
-       80, 81, 82, 83, 84, 85, 86, 87,
-       88, 89, 90, 95, 95, 95, 95, 95,
-       95, 97, 98, 99, 100, 101, 102, 103,
-       104, 105, 106, 107, 108, 109, 110, 111,
-       112, 113, 114, 115, 116, 117, 118, 119,
-       120, 121, 122, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 95, 95, 95,
-       95, 95, 95, 95, 95, 95, 95, 183,
-       95, 95, 95, 95, 95, 95, 95, 95,
-       192, 193, 194, 195, 196, 197, 198, 199,
-       200, 201, 202, 203, 204, 205, 206, 207,
-       208, 209, 210, 211, 212, 213, 214, 95,
-       216, 217, 218, 219, 220, 221, 222, 223,
-       224, 225, 226, 227, 228, 229, 230, 231,
-       232, 233, 234, 235, 236, 237, 238, 239,
-       240, 241, 242, 243, 244, 245, 246, 95,
-       248, 249, 250, 251, 252, 253, 254, 255};
-
-/** Look at documentation of translate_map */
-static std::string translate_id(const std::string &id)
-{
-       std::string id_translated = id;
-       for (unsigned int i=0; i < id_translated.size(); i++)
-       {
-               id_translated[i] = translate_map[(unsigned int)id_translated[i]];
-       }
-       return id_translated;
-}
-
-static std::string id_name(void *id)
-{
-       return ((ID*)id)->name + 2;
-}
-
-static std::string get_geometry_id(Object *ob)
-{
-       return translate_id(id_name(ob)) + "-mesh";
-}
-
-static std::string get_light_id(Object *ob)
-{
-       return translate_id(id_name(ob)) + "-light";
-}
-
-static std::string get_camera_id(Object *ob)
-{
-       return translate_id(id_name(ob)) + "-camera";
-}
-
-std::string get_joint_id(Bone *bone, Object *ob_arm)
-{
-       return translate_id(id_name(ob_arm) + "_" + bone->name);
-}
-
-
-/*
-  Utilities to avoid code duplication.
-  Definition can take some time to understand, but they should be useful.
-*/
-
-// f should have
-// void operator()(Object* ob)
-template<class Functor>
-void forEachMeshObjectInScene(Scene *sce, Functor &f)
-{
-       
-       Base *base= (Base*) sce->base.first;
-       while(base) {
-               Object *ob = base->object;
-               
-               if (ob->type == OB_MESH && ob->data) {
-                       f(ob);
-               }
-               base= base->next;
-               
-       }
-}
-
-template<class Functor>
-void forEachObjectInScene(Scene *sce, Functor &f)
-{
-       Base *base= (Base*) sce->base.first;
-       while(base) {
-               Object *ob = base->object;
-                       
-               f(ob);
-
-               base= base->next;
-       }
-}
-
-template<class Functor>
-void forEachCameraObjectInScene(Scene *sce, Functor &f)
-{
-       Base *base= (Base*) sce->base.first;
-       while(base) {
-               Object *ob = base->object;
-                       
-               if (ob->type == OB_CAMERA && ob->data) {
-                       f(ob, sce);
-               }
-               base= base->next;
-       }
-}
-
-template<class Functor>
-void forEachLampObjectInScene(Scene *sce, Functor &f)
-{
-       Base *base= (Base*) sce->base.first;
-       while(base) {
-               Object *ob = base->object;
-                       
-               if (ob->type == OB_LAMP && ob->data) {
-                       f(ob);
-               }
-               base= base->next;
-       }
-}
-
-// used in forEachMaterialInScene
-template <class MaterialFunctor>
-class ForEachMaterialFunctor
-{
-       std::vector<std::string> mMat; // contains list of material names, to avoid duplicate calling of f
-       MaterialFunctor *f;
-public:
-       ForEachMaterialFunctor(MaterialFunctor *f) : f(f) { }
-       void operator ()(Object *ob)
-       {
-               int a;
-               for(a = 0; a < ob->totcol; a++) {
-
-                       Material *ma = give_current_material(ob, a+1);
-
-                       if (!ma) continue;
-
-                       std::string translated_id = translate_id(id_name(ma));
-                       if (find(mMat.begin(), mMat.end(), translated_id) == mMat.end()) {
-                               (*this->f)(ma, ob);
-
-                               mMat.push_back(translated_id);
-                       }
-               }
-       }
-};
-
-// calls f for each unique material linked to each object in sce
-// f should have
-// void operator()(Material* ma)
-template<class Functor>
-void forEachMaterialInScene(Scene *sce, Functor &f)
-{
-       ForEachMaterialFunctor<Functor> matfunc(&f);
-       forEachMeshObjectInScene(sce, matfunc);
-}
-
-// OB_MESH is assumed
-std::string getActiveUVLayerName(Object *ob)
-{
-       Mesh *me = (Mesh*)ob->data;
-
-       int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-       if (num_layers)
-               return std::string(CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
-               
-       return "";
-}
-
-// TODO: optimize UV sets by making indexed list with duplicates removed
-class GeometryExporter : COLLADASW::LibraryGeometries
-{
-       struct Face
-       {
-               unsigned int v1, v2, v3, v4;
-       };
-
-       struct Normal
-       {
-               float x, y, z;
-       };
-
-       Scene *mScene;
-
-public:
-       GeometryExporter(COLLADASW::StreamWriter *sw) : COLLADASW::LibraryGeometries(sw) {}
-
-       void exportGeom(Scene *sce)
-       {
-               openLibrary();
-
-               mScene = sce;
-               forEachMeshObjectInScene(sce, *this);
-
-               closeLibrary();
-       }
-
-       void operator()(Object *ob)
-       {
-               // XXX don't use DerivedMesh, Mesh instead?
-
-#if 0          
-               DerivedMesh *dm = mesh_get_derived_final(mScene, ob, CD_MASK_BAREMESH);
-#endif
-               Mesh *me = (Mesh*)ob->data;
-               std::string geom_id = get_geometry_id(ob);
-               std::vector<Normal> nor;
-               std::vector<Face> norind;
-
-               bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL);
-
-               create_normals(nor, norind, me);
-
-               // openMesh(geoId, geoName, meshId)
-               openMesh(geom_id);
-               
-               // writes <source> for vertex coords
-               createVertsSource(geom_id, me);
-               
-               // writes <source> for normal coords
-               createNormalsSource(geom_id, me, nor);
-
-               bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE);
-               
-               // writes <source> for uv coords if mesh has uv coords
-               if (has_uvs)
-                       createTexcoordsSource(geom_id, me);
-
-               if (has_color)
-                       createVertexColorSource(geom_id, me);
-
-               // <vertices>
-               COLLADASW::Vertices verts(mSW);
-               verts.setId(getIdBySemantics(geom_id, COLLADASW::VERTEX));
-               COLLADASW::InputList &input_list = verts.getInputList();
-               COLLADASW::Input input(COLLADASW::POSITION, getUrlBySemantics(geom_id, COLLADASW::POSITION));
-               input_list.push_back(input);
-               verts.add();
-
-               // XXX slow             
-               if (ob->totcol) {
-                       for(int a = 0; a < ob->totcol; a++)     {
-                               // account for NULL materials, this should not normally happen?
-                               Material *ma = give_current_material(ob, a + 1);
-                               createPolylist(ma != NULL, a, has_uvs, has_color, ob, geom_id, norind);
-                       }
-               }
-               else {
-                       createPolylist(false, 0, has_uvs, has_color, ob, geom_id, norind);
-               }
-               
-               closeMesh();
-               closeGeometry();
-               
-#if 0
-               dm->release(dm);
-#endif
-       }
-
-       // powerful because it handles both cases when there is material and when there's not
-       void createPolylist(bool has_material,
-                                               int material_index,
-                                               bool has_uvs,
-                                               bool has_color,
-                                               Object *ob,
-                                               std::string& geom_id,
-                                               std::vector<Face>& norind)
-       {
-               Mesh *me = (Mesh*)ob->data;
-               MFace *mfaces = me->mface;
-               int totfaces = me->totface;
-
-               // <vcount>
-               int i;
-               int faces_in_polylist = 0;
-               std::vector<unsigned long> vcount_list;
-
-               // count faces with this material
-               for (i = 0; i < totfaces; i++) {
-                       MFace *f = &mfaces[i];
-                       
-                       if ((has_material && f->mat_nr == material_index) || !has_material) {
-                               faces_in_polylist++;
-                               if (f->v4 == 0) {
-                                       vcount_list.push_back(3);
-                               }
-                               else {
-                                       vcount_list.push_back(4);
-                               }
-                       }
-               }
-
-               // no faces using this material
-               if (faces_in_polylist == 0) {
-                       return;
-               }
-                       
-               Material *ma = has_material ? give_current_material(ob, material_index + 1) : NULL;
-               COLLADASW::Polylist polylist(mSW);
-                       
-               // sets count attribute in <polylist>
-               polylist.setCount(faces_in_polylist);
-                       
-               // sets material name
-               if (has_material) {
-                       polylist.setMaterial(translate_id(id_name(ma)));
-               }
-                               
-               COLLADASW::InputList &til = polylist.getInputList();
-                       
-               // creates <input> in <polylist> for vertices 
-               COLLADASW::Input input1(COLLADASW::VERTEX, getUrlBySemantics(geom_id, COLLADASW::VERTEX), 0);
-                       
-               // creates <input> in <polylist> for normals
-               COLLADASW::Input input2(COLLADASW::NORMAL, getUrlBySemantics(geom_id, COLLADASW::NORMAL), 1);
-                       
-               til.push_back(input1);
-               til.push_back(input2);
-                       
-               // if mesh has uv coords writes <input> for TEXCOORD
-               int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-
-               for (i = 0; i < num_layers; i++) {
-                       // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
-                       COLLADASW::Input input3(COLLADASW::TEXCOORD,
-                                                                       makeUrl(makeTexcoordSourceId(geom_id, i)),
-                                                                       2, // offset always 2, this is only until we have optimized UV sets
-                                                                       i  // set number equals UV layer index
-                                                                       );
-                       til.push_back(input3);
-               }
-
-               if (has_color) {
-                       COLLADASW::Input input4(COLLADASW::COLOR, getUrlBySemantics(geom_id, COLLADASW::COLOR), has_uvs ? 3 : 2);
-                       til.push_back(input4);
-               }
-                       
-               // sets <vcount>
-               polylist.setVCountList(vcount_list);
-                       
-               // performs the actual writing
-               polylist.prepareToAppendValues();
-                       
-               // <p>
-               int texindex = 0;
-               for (i = 0; i < totfaces; i++) {
-                       MFace *f = &mfaces[i];
-
-                       if ((has_material && f->mat_nr == material_index) || !has_material) {
-
-                               unsigned int *v = &f->v1;
-                               unsigned int *n = &norind[i].v1;
-                               for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) {
-                                       polylist.appendValues(v[j]);
-                                       polylist.appendValues(n[j]);
-
-                                       if (has_uvs)
-                                               polylist.appendValues(texindex + j);
-
-                                       if (has_color)
-                                               polylist.appendValues(texindex + j);
-                               }
-                       }
-
-                       texindex += 3;
-                       if (f->v4 != 0)
-                               texindex++;
-               }
-                       
-               polylist.finish();
-       }
-       
-       // creates <source> for positions
-       void createVertsSource(std::string geom_id, Mesh *me)
-       {
-#if 0
-               int totverts = dm->getNumVerts(dm);
-               MVert *verts = dm->getVertArray(dm);
-#endif
-               int totverts = me->totvert;
-               MVert *verts = me->mvert;
-               
-               COLLADASW::FloatSourceF source(mSW);
-               source.setId(getIdBySemantics(geom_id, COLLADASW::POSITION));
-               source.setArrayId(getIdBySemantics(geom_id, COLLADASW::POSITION) +
-                                                 ARRAY_ID_SUFFIX);
-               source.setAccessorCount(totverts);
-               source.setAccessorStride(3);
-               COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
-               param.push_back("X");
-               param.push_back("Y");
-               param.push_back("Z");
-               /*main function, it creates <source id = "">, <float_array id = ""
-                 count = ""> */
-               source.prepareToAppendValues();
-               //appends data to <float_array>
-               int i = 0;
-               for (i = 0; i < totverts; i++) {
-                       source.appendValues(verts[i].co[0], verts[i].co[1], verts[i].co[2]);                    
-               }
-               
-               source.finish();
-       
-       }
-
-       void createVertexColorSource(std::string geom_id, Mesh *me)
-       {
-               if (!CustomData_has_layer(&me->fdata, CD_MCOL))
-                       return;
-
-               MFace *f;
-               int totcolor = 0, i, j;
-
-               for (i = 0, f = me->mface; i < me->totface; i++, f++)
-                       totcolor += f->v4 ? 4 : 3;
-
-               COLLADASW::FloatSourceF source(mSW);
-               source.setId(getIdBySemantics(geom_id, COLLADASW::COLOR));
-               source.setArrayId(getIdBySemantics(geom_id, COLLADASW::COLOR) + ARRAY_ID_SUFFIX);
-               source.setAccessorCount(totcolor);
-               source.setAccessorStride(3);
-
-               COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
-               param.push_back("R");
-               param.push_back("G");
-               param.push_back("B");
-
-               source.prepareToAppendValues();
-
-               int index = CustomData_get_active_layer_index(&me->fdata, CD_MCOL);
-
-               MCol *mcol = (MCol*)me->fdata.layers[index].data;
-               MCol *c = mcol;
-
-               for (i = 0, f = me->mface; i < me->totface; i++, c += 4, f++)
-                       for (j = 0; j < (f->v4 ? 4 : 3); j++)
-                               source.appendValues(c[j].b / 255.0f, c[j].g / 255.0f, c[j].r / 255.0f);
-               
-               source.finish();
-       }
-
-       std::string makeTexcoordSourceId(std::string& geom_id, int layer_index)
-       {
-               char suffix[20];
-               sprintf(suffix, "-%d", layer_index);
-               return getIdBySemantics(geom_id, COLLADASW::TEXCOORD) + suffix;
-       }
-
-       //creates <source> for texcoords
-       void createTexcoordsSource(std::string geom_id, Mesh *me)
-       {
-#if 0
-               int totfaces = dm->getNumFaces(dm);
-               MFace *mfaces = dm->getFaceArray(dm);
-#endif
-               int totfaces = me->totface;
-               MFace *mfaces = me->mface;
-
-               int totuv = 0;
-               int i;
-
-               // count totuv
-               for (i = 0; i < totfaces; i++) {
-                       MFace *f = &mfaces[i];
-                       if (f->v4 == 0) {
-                               totuv+=3;
-                       }
-                       else {
-                               totuv+=4;
-                       }
-               }
-
-               int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-
-               // write <source> for each layer
-               // each <source> will get id like meshName + "map-channel-1"
-               for (int a = 0; a < num_layers; a++) {
-                       MTFace *tface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, a);
-                       // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, a);
-                       
-                       COLLADASW::FloatSourceF source(mSW);
-                       std::string layer_id = makeTexcoordSourceId(geom_id, a);
-                       source.setId(layer_id);
-                       source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
-                       
-                       source.setAccessorCount(totuv);
-                       source.setAccessorStride(2);
-                       COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
-                       param.push_back("S");
-                       param.push_back("T");
-                       
-                       source.prepareToAppendValues();
-                       
-                       for (i = 0; i < totfaces; i++) {
-                               MFace *f = &mfaces[i];
-                               
-                               for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) {
-                                       source.appendValues(tface[i].uv[j][0],
-                                                                               tface[i].uv[j][1]);
-                               }
-                       }
-                       
-                       source.finish();
-               }
-       }
-
-
-       //creates <source> for normals
-       void createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal>& nor)
-       {
-#if 0
-               int totverts = dm->getNumVerts(dm);
-               MVert *verts = dm->getVertArray(dm);
-#endif
-
-               COLLADASW::FloatSourceF source(mSW);
-               source.setId(getIdBySemantics(geom_id, COLLADASW::NORMAL));
-               source.setArrayId(getIdBySemantics(geom_id, COLLADASW::NORMAL) +
-                                                 ARRAY_ID_SUFFIX);
-               source.setAccessorCount(nor.size());
-               source.setAccessorStride(3);
-               COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
-               param.push_back("X");
-               param.push_back("Y");
-               param.push_back("Z");
-               
-               source.prepareToAppendValues();
-
-               std::vector<Normal>::iterator it;
-               for (it = nor.begin(); it != nor.end(); it++) {
-                       Normal& n = *it;
-                       source.appendValues(n.x, n.y, n.z);
-               }
-
-               source.finish();
-       }
-
-       void create_normals(std::vector<Normal> &nor, std::vector<Face> &ind, Mesh *me)
-       {
-               int i, j, v;
-               MVert *vert = me->mvert;
-               std::map<unsigned int, unsigned int> nshar;
-
-               for (i = 0; i < me->totface; i++) {
-                       MFace *fa = &me->mface[i];
-                       Face f;
-                       unsigned int *nn = &f.v1;
-                       unsigned int *vv = &fa->v1;
-
-                       memset(&f, 0, sizeof(f));
-                       v = fa->v4 == 0 ? 3 : 4;
-
-                       if (!(fa->flag & ME_SMOOTH)) {
-                               Normal n;
-                               if (v == 4)
-                                       normal_quad_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co, vert[fa->v4].co);
-                               else
-                                       normal_tri_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co);
-                               nor.push_back(n);
-                       }
-
-                       for (j = 0; j < v; j++) {
-                               if (fa->flag & ME_SMOOTH) {
-                                       if (nshar.find(*vv) != nshar.end())
-                                               *nn = nshar[*vv];
-                                       else {
-                                               Normal n = {
-                                                       vert[*vv].no[0]/32767.0,
-                                                       vert[*vv].no[1]/32767.0,
-                                                       vert[*vv].no[2]/32767.0
-                                               };
-                                               nor.push_back(n);
-                                               *nn = nor.size() - 1;
-                                               nshar[*vv] = *nn;
-                                       }
-                                       vv++;
-                               }
-                               else {
-                                       *nn = nor.size() - 1;
-                               }
-                               nn++;
-                       }
-
-                       ind.push_back(f);
-               }
-       }
-       
-       std::string getIdBySemantics(std::string geom_id, COLLADASW::Semantics type, std::string other_suffix = "") {
-               return geom_id + getSuffixBySemantic(type) + other_suffix;
-       }
-       
-       
-       COLLADASW::URI getUrlBySemantics(std::string geom_id, COLLADASW::Semantics type, std::string other_suffix = "") {
-               
-               std::string id(getIdBySemantics(geom_id, type, other_suffix));
-               return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
-               
-       }
-
-       COLLADASW::URI makeUrl(std::string id)
-       {
-               return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
-       }
-       
-
-       /*      int getTriCount(MFace *faces, int totface) {
-               int i;
-               int tris = 0;
-               for (i = 0; i < totface; i++) {
-                       // if quad
-                       if (faces[i].v4 != 0)
-                               tris += 2;
-                       else
-                               tris++;
-               }
-
-               return tris;
-               }*/
-};
-
-class TransformWriter : protected TransformBase
-{
-protected:
-       void add_node_transform(COLLADASW::Node& node, float mat[][4], float parent_mat[][4])
-       {
-               float loc[3], rot[3], scale[3];
-               float local[4][4];
-
-               if (parent_mat) {
-                       float invpar[4][4];
-                       invert_m4_m4(invpar, parent_mat);
-                       mul_m4_m4m4(local, mat, invpar);
-               }
-               else {
-                       copy_m4_m4(local, mat);
-               }
-
-               TransformBase::decompose(local, loc, rot, NULL, scale);
-               
-               add_transform(node, loc, rot, scale);
-       }
-
-       void add_node_transform_ob(COLLADASW::Node& node, Object *ob)
-       {
-               float rot[3], loc[3], scale[3];
-
-               if (ob->parent) {
-                       float C[4][4], tmat[4][4], imat[4][4], mat[4][4];
-
-                       // factor out scale from obmat
-
-                       copy_v3_v3(scale, ob->size);
-
-                       ob->size[0] = ob->size[1] = ob->size[2] = 1.0f;
-                       object_to_mat4(ob, C);
-                       copy_v3_v3(ob->size, scale);
-
-                       mul_serie_m4(tmat, ob->parent->obmat, ob->parentinv, C, NULL, NULL, NULL, NULL, NULL);
-
-                       // calculate local mat
-
-                       invert_m4_m4(imat, ob->parent->obmat);
-                       mul_m4_m4m4(mat, tmat, imat);
-
-                       // done
-
-                       mat4_to_eul(rot, mat);
-                       copy_v3_v3(loc, mat[3]);
-               }
-               else {
-                       copy_v3_v3(loc, ob->loc);
-                       copy_v3_v3(rot, ob->rot);
-                       copy_v3_v3(scale, ob->size);
-               }
-
-               add_transform(node, loc, rot, scale);
-       }
-
-       void add_node_transform_identity(COLLADASW::Node& node)
-       {
-               float loc[] = {0.0f, 0.0f, 0.0f}, scale[] = {1.0f, 1.0f, 1.0f}, rot[] = {0.0f, 0.0f, 0.0f};
-               add_transform(node, loc, rot, scale);
-       }
-
-private:
-       void add_transform(COLLADASW::Node& node, float loc[3], float rot[3], float scale[3])
-       {
-               node.addTranslate("location", loc[0], loc[1], loc[2]);
-               node.addRotateZ("rotationZ", COLLADABU::Math::Utils::radToDegF(rot[2]));
-               node.addRotateY("rotationY", COLLADABU::Math::Utils::radToDegF(rot[1]));
-               node.addRotateX("rotationX", COLLADABU::Math::Utils::radToDegF(rot[0]));
-               node.addScale("scale", scale[0], scale[1], scale[2]);
-       }
-};
-
-class InstanceWriter
-{
-protected:
-       void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob)
-       {
-               for(int a = 0; a < ob->totcol; a++)     {
-                       Material *ma = give_current_material(ob, a+1);
-                               
-                       COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
-
-                       if (ma) {
-                               std::string matid(id_name(ma));
-                               matid = translate_id(matid);
-                               COLLADASW::InstanceMaterial im(matid, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
-                               
-                               // create <bind_vertex_input> for each uv layer
-                               Mesh *me = (Mesh*)ob->data;
-                               int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-                               
-                               for (int b = 0; b < totlayer; b++) {
-                                       char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
-                                       im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", b));
-                               }
-                               
-                               iml.push_back(im);
-                       }
-               }
-       }
-};
-
-// XXX exporter writes wrong data for shared armatures.  A separate
-// controller should be written for each armature-mesh binding how do
-// we make controller ids then?
-class ArmatureExporter: public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter
-{
-private:
-       Scene *scene;
-
-public:
-       ArmatureExporter(COLLADASW::StreamWriter *sw) : COLLADASW::LibraryControllers(sw) {}
-
-       // write bone nodes
-       void add_armature_bones(Object *ob_arm, Scene *sce)
-       {
-               // write bone nodes
-               bArmature *arm = (bArmature*)ob_arm->data;
-               for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) {
-                       // start from root bones
-                       if (!bone->parent)
-                               add_bone_node(bone, ob_arm);
-               }
-       }
-
-       bool is_skinned_mesh(Object *ob)
-       {
-               return get_assigned_armature(ob) != NULL;
-       }
-
-       void add_instance_controller(Object *ob)
-       {
-               Object *ob_arm = get_assigned_armature(ob);
-               bArmature *arm = (bArmature*)ob_arm->data;
-
-               const std::string& controller_id = get_controller_id(ob_arm, ob);
-
-               COLLADASW::InstanceController ins(mSW);
-               ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
-
-               // write root bone URLs
-               Bone *bone;
-               for (bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) {
-                       if (!bone->parent)
-                               ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm)));
-               }
-
-               InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob);
-                       
-               ins.add();
-       }
-
-       void export_controllers(Scene *sce)
-       {
-               scene = sce;
-
-               openLibrary();
-
-               forEachMeshObjectInScene(sce, *this);
-
-               closeLibrary();
-       }
-
-       void operator()(Object *ob)
-       {
-               Object *ob_arm = get_assigned_armature(ob);
-
-               if (ob_arm /*&& !already_written(ob_arm)*/)
-                       export_controller(ob, ob_arm);
-       }
-
-private:
-
-       UnitConverter converter;
-
-#if 0
-       std::vector<Object*> written_armatures;
-
-       bool already_written(Object *ob_arm)
-       {
-               return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end();
-       }
-
-       void wrote(Object *ob_arm)
-       {
-               written_armatures.push_back(ob_arm);
-       }
-
-       void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce)
-       {
-               objects.clear();
-
-               Base *base= (Base*) sce->base.first;
-               while(base) {
-                       Object *ob = base->object;
-                       
-                       if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) {
-                               objects.push_back(ob);
-                       }
-
-                       base= base->next;
-               }
-       }
-#endif
-
-       Object *get_assigned_armature(Object *ob)
-       {
-               Object *ob_arm = NULL;
-
-               if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
-                       ob_arm = ob->parent;
-               }
-               else {
-                       ModifierData *mod = (ModifierData*)ob->modifiers.first;
-                       while (mod) {
-                               if (mod->type == eModifierType_Armature) {
-                                       ob_arm = ((ArmatureModifierData*)mod)->object;
-                               }
-
-                               mod = mod->next;
-                       }
-               }
-
-               return ob_arm;
-       }
-
-       std::string get_joint_sid(Bone *bone, Object *ob_arm)
-       {
-               return get_joint_id(bone, ob_arm);
-       }
-
-       // parent_mat is armature-space
-       void add_bone_node(Bone *bone, Object *ob_arm)
-       {
-               std::string node_id = get_joint_id(bone, ob_arm);
-               std::string node_name = std::string(bone->name);
-               std::string node_sid = get_joint_sid(bone, ob_arm);
-
-               COLLADASW::Node node(mSW);
-
-               node.setType(COLLADASW::Node::JOINT);
-               node.setNodeId(node_id);
-               node.setNodeName(node_name);
-               node.setNodeSid(node_sid);
-
-               node.start();
-
-               add_bone_transform(ob_arm, bone, node);
-
-               for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next) {
-                       add_bone_node(child, ob_arm);
-               }
-
-               node.end();
-       }
-
-       void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node)
-       {
-               bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
-
-               float mat[4][4];
-
-               if (bone->parent) {
-                       // get bone-space matrix from armature-space
-                       bPoseChannel *parchan = get_pose_channel(ob_arm->pose, bone->parent->name);
-
-                       float invpar[4][4];
-                       invert_m4_m4(invpar, parchan->pose_mat);
-                       mul_m4_m4m4(mat, pchan->pose_mat, invpar);
-               }
-               else {
-                       // get world-space from armature-space
-                       mul_m4_m4m4(mat, pchan->pose_mat, ob_arm->obmat);
-               }
-
-               TransformWriter::add_node_transform(node, mat, NULL);
-       }
-
-       std::string get_controller_id(Object *ob_arm, Object *ob)
-       {
-               return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
-       }
-
-       // ob should be of type OB_MESH
-       // both args are required
-       void export_controller(Object* ob, Object *ob_arm)
-       {
-               // joint names
-               // joint inverse bind matrices
-               // vertex weights
-
-               // input:
-               // joint names: ob -> vertex group names
-               // vertex group weights: me->dvert -> groups -> index, weight
-
-               /*
-               me->dvert:
-
-               typedef struct MDeformVert {
-                       struct MDeformWeight *dw;
-                       int totweight;
-                       int flag;       // flag only in use for weightpaint now
-               } MDeformVert;
-
-               typedef struct MDeformWeight {
-                       int                             def_nr;
-                       float                   weight;
-               } MDeformWeight;
-               */
-
-               Mesh *me = (Mesh*)ob->data;
-               if (!me->dvert) return;
-
-               std::string controller_name = id_name(ob_arm);
-               std::string controller_id = get_controller_id(ob_arm, ob);
-
-               openSkin(controller_id, controller_name,
-                                COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob)));
-
-               add_bind_shape_mat(ob);
-
-               std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id);
-               std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id);
-               std::string weights_source_id = add_weights_source(me, controller_id);
-
-               add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
-               add_vertex_weights_element(weights_source_id, joints_source_id, me, ob_arm, &ob->defbase);
-
-               closeSkin();
-               closeController();
-       }
-
-       void add_joints_element(ListBase *defbase,
-                                                       const std::string& joints_source_id, const std::string& inv_bind_mat_source_id)
-       {
-               COLLADASW::JointsElement joints(mSW);
-               COLLADASW::InputList &input = joints.getInputList();
-
-               input.push_back(COLLADASW::Input(COLLADASW::JOINT, // constant declared in COLLADASWInputList.h
-                                                                  COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id)));
-               input.push_back(COLLADASW::Input(COLLADASW::BINDMATRIX,
-                                                                  COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id)));
-               joints.add();
-       }
-
-       void add_bind_shape_mat(Object *ob)
-       {
-               double bind_mat[4][4];
-
-               converter.mat4_to_dae_double(bind_mat, ob->obmat);
-
-               addBindShapeTransform(bind_mat);
-       }
-
-       std::string add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
-       {
-               std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
-
-               int totjoint = 0;
-               bDeformGroup *def;
-               for (def = (bDeformGroup*)defbase->first; def; def = def->next) {
-                       if (is_bone_defgroup(ob_arm, def))
-                               totjoint++;
-               }
-
-               COLLADASW::NameSource source(mSW);
-               source.setId(source_id);
-               source.setArrayId(source_id + ARRAY_ID_SUFFIX);
-               source.setAccessorCount(totjoint);
-               source.setAccessorStride(1);
-               
-               COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
-               param.push_back("JOINT");
-
-               source.prepareToAppendValues();
-
-               for (def = (bDeformGroup*)defbase->first; def; def = def->next) {
-                       Bone *bone = get_bone_from_defgroup(ob_arm, def);
-                       if (bone)
-                               source.appendValues(get_joint_sid(bone, ob_arm));
-               }
-
-               source.finish();
-
-               return source_id;
-       }
-
-       std::string add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
-       {
-               std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
-
-               COLLADASW::FloatSourceF source(mSW);
-               source.setId(source_id);
-               source.setArrayId(source_id + ARRAY_ID_SUFFIX);
-               source.setAccessorCount(BLI_countlist(defbase));
-               source.setAccessorStride(16);
-               
-               source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
-               COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
-               param.push_back("TRANSFORM");
-
-               source.prepareToAppendValues();
-
-               bPose *pose = ob_arm->pose;
-               bArmature *arm = (bArmature*)ob_arm->data;
-
-               int flag = arm->flag;
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
 
-               // put armature in rest position
-               if (!(arm->flag & ARM_RESTPOS)) {
-                       arm->flag |= ARM_RESTPOS;
-                       where_is_pose(scene, ob_arm);
-               }
+extern "C" 
+{
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_image_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_userdef_types.h"
 
-               for (bDeformGroup *def = (bDeformGroup*)defbase->first; def; def = def->next) {
-                       if (is_bone_defgroup(ob_arm, def)) {
+#include "BKE_DerivedMesh.h"
+#include "BKE_fcurve.h"
+#include "BKE_animsys.h"
+#include "BLI_path_util.h"
+#include "BLI_fileops.h"
+#include "ED_keyframing.h"
+#ifdef NAN_BUILDINFO
+extern char build_rev[];
+#endif
+}
 
-                               bPoseChannel *pchan = get_pose_channel(pose, def->name);
+#include "MEM_guardedalloc.h"
 
-                               float mat[4][4];
-                               float world[4][4];
-                               float inv_bind_mat[4][4];
+#include "BKE_blender.h" // version info
+#include "BKE_scene.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_action.h" // pose functions
+#include "BKE_armature.h"
+#include "BKE_image.h"
+#include "BKE_utildefines.h"
+#include "BKE_object.h"
 
-                               // make world-space matrix, pose_mat is armature-space
-                               mul_m4_m4m4(world, pchan->pose_mat, ob_arm->obmat);
-                               
-                               invert_m4_m4(mat, world);
-                               converter.mat4_to_dae(inv_bind_mat, mat);
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_listbase.h"
 
-                               source.appendValues(inv_bind_mat);
-                       }
-               }
+#include "RNA_access.h"
 
-               // back from rest positon
-               if (!(flag & ARM_RESTPOS)) {
-                       arm->flag = flag;
-                       where_is_pose(scene, ob_arm);
-               }
+#include "COLLADASWAsset.h"
+#include "COLLADASWLibraryVisualScenes.h"
+#include "COLLADASWNode.h"
+#include "COLLADASWSource.h"
+#include "COLLADASWInstanceGeometry.h"
+#include "COLLADASWInputList.h"
+#include "COLLADASWPrimitves.h"
+#include "COLLADASWVertices.h"
+#include "COLLADASWLibraryAnimations.h"
+#include "COLLADASWLibraryImages.h"
+#include "COLLADASWLibraryEffects.h"
+#include "COLLADASWImage.h"
+#include "COLLADASWEffectProfile.h"
+#include "COLLADASWColorOrTexture.h"
+#include "COLLADASWParamTemplate.h"
+#include "COLLADASWParamBase.h"
+#include "COLLADASWSurfaceInitOption.h"
+#include "COLLADASWSampler.h"
+#include "COLLADASWScene.h"
+#include "COLLADASWTechnique.h"
+#include "COLLADASWTexture.h"
+#include "COLLADASWLibraryMaterials.h"
+#include "COLLADASWBindMaterial.h"
+#include "COLLADASWInstanceCamera.h"
+#include "COLLADASWInstanceLight.h"
+#include "COLLADASWConstants.h"
+#include "COLLADASWLibraryControllers.h"
+#include "COLLADASWInstanceController.h"
+#include "COLLADASWBaseInputElement.h"
 
-               source.finish();
+#include "collada_internal.h"
+#include "DocumentExporter.h"
 
-               return source_id;
-       }
+// can probably go after refactor is complete
+#include "InstanceWriter.h"
+#include "TransformWriter.h"
 
-       Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup* def)
-       {
-               bPoseChannel *pchan = get_pose_channel(ob_arm->pose, def->name);
-               return pchan ? pchan->bone : NULL;
-       }
+#include "ArmatureExporter.h"
+#include "CameraExporter.h"
+#include "EffectExporter.h"
+#include "GeometryExporter.h"
+#include "ImageExporter.h"
+#include "LightExporter.h"
+#include "MaterialExporter.h"
 
-       bool is_bone_defgroup(Object *ob_arm, bDeformGroup* def)
-       {
-               return get_bone_from_defgroup(ob_arm, def) != NULL;
-       }
+#include <vector>
+#include <algorithm> // std::find
 
-       std::string add_weights_source(Mesh *me, const std::string& controller_id)
-       {
-               std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
+char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n)
+{
+       int layer_index = CustomData_get_layer_index(data, type);
+       if(layer_index < 0) return NULL;
 
-               int i;
-               int totweight = 0;
+       return data->layers[layer_index+n].name;
+}
 
-               for (i = 0; i < me->totvert; i++) {
-                       totweight += me->dvert[i].totweight;
-               }
+char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
+{
+       /* get the layer index of the active layer of type */
+       int layer_index = CustomData_get_active_layer_index(data, type);
+       if(layer_index < 0) return NULL;
 
-               COLLADASW::FloatSourceF source(mSW);
-               source.setId(source_id);
-               source.setArrayId(source_id + ARRAY_ID_SUFFIX);
-               source.setAccessorCount(totweight);
-               source.setAccessorStride(1);
-               
-               COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
-               param.push_back("WEIGHT");
+       return data->layers[layer_index].name;
+}
 
-               source.prepareToAppendValues();
 
-               // NOTE: COLLADA spec says weights should be normalized
+/*
+  Utilities to avoid code duplication.
+  Definition can take some time to understand, but they should be useful.
+*/
 
-               for (i = 0; i < me->totvert; i++) {
-                       MDeformVert *vert = &me->dvert[i];
-                       for (int j = 0; j < vert->totweight; j++) {
-                               source.appendValues(vert->dw[j].weight);
-                       }
-               }
 
-               source.finish();
+template<class Functor>
+void forEachObjectInScene(Scene *sce, Functor &f)
+{
+       Base *base= (Base*) sce->base.first;
+       while(base) {
+               Object *ob = base->object;
+                       
+               f(ob);
 
-               return source_id;
+               base= base->next;
        }
+}
 
-       void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, Mesh *me,
-                                                                       Object *ob_arm, ListBase *defbase)
-       {
-               COLLADASW::VertexWeightsElement weights(mSW);
-               COLLADASW::InputList &input = weights.getInputList();
-
-               int offset = 0;
-               input.push_back(COLLADASW::Input(COLLADASW::JOINT, // constant declared in COLLADASWInputList.h
-                                                                                COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++));
-        input.push_back(COLLADASW::Input(COLLADASW::WEIGHT,
-                                                                                COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++));
-
-               weights.setCount(me->totvert);
-
-               // write number of deformers per vertex
-               COLLADASW::PrimitivesBase::VCountList vcount;
-               int i;
-               for (i = 0; i < me->totvert; i++) {
-                       vcount.push_back(me->dvert[i].totweight);
-               }
-
-               weights.prepareToAppendVCountValues();
-               weights.appendVertexCount(vcount);
-
-               // def group index -> joint index
-               std::map<int, int> joint_index_by_def_index;
-               bDeformGroup *def;
-               int j;
-               for (def = (bDeformGroup*)defbase->first, i = 0, j = 0; def; def = def->next, i++) {
-                       if (is_bone_defgroup(ob_arm, def))
-                               joint_index_by_def_index[i] = j++;
-                       else
-                               joint_index_by_def_index[i] = -1;
-               }
-
-               weights.CloseVCountAndOpenVElement();
-
-               // write deformer index - weight index pairs
-               int weight_index = 0;
-               for (i = 0; i < me->totvert; i++) {
-                       MDeformVert *dvert = &me->dvert[i];
-                       for (int j = 0; j < dvert->totweight; j++) {
-                               weights.appendValues(joint_index_by_def_index[dvert->dw[j].def_nr]);
-                               weights.appendValues(weight_index++);
-                       }
-               }
 
-               weights.finish();
-       }
-};
 
 class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter, protected InstanceWriter
 {
@@ -1474,6 +290,7 @@ public:
        }
 };
 
+<<<<<<< .working
 class ImagesExporter: COLLADASW::LibraryImages
 {
        const char *mfilename;
@@ -1911,16 +728,19 @@ public:
        }
 };
 
+=======
+>>>>>>> .merge-right.r35190
 // TODO: it would be better to instantiate animations rather than create a new one per object
 // COLLADA allows this through multiple <channel>s in <animation>.
 // For this to work, we need to know objects that use a certain action.
 class AnimationExporter: COLLADASW::LibraryAnimations
 {
        Scene *scene;
+       COLLADASW::StreamWriter *sw;
 
 public:
 
-       AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) {}
+       AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) { this->sw = sw; }
 
        void exportAnimations(Scene *sce)
        {
@@ -1978,22 +798,22 @@ protected:
                openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
 
                // create input source
-               std::string input_id = create_source_from_fcurve(Sampler::INPUT, fcu, anim_id, axis_name);
+               std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
 
                // create output source
-               std::string output_id = create_source_from_fcurve(Sampler::OUTPUT, fcu, anim_id, axis_name);
+               std::string output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name);
 
                // create interpolations source
                std::string interpolation_id = create_interpolation_source(fcu->totvert, anim_id, axis_name);
 
                std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
-               COLLADASW::LibraryAnimations::Sampler sampler(sampler_id);
+               COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
                std::string empty;
-               sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id));
-               sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id));
+               sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
+               sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
 
                // this input is required
-               sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+               sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
 
                addSampler(sampler);
 
@@ -2154,28 +974,28 @@ protected:
                openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
 
                // create input source
-               std::string input_id = create_source_from_vector(Sampler::INPUT, fra, is_rot, anim_id, axis_name);
+               std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
 
                // create output source
                std::string output_id;
                if (axis == -1)
                        output_id = create_xyz_source(v, fra.size(), anim_id);
                else
-                       output_id = create_source_from_array(Sampler::OUTPUT, v, fra.size(), is_rot, anim_id, axis_name);
+                       output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, v, fra.size(), is_rot, anim_id, axis_name);
 
                // create interpolations source
                std::string interpolation_id = create_interpolation_source(fra.size(), anim_id, axis_name);
 
                std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
-               COLLADASW::LibraryAnimations::Sampler sampler(sampler_id);
+               COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
                std::string empty;
-               sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id));
-               sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id));
+               sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
+               sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
 
                // TODO create in/out tangents source
 
                // this input is required
-               sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+               sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
 
                addSampler(sampler);
 
@@ -2195,18 +1015,18 @@ protected:
                return COLLADABU::Math::Utils::radToDegF(angle);
        }
 
-       std::string get_semantic_suffix(Sampler::Semantic semantic)
+       std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
        {
                switch(semantic) {
-               case Sampler::INPUT:
+               case COLLADASW::InputSemantic::INPUT:
                        return INPUT_SOURCE_ID_SUFFIX;
-               case Sampler::OUTPUT:
+               case COLLADASW::InputSemantic::OUTPUT:
                        return OUTPUT_SOURCE_ID_SUFFIX;
-               case Sampler::INTERPOLATION:
+               case COLLADASW::InputSemantic::INTERPOLATION:
                        return INTERPOLATION_SOURCE_ID_SUFFIX;
-               case Sampler::IN_TANGENT:
+               case COLLADASW::InputSemantic::IN_TANGENT:
                        return INTANGENT_SOURCE_ID_SUFFIX;
-               case Sampler::OUT_TANGENT:
+               case COLLADASW::InputSemantic::OUT_TANGENT:
                        return OUTTANGENT_SOURCE_ID_SUFFIX;
                default:
                        break;
@@ -2215,13 +1035,13 @@ protected:
        }
 
        void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
-                                                          Sampler::Semantic semantic, bool is_rot, const char *axis)
+                                                          COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis)
        {
                switch(semantic) {
-               case Sampler::INPUT:
+               case COLLADASW::InputSemantic::INPUT:
                        param.push_back("TIME");
                        break;
-               case Sampler::OUTPUT:
+               case COLLADASW::InputSemantic::OUTPUT:
                        if (is_rot) {
                                param.push_back("ANGLE");
                        }
@@ -2236,8 +1056,8 @@ protected:
                                }
                        }
                        break;
-               case Sampler::IN_TANGENT:
-               case Sampler::OUT_TANGENT:
+               case COLLADASW::InputSemantic::IN_TANGENT:
+               case COLLADASW::InputSemantic::OUT_TANGENT:
                        param.push_back("X");
                        param.push_back("Y");
                        break;
@@ -2246,14 +1066,14 @@ protected:
                }
        }
 
-       void get_source_values(BezTriple *bezt, Sampler::Semantic semantic, bool rotation, float *values, int *length)
+       void get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length)
        {
                switch (semantic) {
-               case Sampler::INPUT:
+               case COLLADASW::InputSemantic::INPUT:
                        *length = 1;
                        values[0] = convert_time(bezt->vec[1][0]);
                        break;
-               case Sampler::OUTPUT:
+               case COLLADASW::InputSemantic::OUTPUT:
                        *length = 1;
                        if (rotation) {
                                values[0] = convert_angle(bezt->vec[1][1]);
@@ -2262,8 +1082,8 @@ protected:
                                values[0] = bezt->vec[1][1];
                        }
                        break;
-               case Sampler::IN_TANGENT:
-               case Sampler::OUT_TANGENT:
+               case COLLADASW::InputSemantic::IN_TANGENT:
+               case COLLADASW::InputSemantic::OUT_TANGENT:
                        // XXX
                        *length = 2;
                        break;
@@ -2273,7 +1093,7 @@ protected:
                }
        }
 
-       std::string create_source_from_fcurve(Sampler::Semantic semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
+       std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
        {
                std::string source_id = anim_id + get_semantic_suffix(semantic);
 
@@ -2307,7 +1127,7 @@ protected:
                return source_id;
        }
 
-       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)
+       std::string create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name)
        {
                std::string source_id = anim_id + get_semantic_suffix(semantic);
 
@@ -2324,7 +1144,7 @@ protected:
 
                for (int i = 0; i < tot; i++) {
                        float val = v[i];
-                       if (semantic == Sampler::INPUT)
+                       if (semantic == COLLADASW::InputSemantic::INPUT)
                                val = convert_time(val);
                        else if (is_rot)
                                val = convert_angle(val);
@@ -2336,7 +1156,7 @@ protected:
                return source_id;
        }
 
-       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)
+       std::string create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name)
        {
                std::string source_id = anim_id + get_semantic_suffix(semantic);
 
@@ -2354,7 +1174,7 @@ protected:
                std::vector<float>::iterator it;
                for (it = fra.begin(); it != fra.end(); it++) {
                        float val = *it;
-                       if (semantic == Sampler::INPUT)
+                       if (semantic == COLLADASW::InputSemantic::INPUT)
                                val = convert_time(val);
                        else if (is_rot)
                                val = convert_angle(val);
@@ -2369,7 +1189,7 @@ protected:
        // only used for sources with OUTPUT semantic
        std::string create_xyz_source(float *v, int tot, const std::string& anim_id)
        {
-               Sampler::Semantic semantic = Sampler::OUTPUT;
+               COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
                std::string source_id = anim_id + get_semantic_suffix(semantic);
 
                COLLADASW::FloatSourceF source(mSW);
@@ -2395,7 +1215,7 @@ protected:
 
        std::string create_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
        {
-               std::string source_id = anim_id + get_semantic_suffix(Sampler::INTERPOLATION);
+               std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
 
                COLLADASW::NameSource source(mSW);
                source.setId(source_id);
@@ -2494,8 +1314,8 @@ protected:
                        find_frames(ob, fra, prefix, "rotation_euler");
                else if (rotmode == ROT_MODE_QUAT)
                        find_frames(ob, fra, prefix, "rotation_quaternion");
-               else if (rotmode == ROT_MODE_AXISANGLE)
-                       ;
+               /*else if (rotmode == ROT_MODE_AXISANGLE)
+                       ;*/
        }
 
        // enable fcurves driving a specific bone, disable all the rest
@@ -2524,18 +1344,68 @@ protected:
 
 void DocumentExporter::exportCurrentScene(Scene *sce, const char* filename)
 {
+       PointerRNA sceneptr, unit_settings;
+       PropertyRNA *system; /* unused , *scale; */
+
+       clear_global_id_map();
+       
        COLLADABU::NativeString native_filename =
                COLLADABU::NativeString(std::string(filename));
        COLLADASW::StreamWriter sw(native_filename);
 
-       // open <Collada>
+       // open <collada>
        sw.startDocument();
 
        // <asset>
        COLLADASW::Asset asset(&sw);
-       // XXX ask blender devs about this?
-       asset.setUnit("decimetre", 0.1);
+
+       RNA_id_pointer_create(&(sce->id), &sceneptr);
+       unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
+       system = RNA_struct_find_property(&unit_settings, "system");
+       //scale = RNA_struct_find_property(&unit_settings, "scale_length");
+
+       std::string unitname = "meter";
+       float linearmeasure = 1.0f;
+
+       linearmeasure = RNA_float_get(&unit_settings, "scale_length");
+
+       switch(RNA_property_enum_get(&unit_settings, system)) {
+               case USER_UNIT_NONE:
+               case USER_UNIT_METRIC:
+                       if(linearmeasure == 0.001f) {
+                               unitname = "millimeter";
+                       }
+                       else if(linearmeasure == 0.01f) {
+                               unitname = "centimeter";
+                       }
+                       else if(linearmeasure == 0.1f) {
+                               unitname = "decimeter";
+                       }
+                       else if(linearmeasure == 1.0f) {
+                               unitname = "meter";
+                       }
+                       else if(linearmeasure == 1000.0f) {
+                               unitname = "kilometer";
+                       }
+                       break;
+               case USER_UNIT_IMPERIAL:
+                       if(linearmeasure == 0.0254f) {
+                               unitname = "inch";
+                       }
+                       else if(linearmeasure == 0.3048f) {
+                               unitname = "foot";
+                       }
+                       else if(linearmeasure == 0.9144f) {
+                               unitname = "yard";
+                       }
+                       break;
+               default:
+                       break;
+       }
+
+       asset.setUnit(unitname, linearmeasure);
        asset.setUpAxisType(COLLADASW::Asset::Z_UP);
+<<<<<<< .working
        // TODO: need an Author field in userpref
        asset.getContributor().mAuthor = "Blender User";
 #ifdef NAN_BUILDINFO
@@ -2545,6 +1415,22 @@ void DocumentExporter::exportCurrentScene(Scene *sce, const char* filename)
 #else
        asset.getContributor().mAuthoringTool = "Blender 2.5x";
 #endif
+=======
+       // TODO: need an Author field in userpref
+       if(strlen(U.author) > 0) {
+               asset.getContributor().mAuthor = U.author;
+       }
+       else {
+               asset.getContributor().mAuthor = "Blender User";
+       }
+#ifdef NAN_BUILDINFO
+       char version_buf[128];
+       sprintf(version_buf, "Blender %d.%02d.%d r%s", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION, build_rev);
+       asset.getContributor().mAuthoringTool = version_buf;
+#else
+       asset.getContributor().mAuthoringTool = "Blender 2.5x";
+#endif
+>>>>>>> .merge-right.r35190
        asset.add();
        
        // <library_cameras>