[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [29189] branches/soc-2009-chingachgook/ source/blender/collada/DocumentImporter.cpp: COLLADA branch: fix bug #22388 .
Arystanbek Dyussenov
arystan.d at gmail.com
Thu Jun 3 19:23:36 CEST 2010
Revision: 29189
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=29189
Author: kazanbas
Date: 2010-06-03 19:23:36 +0200 (Thu, 03 Jun 2010)
Log Message:
-----------
COLLADA branch: fix bug #22388.
Do not create multiple armatures when multiple controllers share armature.
Modified Paths:
--------------
branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp
Modified: branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp
===================================================================
--- branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp 2010-06-03 16:26:04 UTC (rev 29188)
+++ branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp 2010-06-03 17:23:36 UTC (rev 29189)
@@ -419,8 +419,6 @@
std::vector<COLLADAFW::Node*> root_joints;
std::map<COLLADAFW::UniqueId, Object*> joint_parent_map;
- std::vector<Object*> armature_objects;
-
MeshImporterBase *mesh_importer;
AnimationImporterBase *anim_importer;
@@ -529,13 +527,11 @@
joint_data.push_back(jd);
}
- // called from write_controller
- Object *create_armature(const COLLADAFW::SkinController* co, Scene *scene)
+ void set_controller(const COLLADAFW::SkinController* co)
{
- ob_arm = add_object(scene, OB_ARMATURE);
-
controller_uid = co->getUniqueId();
+ // fill in joint UIDs
const COLLADAFW::UniqueIdArray& joint_uids = co->getJoints();
for (unsigned int i = 0; i < joint_uids.getCount(); i++) {
joint_data[i].joint_uid = joint_uids[i];
@@ -547,10 +543,24 @@
// now we'll be able to get inv bind matrix from joint id
// joint_id_to_joint_index_map[joint_ids[i]] = i;
}
+ }
+ // called from write_controller
+ Object *create_armature(Scene *scene)
+ {
+ ob_arm = add_object(scene, OB_ARMATURE);
return ob_arm;
}
+ Object* set_armature(Object *ob_arm)
+ {
+ if (this->ob_arm)
+ return this->ob_arm;
+
+ this->ob_arm = ob_arm;
+ return ob_arm;
+ }
+
bool get_joint_inv_bind_matrix(float inv_bind_mat[][4], COLLADAFW::Node *node)
{
const COLLADAFW::UniqueId& uid = node->getUniqueId();
@@ -575,10 +585,12 @@
return controller_uid;
}
+ // check if this skin controller references a joint or any descendant of it
+ //
// some nodes may not be referenced by SkinController,
// in this case to determine if the node belongs to this armature,
// we need to search down the tree
- bool uses_joint(COLLADAFW::Node *node)
+ bool uses_joint_or_descendant(COLLADAFW::Node *node)
{
const COLLADAFW::UniqueId& uid = node->getUniqueId();
std::vector<JointData>::iterator it;
@@ -589,7 +601,7 @@
COLLADAFW::NodePointerArray& children = node->getChildNodes();
for (unsigned int i = 0; i < children.getCount(); i++) {
- if (this->uses_joint(children[i]))
+ if (uses_joint_or_descendant(children[i]))
return true;
}
@@ -681,6 +693,38 @@
return parent;
}
+ void find_root_joints(const std::vector<COLLADAFW::Node*> &root_joints,
+ std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid,
+ std::vector<COLLADAFW::Node*>& result)
+ {
+ std::vector<COLLADAFW::Node*>::const_iterator it;
+ for (it = root_joints.begin(); it != root_joints.end(); it++) {
+ COLLADAFW::Node *root = *it;
+ std::vector<JointData>::iterator ji;
+ for (ji = joint_data.begin(); ji != joint_data.end(); ji++) {
+ COLLADAFW::Node *joint = joint_by_uid[(*ji).joint_uid];
+ if (find_node_in_tree(joint, root)) {
+ if (std::find(result.begin(), result.end(), root) == result.end())
+ result.push_back(root);
+ }
+ }
+ }
+ }
+
+ bool find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_root)
+ {
+ if (node == tree_root)
+ return true;
+
+ COLLADAFW::NodePointerArray& children = tree_root->getChildNodes();
+ for (unsigned int i = 0; i < children.getCount(); i++) {
+ if (find_node_in_tree(node, children[i]))
+ return true;
+ }
+
+ return false;
+ }
+
};
std::map<COLLADAFW::UniqueId, SkinInfo> skin_by_data_uid; // data UID = skin controller data UID
@@ -864,7 +908,7 @@
for (sit = skin_by_data_uid.begin(); sit != skin_by_data_uid.end(); sit++) {
SkinInfo& skin = sit->second;
- if (skin.uses_joint(joint)) {
+ if (skin.uses_joint_or_descendant(joint)) {
bPoseChannel *pchan = skin.get_pose_channel_from_node(joint);
if (pchan) {
@@ -932,8 +976,71 @@
// - exit edit mode
// - set a sphere shape to leaf bones
- Object *ob_arm = skin.get_armature();
+ Object *ob_arm = NULL;
+ /*
+ * find if there's another skin sharing at least one bone with this skin
+ * if so, use that skin's armature
+ */
+
+ /*
+ Pseudocode:
+
+ find_node_in_tree(node, root_joint)
+
+ skin::find_root_joints(root_joints):
+ std::vector root_joints;
+ for each root in root_joints:
+ for each joint in joints:
+ if find_node_in_tree(joint, root):
+ if (std::find(root_joints.begin(), root_joints.end(), root) == root_joints.end())
+ root_joints.push_back(root);
+
+ for (each skin B with armature) {
+ find all root joints for skin B
+
+ for each joint X in skin A:
+ for each root joint R in skin B:
+ if (find_node_in_tree(X, R)) {
+ shared = 1;
+ goto endloop;
+ }
+ }
+
+ endloop:
+ */
+
+ SkinInfo *a = &skin;
+ Object *shared = NULL;
+ std::vector<COLLADAFW::Node*> skin_root_joints;
+
+ std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it;
+ for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
+ SkinInfo *b = &it->second;
+ if (b == a || b->get_armature() == NULL)
+ continue;
+
+ skin_root_joints.clear();
+
+ b->find_root_joints(root_joints, joint_by_uid, skin_root_joints);
+
+ std::vector<COLLADAFW::Node*>::iterator ri;
+ for (ri = skin_root_joints.begin(); ri != skin_root_joints.end(); ri++) {
+ if (a->uses_joint_or_descendant(*ri)) {
+ shared = b->get_armature();
+ break;
+ }
+ }
+
+ if (shared != NULL)
+ break;
+ }
+
+ if (shared)
+ ob_arm = skin.set_armature(shared);
+ else
+ ob_arm = skin.create_armature(scene);
+
// enter armature edit mode
ED_armature_to_edit(ob_arm);
@@ -944,15 +1051,23 @@
// min_angle = 360.0f; // minimum angle between bone head-tail and a row of bone matrix
// create bones
+ /*
+ TODO:
+ check if bones have already been created for a given joint
+ */
- std::vector<COLLADAFW::Node*>::iterator it;
- for (it = root_joints.begin(); it != root_joints.end(); it++) {
+ std::vector<COLLADAFW::Node*>::iterator ri;
+ for (ri = root_joints.begin(); ri != root_joints.end(); ri++) {
+ // for shared armature check if bone tree is already created
+ if (shared && std::find(skin_root_joints.begin(), skin_root_joints.end(), *ri) != skin_root_joints.end())
+ continue;
+
// since root_joints may contain joints for multiple controllers, we need to filter
- if (skin.uses_joint(*it)) {
- create_bone(skin, *it, NULL, (*it)->getChildNodes().getCount(), NULL, (bArmature*)ob_arm->data);
+ if (skin.uses_joint_or_descendant(*ri)) {
+ create_bone(skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature*)ob_arm->data);
- if (joint_parent_map.find((*it)->getUniqueId()) != joint_parent_map.end() && !skin.get_parent())
- skin.set_parent(joint_parent_map[(*it)->getUniqueId()]);
+ if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && !skin.get_parent())
+ skin.set_parent(joint_parent_map[(*ri)->getUniqueId()]);
}
}
@@ -1094,10 +1209,8 @@
const COLLADAFW::UniqueId& skin_id = controller->getUniqueId();
if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_SKIN) {
-
COLLADAFW::SkinController *co = (COLLADAFW::SkinController*)controller;
-
- // to find geom id by controller id
+ // to be able to find geom id by controller id
geom_uid_by_controller_uid[skin_id] = co->getSource();
const COLLADAFW::UniqueId& data_uid = co->getSkinControllerData();
@@ -1106,9 +1219,7 @@
return true;
}
- Object *ob_arm = skin_by_data_uid[data_uid].create_armature(co, scene);
-
- armature_objects.push_back(ob_arm);
+ skin_by_data_uid[data_uid].set_controller(co);
}
// morph controller
else {
@@ -1133,7 +1244,7 @@
for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
SkinInfo& skin = it->second;
- if (skin.uses_joint(node))
+ if (skin.uses_joint_or_descendant(node))
return skin.get_armature();
}
@@ -1145,19 +1256,6 @@
BLI_snprintf(joint_path, count, "pose.bones[\"%s\"]", get_joint_name(node));
}
-#if 0
- void fix_animation()
- {
- /* Change Euler rotation to Quaternion for bone animation */
- std::vector<Object*>::iterator it;
- for (it = armature_objects.begin(); it != armature_objects.end(); it++) {
- Object *ob = *it;
- if (!ob || !ob->adt || !ob->adt->action) continue;
- anim_importer->change_eul_to_quat(ob, ob->adt->action);
- }
- }
-#endif
-
// gives a world-space mat
bool get_joint_bind_mat(float m[][4], COLLADAFW::Node *joint)
{
More information about the Bf-blender-cvs
mailing list