Blender V2.61 - r43446

ArmatureExporter.cpp

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