Blender  V2.59
ArmatureExporter.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: ArmatureExporter.cpp 38079 2011-07-04 08:59:28Z jesterking $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed,
00021  *                 Nathan Letwory
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include "COLLADASWBaseInputElement.h"
00032 #include "COLLADASWInstanceController.h"
00033 #include "COLLADASWPrimitves.h"
00034 #include "COLLADASWSource.h"
00035 
00036 #include "DNA_action_types.h"
00037 #include "DNA_meshdata_types.h"
00038 #include "DNA_modifier_types.h"
00039 
00040 #include "BKE_action.h"
00041 #include "BKE_armature.h"
00042 
00043 #include "BLI_listbase.h"
00044 
00045 #include "GeometryExporter.h"
00046 #include "ArmatureExporter.h"
00047 
00048 // XXX exporter writes wrong data for shared armatures.  A separate
00049 // controller should be written for each armature-mesh binding how do
00050 // we make controller ids then?
00051 ArmatureExporter::ArmatureExporter(COLLADASW::StreamWriter *sw) : COLLADASW::LibraryControllers(sw) {}
00052 
00053 // write bone nodes
00054 void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce)
00055 {
00056         // write bone nodes
00057         bArmature *arm = (bArmature*)ob_arm->data;
00058         for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) {
00059                 // start from root bones
00060                 if (!bone->parent)
00061                         add_bone_node(bone, ob_arm);
00062         }
00063 }
00064 
00065 bool ArmatureExporter::is_skinned_mesh(Object *ob)
00066 {
00067         return get_assigned_armature(ob) != NULL;
00068 }
00069 
00070 void ArmatureExporter::add_instance_controller(Object *ob)
00071 {
00072         Object *ob_arm = get_assigned_armature(ob);
00073         bArmature *arm = (bArmature*)ob_arm->data;
00074 
00075         const std::string& controller_id = get_controller_id(ob_arm, ob);
00076 
00077         COLLADASW::InstanceController ins(mSW);
00078         ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
00079 
00080         // write root bone URLs
00081         Bone *bone;
00082         for (bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) {
00083                 if (!bone->parent)
00084                         ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm)));
00085         }
00086 
00087         InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob);
00088                 
00089         ins.add();
00090 }
00091 
00092 void ArmatureExporter::export_controllers(Scene *sce, bool export_selected)
00093 {
00094         scene = sce;
00095 
00096         openLibrary();
00097 
00098         GeometryFunctor gf;
00099         gf.forEachMeshObjectInScene<ArmatureExporter>(sce, *this, export_selected);
00100 
00101         closeLibrary();
00102 }
00103 
00104 void ArmatureExporter::operator()(Object *ob)
00105 {
00106         Object *ob_arm = get_assigned_armature(ob);
00107 
00108         if (ob_arm /*&& !already_written(ob_arm)*/)
00109                 export_controller(ob, ob_arm);
00110 }
00111 #if 0
00112 
00113 bool ArmatureExporter::already_written(Object *ob_arm)
00114 {
00115         return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end();
00116 }
00117 
00118 void ArmatureExporter::wrote(Object *ob_arm)
00119 {
00120         written_armatures.push_back(ob_arm);
00121 }
00122 
00123 void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce)
00124 {
00125         objects.clear();
00126 
00127         Base *base= (Base*) sce->base.first;
00128         while(base) {
00129                 Object *ob = base->object;
00130                 
00131                 if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) {
00132                         objects.push_back(ob);
00133                 }
00134 
00135                 base= base->next;
00136         }
00137 }
00138 #endif
00139 
00140 Object *ArmatureExporter::get_assigned_armature(Object *ob)
00141 {
00142         Object *ob_arm = NULL;
00143 
00144         if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
00145                 ob_arm = ob->parent;
00146         }
00147         else {
00148                 ModifierData *mod = (ModifierData*)ob->modifiers.first;
00149                 while (mod) {
00150                         if (mod->type == eModifierType_Armature) {
00151                                 ob_arm = ((ArmatureModifierData*)mod)->object;
00152                         }
00153 
00154                         mod = mod->next;
00155                 }
00156         }
00157 
00158         return ob_arm;
00159 }
00160 
00161 std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm)
00162 {
00163         return get_joint_id(bone, ob_arm);
00164 }
00165 
00166 // parent_mat is armature-space
00167 void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm)
00168 {
00169         std::string node_id = get_joint_id(bone, ob_arm);
00170         std::string node_name = std::string(bone->name);
00171         std::string node_sid = get_joint_sid(bone, ob_arm);
00172 
00173         COLLADASW::Node node(mSW);
00174 
00175         node.setType(COLLADASW::Node::JOINT);
00176         node.setNodeId(node_id);
00177         node.setNodeName(node_name);
00178         node.setNodeSid(node_sid);
00179 
00180         node.start();
00181 
00182         add_bone_transform(ob_arm, bone, node);
00183 
00184         for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next) {
00185                 add_bone_node(child, ob_arm);
00186         }
00187 
00188         node.end();
00189 }
00190 
00191 void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node)
00192 {
00193         bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
00194 
00195         float mat[4][4];
00196 
00197         if (bone->parent) {
00198                 // get bone-space matrix from armature-space
00199                 bPoseChannel *parchan = get_pose_channel(ob_arm->pose, bone->parent->name);
00200 
00201                 float invpar[4][4];
00202                 invert_m4_m4(invpar, parchan->pose_mat);
00203                 mul_m4_m4m4(mat, pchan->pose_mat, invpar);
00204         }
00205         else {
00206                 // get world-space from armature-space
00207                 mul_m4_m4m4(mat, pchan->pose_mat, ob_arm->obmat);
00208         }
00209 
00210         TransformWriter::add_node_transform(node, mat, NULL);
00211 }
00212 
00213 std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob)
00214 {
00215         return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
00216 }
00217 
00218 // ob should be of type OB_MESH
00219 // both args are required
00220 void ArmatureExporter::export_controller(Object* ob, Object *ob_arm)
00221 {
00222         // joint names
00223         // joint inverse bind matrices
00224         // vertex weights
00225 
00226         // input:
00227         // joint names: ob -> vertex group names
00228         // vertex group weights: me->dvert -> groups -> index, weight
00229 
00230         /*
00231         me->dvert:
00232 
00233         typedef struct MDeformVert {
00234                 struct MDeformWeight *dw;
00235                 int totweight;
00236                 int flag;       // flag only in use for weightpaint now
00237         } MDeformVert;
00238 
00239         typedef struct MDeformWeight {
00240                 int                             def_nr;
00241                 float                   weight;
00242         } MDeformWeight;
00243         */
00244 
00245         Mesh *me = (Mesh*)ob->data;
00246         if (!me->dvert) return;
00247 
00248         std::string controller_name = id_name(ob_arm);
00249         std::string controller_id = get_controller_id(ob_arm, ob);
00250 
00251         openSkin(controller_id, controller_name,
00252                          COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob)));
00253 
00254         add_bind_shape_mat(ob);
00255 
00256         std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id);
00257         std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id);
00258         std::string weights_source_id = add_weights_source(me, controller_id);
00259 
00260         add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
00261         add_vertex_weights_element(weights_source_id, joints_source_id, me, ob_arm, &ob->defbase);
00262 
00263         closeSkin();
00264         closeController();
00265 }
00266 
00267 void ArmatureExporter::add_joints_element(ListBase *defbase,
00268                                                 const std::string& joints_source_id, const std::string& inv_bind_mat_source_id)
00269 {
00270         COLLADASW::JointsElement joints(mSW);
00271         COLLADASW::InputList &input = joints.getInputList();
00272 
00273         input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
00274                                                            COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id)));
00275         input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX,
00276                                                            COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id)));
00277         joints.add();
00278 }
00279 
00280 void ArmatureExporter::add_bind_shape_mat(Object *ob)
00281 {
00282         double bind_mat[4][4];
00283 
00284         converter.mat4_to_dae_double(bind_mat, ob->obmat);
00285 
00286         addBindShapeTransform(bind_mat);
00287 }
00288 
00289 std::string ArmatureExporter::add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
00290 {
00291         std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
00292 
00293         int totjoint = 0;
00294         bDeformGroup *def;
00295         for (def = (bDeformGroup*)defbase->first; def; def = def->next) {
00296                 if (is_bone_defgroup(ob_arm, def))
00297                         totjoint++;
00298         }
00299 
00300         COLLADASW::NameSource source(mSW);
00301         source.setId(source_id);
00302         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
00303         source.setAccessorCount(totjoint);
00304         source.setAccessorStride(1);
00305         
00306         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
00307         param.push_back("JOINT");
00308 
00309         source.prepareToAppendValues();
00310 
00311         for (def = (bDeformGroup*)defbase->first; def; def = def->next) {
00312                 Bone *bone = get_bone_from_defgroup(ob_arm, def);
00313                 if (bone)
00314                         source.appendValues(get_joint_sid(bone, ob_arm));
00315         }
00316 
00317         source.finish();
00318 
00319         return source_id;
00320 }
00321 
00322 std::string ArmatureExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
00323 {
00324         std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
00325 
00326         COLLADASW::FloatSourceF source(mSW);
00327         source.setId(source_id);
00328         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
00329         source.setAccessorCount(BLI_countlist(defbase));
00330         source.setAccessorStride(16);
00331         
00332         source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
00333         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
00334         param.push_back("TRANSFORM");
00335 
00336         source.prepareToAppendValues();
00337 
00338         bPose *pose = ob_arm->pose;
00339         bArmature *arm = (bArmature*)ob_arm->data;
00340 
00341         int flag = arm->flag;
00342 
00343         // put armature in rest position
00344         if (!(arm->flag & ARM_RESTPOS)) {
00345                 arm->flag |= ARM_RESTPOS;
00346                 where_is_pose(scene, ob_arm);
00347         }
00348 
00349         for (bDeformGroup *def = (bDeformGroup*)defbase->first; def; def = def->next) {
00350                 if (is_bone_defgroup(ob_arm, def)) {
00351 
00352                         bPoseChannel *pchan = get_pose_channel(pose, def->name);
00353 
00354                         float pose_mat[4][4];
00355                         float mat[4][4];
00356                         float world[4][4];
00357                         float inv_bind_mat[4][4];
00358 
00359                         // pose_mat is the same as pchan->pose_mat, but without the rotation
00360                         unit_m4(pose_mat);
00361                         translate_m4(pose_mat, pchan->pose_head[0], pchan->pose_head[1], pchan->pose_head[2]);
00362 
00363                         // make world-space matrix, pose_mat is armature-space
00364                         mul_m4_m4m4(world, pose_mat, ob_arm->obmat);
00365                         
00366                         invert_m4_m4(mat, world);
00367                         converter.mat4_to_dae(inv_bind_mat, mat);
00368 
00369                         source.appendValues(inv_bind_mat);
00370                 }
00371         }
00372 
00373         // back from rest positon
00374         if (!(flag & ARM_RESTPOS)) {
00375                 arm->flag = flag;
00376                 where_is_pose(scene, ob_arm);
00377         }
00378 
00379         source.finish();
00380 
00381         return source_id;
00382 }
00383 
00384 Bone *ArmatureExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup* def)
00385 {
00386         bPoseChannel *pchan = get_pose_channel(ob_arm->pose, def->name);
00387         return pchan ? pchan->bone : NULL;
00388 }
00389 
00390 bool ArmatureExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup* def)
00391 {
00392         return get_bone_from_defgroup(ob_arm, def) != NULL;
00393 }
00394 
00395 std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& controller_id)
00396 {
00397         std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
00398 
00399         int i;
00400         int totweight = 0;
00401 
00402         for (i = 0; i < me->totvert; i++) {
00403                 totweight += me->dvert[i].totweight;
00404         }
00405 
00406         COLLADASW::FloatSourceF source(mSW);
00407         source.setId(source_id);
00408         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
00409         source.setAccessorCount(totweight);
00410         source.setAccessorStride(1);
00411         
00412         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
00413         param.push_back("WEIGHT");
00414 
00415         source.prepareToAppendValues();
00416 
00417         // NOTE: COLLADA spec says weights should be normalized
00418 
00419         for (i = 0; i < me->totvert; i++) {
00420                 MDeformVert *vert = &me->dvert[i];
00421                 for (int j = 0; j < vert->totweight; j++) {
00422                         source.appendValues(vert->dw[j].weight);
00423                 }
00424         }
00425 
00426         source.finish();
00427 
00428         return source_id;
00429 }
00430 
00431 void ArmatureExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, Mesh *me,
00432                                                                 Object *ob_arm, ListBase *defbase)
00433 {
00434         COLLADASW::VertexWeightsElement weights(mSW);
00435         COLLADASW::InputList &input = weights.getInputList();
00436 
00437         int offset = 0;
00438         input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
00439                                                                          COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++));
00440         input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT,
00441                                                                          COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++));
00442 
00443         weights.setCount(me->totvert);
00444 
00445         // write number of deformers per vertex
00446         COLLADASW::PrimitivesBase::VCountList vcount;
00447         int i;
00448         for (i = 0; i < me->totvert; i++) {
00449                 vcount.push_back(me->dvert[i].totweight);
00450         }
00451 
00452         weights.prepareToAppendVCountValues();
00453         weights.appendVertexCount(vcount);
00454 
00455         // def group index -> joint index
00456         std::map<int, int> joint_index_by_def_index;
00457         bDeformGroup *def;
00458         int j;
00459         for (def = (bDeformGroup*)defbase->first, i = 0, j = 0; def; def = def->next, i++) {
00460                 if (is_bone_defgroup(ob_arm, def))
00461                         joint_index_by_def_index[i] = j++;
00462                 else
00463                         joint_index_by_def_index[i] = -1;
00464         }
00465 
00466         weights.CloseVCountAndOpenVElement();
00467 
00468         // write deformer index - weight index pairs
00469         int weight_index = 0;
00470         for (i = 0; i < me->totvert; i++) {
00471                 MDeformVert *dvert = &me->dvert[i];
00472                 for (int j = 0; j < dvert->totweight; j++) {
00473                         weights.appendValues(joint_index_by_def_index[dvert->dw[j].def_nr]);
00474                         weights.appendValues(weight_index++);
00475                 }
00476         }
00477 
00478         weights.finish();
00479 }