Revision: 21970
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=21970
Author:   kazanbas
Date:     2009-07-28 14:08:54 +0200 (Tue, 28 Jul 2009)

Log Message:
-----------
Added armature export in COLLADA exporter (not complete yet).

For each object in scene linked with armature writing the following information:
- bone names
- vertex weights
- bone inverse bind matrices (fake values for now)

Assuming objects don't share Armatures for now.

Modified Paths:
--------------
    branches/soc-2009-chingachgook/source/blender/collada/DocumentExporter.cpp

Added Paths:
-----------
    branches/soc-2009-chingachgook/source/blender/collada/collada_internal.h

Modified: 
branches/soc-2009-chingachgook/source/blender/collada/DocumentExporter.cpp
===================================================================
--- branches/soc-2009-chingachgook/source/blender/collada/DocumentExporter.cpp  
2009-07-28 11:04:32 UTC (rev 21969)
+++ branches/soc-2009-chingachgook/source/blender/collada/DocumentExporter.cpp  
2009-07-28 12:08:54 UTC (rev 21970)
@@ -14,6 +14,8 @@
 #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" 
 {
@@ -24,12 +26,12 @@
 #include "BKE_global.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
+#include "BKE_action.h" // pose functions
 
 #include "BLI_arithb.h"
 #include "BLI_string.h"
+#include "BLI_listbase.h"
 
-#include "DocumentExporter.h"
-
 #include "COLLADASWAsset.h"
 #include "COLLADASWLibraryVisualScenes.h"
 #include "COLLADASWNode.h"
@@ -60,7 +62,13 @@
 #include "COLLADASWInstanceCamera.h"
 #include "COLLADASWInstanceLight.h"
 #include "COLLADASWCameraOptic.h"
+#include "COLLADASWConstants.h"
+#include "COLLADASWLibraryControllers.h"
+#include "COLLADASWBaseInputElement.h"
 
+#include "collada_internal.h"
+#include "DocumentExporter.h"
+
 #include <vector>
 #include <algorithm> // std::find
 
@@ -551,6 +559,259 @@
                }*/
 };
 
+// XXX exporter assumes armatures are not shared between meshes.
+class ArmatureExporter: COLLADASW::LibraryControllers
+{
+public:
+       ArmatureExporter(COLLADASW::StreamWriter *sw) : 
COLLADASW::LibraryControllers(sw) {}
+
+       void export_armatures(Scene *sce)
+       {
+               openLibrary();
+
+               forEachMeshObjectInScene(sce, *this);
+
+               closeLibrary();
+       }
+
+       void operator()(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;
+                       }
+               }
+
+               if (ob_arm)
+                       export_armature(ob, ob_arm);
+       }
+
+private:
+
+       UnitConverter converter;
+
+       // ob should be of type OB_MESH
+       // both args are required
+       void export_armature(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(ob_arm->id.name);
+               std::string controller_id = controller_name + 
SKIN_CONTROLLER_ID_SUFFIX;
+
+               openSkin(controller_id, controller_name, 
COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, ob->id.name));
+
+               add_bind_shape_mat(ob);
+
+               std::string joints_source_id = add_joints_source(&ob->defbase, 
controller_id);
+               std::string inv_bind_mat_source_id =
+                       add_inv_bind_mats_source((bArmature*)ob_arm->data, 
&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);
+
+               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();
+
+               int offset = 0;
+               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)
+       {
+               float ob_bind_mat[4][4];
+               double dae_mat[4][4];
+
+               // TODO: get matrix from ob
+               Mat4One(ob_bind_mat);
+
+               converter.mat4_to_dae(dae_mat, ob_bind_mat);
+
+               addBindShapeTransform(dae_mat);
+       }
+
+       std::string add_joints_source(ListBase *defbase, const std::string& 
controller_id)
+       {
+               std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
+
+               COLLADASW::NameSource source(mSW);
+               source.setId(source_id);
+               source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+               source.setAccessorCount(BLI_countlist(defbase));
+               source.setAccessorStride(1);
+               
+               COLLADASW::SourceBase::ParameterNameList &param = 
source.getParameterNameList();
+               param.push_back("JOINT");
+
+               source.prepareToAppendValues();
+
+               bDeformGroup *def;
+
+               for (def = (bDeformGroup*)defbase->first; def; def = def->next) 
{
+                       source.appendValues(def->name);
+               }
+
+               source.finish();
+
+               return source_id;
+       }
+
+       std::string add_inv_bind_mats_source(bArmature *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();
+
+               bDeformGroup *def;
+
+               /*
+               Bone *get_named_bone (struct bArmature *arm, const char *name);
+               bPoseChannel *get_pose_channel(const struct bPose *pose, const 
char *name);
+               */
+
+               float inv_bind_mat[4][4];
+               Mat4One(inv_bind_mat);
+
+               float dae_mat[4][4];
+               converter.mat4_to_dae(dae_mat, inv_bind_mat);
+
+               // TODO: write inverse bind matrices for each bone (name taken 
from defbase)
+               for (def = (bDeformGroup*)defbase->first; def; def = def->next) 
{
+                       source.appendValues(dae_mat);
+               }
+
+               source.finish();
+
+               return source_id;
+       }
+
+       std::string add_weights_source(Mesh *me, const std::string& 
controller_id)
+       {
+               std::string source_id = controller_id + 
WEIGHTS_SOURCE_ID_SUFFIX;
+
+               COLLADASW::FloatSourceF source(mSW);
+               source.setId(source_id);
+               source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+               source.setAccessorCount(me->totvert);
+               source.setAccessorStride(1);
+               
+               COLLADASW::SourceBase::ParameterNameList &param = 
source.getParameterNameList();
+               param.push_back("WEIGHT");
+
+               source.prepareToAppendValues();
+
+               // NOTE: COLLADA spec says weights should be normalized
+
+               for (int 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)
+       {
+               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);
+
+               std::vector<unsigned long> indices;
+
+               // 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++) {
+                               indices.push_back(dvert->dw[j].def_nr);
+                               indices.push_back(weight_index++);
+                       }
+               }
+               
+               weights.CloseVCountAndOpenVElement();
+               weights.appendValues(indices);
+
+               weights.finish();
+       }
+};
+
 class SceneExporter: COLLADASW::LibraryVisualScenes
 {
 public:
@@ -1301,7 +1562,10 @@
        // <library_animations>
        AnimationExporter ae(&sw);
        ae.exportAnimations(sce);
-       
+
+       // <library_controllers>
+       ArmatureExporter(&sw).export_armatures(sce);
+
        // <library_visual_scenes>
        SceneExporter se(&sw);
        se.exportScene(sce);

Added: branches/soc-2009-chingachgook/source/blender/collada/collada_internal.h
===================================================================
--- branches/soc-2009-chingachgook/source/blender/collada/collada_internal.h    
                        (rev 0)
+++ branches/soc-2009-chingachgook/source/blender/collada/collada_internal.h    
2009-07-28 12:08:54 UTC (rev 21970)
@@ -0,0 +1,58 @@
+#ifndef BLENDER_COLLADA_H
+#define BLENDER_COLLADA_H
+
+#include "COLLADAFWFileInfo.h"
+#include "Math/COLLADABUMathMatrix4.h"
+
+class UnitConverter
+{
+private:
+       COLLADAFW::FileInfo::Unit unit;
+       COLLADAFW::FileInfo::UpAxisType up_axis;
+
+public:
+
+       UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP) {}
+
+       void read_asset(const COLLADAFW::FileInfo* asset)
+       {
+       }
+
+       // TODO
+       // convert vector vec from COLLADA format to Blender
+       void convertVec3(float *vec)
+       {
+       }
+               
+       // TODO need also for angle conversion, time conversion...
+
+       void mat4_from_dae(float out[][4], const COLLADABU::Math::Matrix4& in)
+       {
+               // in DAE, matrices use columns vectors, (see comments in 
COLLADABUMathMatrix4.h)
+               // so here, to make a blender matrix, we swap columns and rows
+               for (int i = 0; i < 4; i++) {
+                       for (int j = 0; j < 4; j++) {
+                               out[i][j] = in[j][i];
+                       }
+               }
+       }
+
+       void mat4_to_dae(float out[][4], float in[][4])
+       {
+               Mat4CpyMat4(out, in);
+               Mat4Transp(out);
+       }
+
+       void mat4_to_dae(double out[][4], float in[][4])
+       {
+               float outf[4][4];
+
+               mat4_to_dae(outf, in);
+
+               for (int i = 0; i < 4; i++)
+                       for (int j = 0; j < 4; j++)
+                               out[i][j] = outf[i][j];
+       }
+};
+
+#endif


_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to