COLLADA: Split ArmatureExporter, InstanceWriter and TransformWriter into separate...
authorNathan Letwory <nathan@letworyinteractive.com>
Wed, 6 Oct 2010 11:02:44 +0000 (11:02 +0000)
committerNathan Letwory <nathan@letworyinteractive.com>
Wed, 6 Oct 2010 11:02:44 +0000 (11:02 +0000)
source/blender/collada/ArmatureExporter.cpp [new file with mode: 0644]
source/blender/collada/ArmatureExporter.h [new file with mode: 0644]
source/blender/collada/DocumentExporter.cpp
source/blender/collada/InstanceWriter.cpp [new file with mode: 0644]
source/blender/collada/InstanceWriter.h [new file with mode: 0644]
source/blender/collada/TransformWriter.cpp [new file with mode: 0644]
source/blender/collada/TransformWriter.h [new file with mode: 0644]

diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
new file mode 100644 (file)
index 0000000..527ccd6
--- /dev/null
@@ -0,0 +1,469 @@
+/**
+ * $Id: DocumentExporter.cpp 32309 2010-10-05 00:05:14Z jesterking $
+ *
+ * ***** 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,
+ *                 Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "COLLADASWBaseInputElement.h"
+#include "COLLADASWInstanceController.h"
+#include "COLLADASWPrimitves.h"
+#include "COLLADASWSource.h"
+
+#include "DNA_action_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+
+#include "BLI_listBase.h"
+
+#include "GeometryExporter.h"
+#include "ArmatureExporter.h"
+
+// 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?
+ArmatureExporter::ArmatureExporter(COLLADASW::StreamWriter *sw) : COLLADASW::LibraryControllers(sw) {}
+
+// write bone nodes
+void ArmatureExporter::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 ArmatureExporter::is_skinned_mesh(Object *ob)
+{
+       return get_assigned_armature(ob) != NULL;
+}
+
+void ArmatureExporter::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 ArmatureExporter::export_controllers(Scene *sce)
+{
+       scene = sce;
+
+       openLibrary();
+
+       GeometryFunctor gf;
+       gf.forEachMeshObjectInScene<ArmatureExporter>(sce, *this);
+
+       closeLibrary();
+}
+
+void ArmatureExporter::operator()(Object *ob)
+{
+       Object *ob_arm = get_assigned_armature(ob);
+
+       if (ob_arm /*&& !already_written(ob_arm)*/)
+               export_controller(ob, ob_arm);
+}
+#if 0
+
+bool ArmatureExporter::already_written(Object *ob_arm)
+{
+       return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end();
+}
+
+void ArmatureExporter::wrote(Object *ob_arm)
+{
+       written_armatures.push_back(ob_arm);
+}
+
+void ArmatureExporter::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 *ArmatureExporter::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 ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm)
+{
+       return get_joint_id(bone, ob_arm);
+}
+
+// parent_mat is armature-space
+void ArmatureExporter::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 ArmatureExporter::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 ArmatureExporter::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 ArmatureExporter::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 ArmatureExporter::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 ArmatureExporter::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 ArmatureExporter::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 ArmatureExporter::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;
+
+       // put armature in rest position
+       if (!(arm->flag & ARM_RESTPOS)) {
+               arm->flag |= ARM_RESTPOS;
+               where_is_pose(scene, ob_arm);
+       }
+
+       for (bDeformGroup *def = (bDeformGroup*)defbase->first; def; def = def->next) {
+               if (is_bone_defgroup(ob_arm, def)) {
+
+                       bPoseChannel *pchan = get_pose_channel(pose, def->name);
+
+                       float mat[4][4];
+                       float world[4][4];
+                       float inv_bind_mat[4][4];
+
+                       // 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);
+
+                       source.appendValues(inv_bind_mat);
+               }
+       }
+
+       // back from rest positon
+       if (!(flag & ARM_RESTPOS)) {
+               arm->flag = flag;
+               where_is_pose(scene, ob_arm);
+       }
+
+       source.finish();
+
+       return source_id;
+}
+
+Bone *ArmatureExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup* def)
+{
+       bPoseChannel *pchan = get_pose_channel(ob_arm->pose, def->name);
+       return pchan ? pchan->bone : NULL;
+}
+
+bool ArmatureExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup* def)
+{
+       return get_bone_from_defgroup(ob_arm, def) != NULL;
+}
+
+std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& controller_id)
+{
+       std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
+
+       int i;
+       int totweight = 0;
+
+       for (i = 0; i < me->totvert; i++) {
+               totweight += me->dvert[i].totweight;
+       }
+
+       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");
+
+       source.prepareToAppendValues();
+
+       // NOTE: COLLADA spec says weights should be normalized
+
+       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();
+
+       return source_id;
+}
+
+void ArmatureExporter::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();
+}
diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h
new file mode 100644 (file)
index 0000000..fc3864a
--- /dev/null
@@ -0,0 +1,137 @@
+/**
+ * $Id: DocumentExporter.cpp 32309 2010-10-05 00:05:14Z jesterking $
+ *
+ * ***** 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,
+ *                 Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __ARMATUREEXPORTER_H__
+#define __ARMATUREEXPORTER_H__
+
+#include <string>
+//#include <vector>
+
+#include "COLLADASWStreamWriter.h"
+#include "COLLADASWLibraryControllers.h"
+#include "COLLADASWInputList.h"
+#include "COLLADASWNode.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_listBase.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "TransformWriter.h"
+#include "InstanceWriter.h"
+
+// 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);
+
+       // write bone nodes
+       void add_armature_bones(Object *ob_arm, Scene *sce);
+
+       bool is_skinned_mesh(Object *ob);
+
+       void add_instance_controller(Object *ob);
+
+       void export_controllers(Scene *sce);
+
+       void operator()(Object *ob);
+
+private:
+
+       UnitConverter converter;
+
+#if 0
+       std::vector<Object*> written_armatures;
+
+       bool already_written(Object *ob_arm);
+
+       void wrote(Object *ob_arm);
+
+       void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce);
+#endif
+
+       Object *get_assigned_armature(Object *ob);
+
+       std::string get_joint_sid(Bone *bone, Object *ob_arm);
+
+       // parent_mat is armature-space
+       void add_bone_node(Bone *bone, Object *ob_arm);
+
+       void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node);
+
+       std::string get_controller_id(Object *ob_arm, Object *ob);
+
+       // ob should be of type OB_MESH
+       // both args are required
+       void export_controller(Object* ob, Object *ob_arm);
+
+       void add_joints_element(ListBase *defbase,
+                                                       const std::string& joints_source_id, const std::string& inv_bind_mat_source_id);
+
+       void add_bind_shape_mat(Object *ob);
+
+       std::string add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id);
+
+       std::string add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id);
+
+       Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup* def);
+
+       bool is_bone_defgroup(Object *ob_arm, bDeformGroup* def);
+
+       std::string add_weights_source(Mesh *me, const std::string& controller_id);
+
+       void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, Mesh *me,
+                                                                       Object *ob_arm, ListBase *defbase);
+};
+
+/*
+struct GeometryFunctor {
+       // 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;
+                       
+               }
+       }
+};*/
+
+#endif
index 0a3166c37c3c4d162e917ce8d806df2e7daf2170..ad85a81c6f8b9d123a87d8877ef058648b517624 100644 (file)
@@ -34,8 +34,6 @@ extern "C"
 #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"
@@ -74,7 +72,6 @@ extern char build_rev[];
 #include "COLLADASWAsset.h"
 #include "COLLADASWLibraryVisualScenes.h"
 #include "COLLADASWNode.h"
-//#include "COLLADASWLibraryGeometries.h"
 #include "COLLADASWSource.h"
 #include "COLLADASWInstanceGeometry.h"
 #include "COLLADASWInputList.h"
@@ -95,11 +92,8 @@ extern char build_rev[];
 #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"
@@ -108,14 +102,19 @@ extern char build_rev[];
 #include "collada_internal.h"
 #include "DocumentExporter.h"
 
+#include "ArmatureExporter.h"
 #include "CameraExporter.h"
-#include "LightExporter.h"
 #include "GeometryExporter.h"
+#include "LightExporter.h"
+
+// can probably go after refactor is complete
+#include "InstanceWriter.h"
+#include "TransformWriter.h"
 
 #include <vector>
 #include <algorithm> // std::find
 
-char *CustomData_get_layer_name(const struct CustomData *data, int type, int n)
+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;
@@ -123,7 +122,7 @@ char *CustomData_get_layer_name(const struct CustomData *data, int type, int n)
        return data->layers[layer_index+n].name;
 }
 
-char *CustomData_get_active_layer_name(const CustomData *data, int type)
+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);
@@ -133,7 +132,6 @@ char *CustomData_get_active_layer_name(const CustomData *data, int type)
 }
 
 
-
 /*
   Utilities to avoid code duplication.
   Definition can take some time to understand, but they should be useful.
@@ -198,558 +196,11 @@ std::string getActiveUVLayerName(Object *ob)
 
        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 std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
                
        return "";
 }
 
-
-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();
-
-               GeometryFunctor gf;
-               gf.forEachMeshObjectInScene<ArmatureExporter>(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;
-
-               // put armature in rest position
-               if (!(arm->flag & ARM_RESTPOS)) {
-                       arm->flag |= ARM_RESTPOS;
-                       where_is_pose(scene, ob_arm);
-               }
-
-               for (bDeformGroup *def = (bDeformGroup*)defbase->first; def; def = def->next) {
-                       if (is_bone_defgroup(ob_arm, def)) {
-
-                               bPoseChannel *pchan = get_pose_channel(pose, def->name);
-
-                               float mat[4][4];
-                               float world[4][4];
-                               float inv_bind_mat[4][4];
-
-                               // 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);
-
-                               source.appendValues(inv_bind_mat);
-                       }
-               }
-
-               // back from rest positon
-               if (!(flag & ARM_RESTPOS)) {
-                       arm->flag = flag;
-                       where_is_pose(scene, ob_arm);
-               }
-
-               source.finish();
-
-               return source_id;
-       }
-
-       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;
-       }
-
-       bool is_bone_defgroup(Object *ob_arm, bDeformGroup* def)
-       {
-               return get_bone_from_defgroup(ob_arm, def) != NULL;
-       }
-
-       std::string add_weights_source(Mesh *me, const std::string& controller_id)
-       {
-               std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
-
-               int i;
-               int totweight = 0;
-
-               for (i = 0; i < me->totvert; i++) {
-                       totweight += me->dvert[i].totweight;
-               }
-
-               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");
-
-               source.prepareToAppendValues();
-
-               // NOTE: COLLADA spec says weights should be normalized
-
-               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();
-
-               return source_id;
-       }
-
-       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
 {
        ArmatureExporter *arm_exporter;
diff --git a/source/blender/collada/InstanceWriter.cpp b/source/blender/collada/InstanceWriter.cpp
new file mode 100644 (file)
index 0000000..a3260c8
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * $Id: DocumentExporter.cpp 32309 2010-10-05 00:05:14Z jesterking $
+ *
+ * ***** 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,
+ *                 Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string>
+
+#include "COLLADASWInstanceMaterial.h"
+
+#include "BKE_customdata.h"
+#include "BKE_material.h"
+
+#include "DNA_mesh_types.h"
+
+#include "InstanceWriter.h"
+
+#include "collada_internal.h"
+#include "collada_utils.h"
+
+void InstanceWriter::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 = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
+                               im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", b));
+                       }
+                       
+                       iml.push_back(im);
+               }
+       }
+}
diff --git a/source/blender/collada/InstanceWriter.h b/source/blender/collada/InstanceWriter.h
new file mode 100644 (file)
index 0000000..f7585bb
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * $Id: DocumentExporter.cpp 32309 2010-10-05 00:05:14Z jesterking $
+ *
+ * ***** 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,
+ *                 Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __INSTANCEWRITER_H__
+#define __INSTANCEWRITER_H__
+
+#include "COLLADASWBindMaterial.h"
+
+#include "DNA_object_types.h"
+
+class InstanceWriter
+{
+protected:
+       void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob);
+};
+
+#endif
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
new file mode 100644 (file)
index 0000000..21260a2
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * $Id: DocumentExporter.cpp 32309 2010-10-05 00:05:14Z jesterking $
+ *
+ * ***** 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,
+ *                 Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "BKE_object.h"
+
+#include "TransformWriter.h"
+
+#include "BLI_math.h"
+
+void TransformWriter::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 TransformWriter::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 TransformWriter::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);
+}
+
+void TransformWriter::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]);
+}
diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h
new file mode 100644 (file)
index 0000000..29aef72
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ * $Id: DocumentExporter.cpp 32309 2010-10-05 00:05:14Z jesterking $
+ *
+ * ***** 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,
+ *                 Nathan Letwory
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __TRANSFORMWRITER_H__
+#define __TRANSFORMWRITER_H__
+
+#include "COLLADASWNode.h"
+
+#include "DNA_object_types.h"
+
+#include "collada_internal.h"
+
+class TransformWriter : protected TransformBase
+{
+protected:
+       void add_node_transform(COLLADASW::Node& node, float mat[][4], float parent_mat[][4]);
+
+       void add_node_transform_ob(COLLADASW::Node& node, Object *ob);
+
+       void add_node_transform_identity(COLLADASW::Node& node);
+
+private:
+       void add_transform(COLLADASW::Node& node, float loc[3], float rot[3], float scale[3]);
+};
+
+#endif