Blender V2.61 - r43446

SkinInfo.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, Nathan Letwory.
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00028 #include <algorithm>
00029 
00030 #if !defined(WIN32) || defined(FREE_WINDOWS)
00031 #include <stdint.h>
00032 #endif
00033 
00034 /* COLLADABU_ASSERT, may be able to remove later */
00035 #include "COLLADABUPlatform.h"
00036 
00037 #include "BKE_object.h"
00038 #include "DNA_armature_types.h"
00039 #include "DNA_modifier_types.h"
00040 #include "ED_mesh.h"
00041 #include "ED_object.h"
00042 #include "BKE_action.h"
00043 #include "BLI_listbase.h"
00044 #include "BLI_math.h"
00045 
00046 #include "SkinInfo.h"
00047 #include "collada_utils.h"
00048 
00049 // use name, or fall back to original id if name not present (name is optional)
00050 template<class T>
00051 static const char *bc_get_joint_name(T *node)
00052 {
00053     const std::string& id = node->getName();
00054     return id.size() ? id.c_str() : node->getOriginalId().c_str();
00055 }
00056 
00057 // This is used to store data passed in write_controller_data.
00058 // Arrays from COLLADAFW::SkinControllerData lose ownership, so do this class members
00059 // so that arrays don't get freed until we free them explicitly.
00060 SkinInfo::SkinInfo() {}
00061 
00062 SkinInfo::SkinInfo(const SkinInfo& skin) : weights(skin.weights),
00063                                  joint_data(skin.joint_data),
00064                                  unit_converter(skin.unit_converter),
00065                                  ob_arm(skin.ob_arm),
00066                                  controller_uid(skin.controller_uid),
00067                                  parent(skin.parent)
00068 {
00069     copy_m4_m4(bind_shape_matrix, (float (*)[4])skin.bind_shape_matrix);
00070 
00071     transfer_uint_array_data_const(skin.joints_per_vertex, joints_per_vertex);
00072     transfer_uint_array_data_const(skin.weight_indices, weight_indices);
00073     transfer_int_array_data_const(skin.joint_indices, joint_indices);
00074 }
00075 
00076 SkinInfo::SkinInfo(UnitConverter *conv) : unit_converter(conv), ob_arm(NULL), parent(NULL) {}
00077 
00078 // nobody owns the data after this, so it should be freed manually with releaseMemory
00079 template <class T>
00080 void SkinInfo::transfer_array_data(T& src, T& dest)
00081 {
00082     dest.setData(src.getData(), src.getCount());
00083     src.yieldOwnerShip();
00084     dest.yieldOwnerShip();
00085 }
00086 
00087 // when src is const we cannot src.yieldOwnerShip, this is used by copy constructor
00088 void SkinInfo::transfer_int_array_data_const(const COLLADAFW::IntValuesArray& src, COLLADAFW::IntValuesArray& dest)
00089 {
00090     dest.setData((int*)src.getData(), src.getCount());
00091     dest.yieldOwnerShip();
00092 }
00093 
00094 void SkinInfo::transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray& src, COLLADAFW::UIntValuesArray& dest)
00095 {
00096     dest.setData((unsigned int*)src.getData(), src.getCount());
00097     dest.yieldOwnerShip();
00098 }
00099 
00100 void SkinInfo::borrow_skin_controller_data(const COLLADAFW::SkinControllerData* skin)
00101 {
00102     transfer_array_data((COLLADAFW::UIntValuesArray&)skin->getJointsPerVertex(), joints_per_vertex);
00103     transfer_array_data((COLLADAFW::UIntValuesArray&)skin->getWeightIndices(), weight_indices);
00104     transfer_array_data((COLLADAFW::IntValuesArray&)skin->getJointIndices(), joint_indices);
00105     // transfer_array_data(skin->getWeights(), weights);
00106 
00107     // cannot transfer data for FloatOrDoubleArray, copy values manually
00108     const COLLADAFW::FloatOrDoubleArray& weight = skin->getWeights();
00109     for (unsigned int i = 0; i < weight.getValuesCount(); i++)
00110         weights.push_back(bc_get_float_value(weight, i));
00111 
00112     unit_converter->dae_matrix_to_mat4_(bind_shape_matrix, skin->getBindShapeMatrix());
00113 }
00114     
00115 void SkinInfo::free()
00116 {
00117     joints_per_vertex.releaseMemory();
00118     weight_indices.releaseMemory();
00119     joint_indices.releaseMemory();
00120     // weights.releaseMemory();
00121 }
00122 
00123 // using inverse bind matrices to construct armature
00124 // it is safe to invert them to get the original matrices
00125 // because if they are inverse matrices, they can be inverted
00126 void SkinInfo::add_joint(const COLLADABU::Math::Matrix4& matrix)
00127 {
00128     JointData jd;
00129     unit_converter->dae_matrix_to_mat4_(jd.inv_bind_mat, matrix);
00130     joint_data.push_back(jd);
00131 }
00132 
00133 void SkinInfo::set_controller(const COLLADAFW::SkinController* co)
00134 {
00135     controller_uid = co->getUniqueId();
00136 
00137     // fill in joint UIDs
00138     const COLLADAFW::UniqueIdArray& joint_uids = co->getJoints();
00139     for (unsigned int i = 0; i < joint_uids.getCount(); i++) {
00140         joint_data[i].joint_uid = joint_uids[i];
00141 
00142         // // store armature pointer
00143         // JointData& jd = joint_index_to_joint_info_map[i];
00144         // jd.ob_arm = ob_arm;
00145 
00146         // now we'll be able to get inv bind matrix from joint id
00147         // joint_id_to_joint_index_map[joint_ids[i]] = i;
00148     }
00149 }
00150 
00151 // called from write_controller
00152 Object *SkinInfo::create_armature(Scene *scene)
00153 {
00154     ob_arm = add_object(scene, OB_ARMATURE);
00155     return ob_arm;
00156 }
00157 
00158 Object* SkinInfo::set_armature(Object *ob_arm)
00159 {
00160     if (this->ob_arm)
00161         return this->ob_arm;
00162 
00163     this->ob_arm = ob_arm;
00164     return ob_arm;
00165 }
00166 
00167 bool SkinInfo::get_joint_inv_bind_matrix(float inv_bind_mat[][4], COLLADAFW::Node *node)
00168 {
00169     const COLLADAFW::UniqueId& uid = node->getUniqueId();
00170     std::vector<JointData>::iterator it;
00171     for (it = joint_data.begin(); it != joint_data.end(); it++) {
00172         if ((*it).joint_uid == uid) {
00173             copy_m4_m4(inv_bind_mat, (*it).inv_bind_mat);
00174             return true;
00175         }
00176     }
00177 
00178     return false;
00179 }
00180 
00181 Object *SkinInfo::get_armature()
00182 {
00183     return ob_arm;
00184 }
00185 
00186 const COLLADAFW::UniqueId& SkinInfo::get_controller_uid()
00187 {
00188     return controller_uid;
00189 }
00190 
00191 // check if this skin controller references a joint or any descendant of it
00192 // 
00193 // some nodes may not be referenced by SkinController,
00194 // in this case to determine if the node belongs to this armature,
00195 // we need to search down the tree
00196 bool SkinInfo::uses_joint_or_descendant(COLLADAFW::Node *node)
00197 {
00198     const COLLADAFW::UniqueId& uid = node->getUniqueId();
00199     std::vector<JointData>::iterator it;
00200     for (it = joint_data.begin(); it != joint_data.end(); it++) {
00201         if ((*it).joint_uid == uid)
00202             return true;
00203     }
00204 
00205     COLLADAFW::NodePointerArray& children = node->getChildNodes();
00206     for (unsigned int i = 0; i < children.getCount(); i++) {
00207         if (uses_joint_or_descendant(children[i]))
00208             return true;
00209     }
00210 
00211     return false;
00212 }
00213 
00214 void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid,
00215                    TransformReader *tm)
00216 {
00217     Main *bmain = CTX_data_main(C);
00218     Scene *scene = CTX_data_scene(C);
00219 
00220     ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature);
00221     ((ArmatureModifierData *)md)->object = ob_arm;
00222 
00223     copy_m4_m4(ob->obmat, bind_shape_matrix);
00224     object_apply_mat4(ob, ob->obmat, 0, 0);
00225 #if 1
00226     bc_set_parent(ob, ob_arm, C);
00227 #else
00228     Object workob;
00229     ob->parent = ob_arm;
00230     ob->partype = PAROBJECT;
00231 
00232     what_does_parent(scene, ob, &workob);
00233     invert_m4_m4(ob->parentinv, workob.obmat);
00234 
00235     ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
00236 
00237     DAG_scene_sort(bmain, scene);
00238     DAG_ids_flush_update(bmain, 0);
00239     WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
00240 #endif
00241 
00242     ((bArmature*)ob_arm->data)->deformflag = ARM_DEF_VGROUP;
00243 
00244     // create all vertex groups
00245     std::vector<JointData>::iterator it;
00246     int joint_index;
00247     for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) {
00248         const char *name = "Group";
00249 
00250         // skip joints that have invalid UID
00251         if ((*it).joint_uid == COLLADAFW::UniqueId::INVALID) continue;
00252         
00253         // name group by joint node name
00254         
00255         if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) {
00256             name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]);
00257         }
00258 
00259         ED_vgroup_add_name(ob, (char*)name);
00260     }
00261 
00262     // <vcount> - number of joints per vertex - joints_per_vertex
00263     // <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices
00264     // ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender?
00265 
00266     // for each vertex in weight indices
00267     //  for each bone index in vertex
00268     //      add vertex to group at group index
00269     //      treat group index -1 specially
00270 
00271     // get def group by index with BLI_findlink
00272 
00273     for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) {
00274 
00275         unsigned int limit = weight + joints_per_vertex[vertex];
00276         for ( ; weight < limit; weight++) {
00277             int joint = joint_indices[weight], joint_weight = weight_indices[weight];
00278 
00279             // -1 means "weight towards the bind shape", we just don't assign it to any group
00280             if (joint != -1) {
00281                 bDeformGroup *def = (bDeformGroup*)BLI_findlink(&ob->defbase, joint);
00282 
00283                 ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE);
00284             }
00285         }
00286     }
00287 }
00288 
00289 bPoseChannel *SkinInfo::get_pose_channel_from_node(COLLADAFW::Node *node)
00290 {
00291     return get_pose_channel(ob_arm->pose, bc_get_joint_name(node));
00292 }
00293 
00294 void SkinInfo::set_parent(Object *_parent)
00295 {
00296     parent = _parent;
00297 }
00298 
00299 Object* SkinInfo::get_parent()
00300 {
00301     return parent;
00302 }
00303 
00304 void SkinInfo::find_root_joints(const std::vector<COLLADAFW::Node*> &root_joints,
00305                       std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid,
00306                       std::vector<COLLADAFW::Node*>& result)
00307 {
00308     std::vector<COLLADAFW::Node*>::const_iterator it;
00309     // for each root_joint
00310     for (it = root_joints.begin(); it != root_joints.end(); it++) {
00311         COLLADAFW::Node *root = *it;
00312         std::vector<JointData>::iterator ji;
00313         //for each joint_data in this skin
00314         for (ji = joint_data.begin(); ji != joint_data.end(); ji++) {
00315             //get joint node from joint map
00316             COLLADAFW::Node *joint = joint_by_uid[(*ji).joint_uid];
00317             //find if joint node is in the tree belonging to the root_joint
00318             if (find_node_in_tree(joint, root)) {
00319                 if (std::find(result.begin(), result.end(), root) == result.end())
00320                     result.push_back(root);
00321             }
00322         }
00323     }
00324 }
00325 
00326 bool SkinInfo::find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_root)
00327 {
00328     if (node == tree_root)
00329         return true;
00330 
00331     COLLADAFW::NodePointerArray& children = tree_root->getChildNodes();
00332     for (unsigned int i = 0; i < children.getCount(); i++) {
00333         if (find_node_in_tree(node, children[i]))
00334             return true;
00335     }
00336 
00337     return false;
00338 }