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