|
Blender
V2.59
|
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 }