[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [53411] trunk/blender/source/blender: fix bug #33275: iTaSC ignores location of disconnected bones when they are changed in pose mode .

Benoit Bolsee benoit.bolsee at online.be
Sat Dec 29 20:43:12 CET 2012


Revision: 53411
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=53411
Author:   ben2610
Date:     2012-12-29 19:43:08 +0000 (Sat, 29 Dec 2012)
Log Message:
-----------
fix bug #33275: iTaSC ignores location of disconnected bones when they are changed in pose mode.

Disconnected bones can be translated in pose mode but this translation
cannot be applied to the iTaSC representation of the armature because
there is no joint associated with it. As a result, moving disconnected
bones had no effect. The bug fix is in two parts:
1) manual or rna change in the armature pose will cause automatic
   rebuilding of the iTaSC scene
2) the iTaSC scene is now built from the current pose instead of
   armature rest pose

Modified Paths:
--------------
    trunk/blender/source/blender/editors/transform/transform_generics.c
    trunk/blender/source/blender/ikplugin/intern/itasc_plugin.cpp
    trunk/blender/source/blender/makesrna/intern/rna_pose.c

Modified: trunk/blender/source/blender/editors/transform/transform_generics.c
===================================================================
--- trunk/blender/source/blender/editors/transform/transform_generics.c	2012-12-29 18:25:03 UTC (rev 53410)
+++ trunk/blender/source/blender/editors/transform/transform_generics.c	2012-12-29 19:43:08 UTC (rev 53411)
@@ -61,6 +61,8 @@
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+#include "BIK_api.h"
+
 #include "BKE_animsys.h"
 #include "BKE_action.h"
 #include "BKE_armature.h"
@@ -847,6 +849,8 @@
 		/* old optimize trick... this enforces to bypass the depgraph */
 		if (!(arm->flag & ARM_DELAYDEFORM)) {
 			DAG_id_tag_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
+			/* transformation of pose may affect IK tree, make sure it is rebuilt */
+			BIK_clear_data(ob->pose);
 		}
 		else
 			BKE_pose_where_is(t->scene, ob);

Modified: trunk/blender/source/blender/ikplugin/intern/itasc_plugin.cpp
===================================================================
--- trunk/blender/source/blender/ikplugin/intern/itasc_plugin.cpp	2012-12-29 18:25:03 UTC (rev 53410)
+++ trunk/blender/source/blender/ikplugin/intern/itasc_plugin.cpp	2012-12-29 19:43:08 UTC (rev 53411)
@@ -864,7 +864,7 @@
 }
 
 // build array of joint corresponding to IK chain
-static int convert_channels(IK_Scene *ikscene, PoseTree *tree)
+static int convert_channels(IK_Scene *ikscene, PoseTree *tree, float ctime)
 {
 	IK_Channel *ikchan;
 	bPoseChannel *pchan;
@@ -877,6 +877,14 @@
 		ikchan->parent = (a > 0) ? tree->parent[a] : -1;
 		ikchan->owner = ikscene->blArmature;
 
+		// the constraint and channels must be applied before we build the iTaSC scene,
+		// this is because some of the pose data (e.g. pose head) don't have corresponding 
+		// joint angles and can't be applied to the iTaSC armature dynamically
+		if (!(pchan->flag & POSE_DONE))
+			BKE_pose_where_is_bone(ikscene->blscene, ikscene->blArmature, pchan, ctime, 1);
+		// tell blender that this channel was controlled by IK, it's cleared on each BKE_pose_where_is()
+		pchan->flag |= (POSE_DONE | POSE_CHAIN);
+
 		/* set DoF flag */
 		flag = 0;
 		if (!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP) &&
@@ -1049,7 +1057,7 @@
 	}
 }
 
-static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
+static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan, float ctime)
 {
 	PoseTree *tree = (PoseTree *)pchan->iktree.first;
 	PoseTarget *target;
@@ -1068,6 +1076,7 @@
 	float length;
 	bool ret = true, ingame;
 	double *rot;
+	float start[3];
 
 	if (tree->totchannel == 0)
 		return NULL;
@@ -1126,7 +1135,7 @@
 	std::vector<double> weights;
 	double weight[3];
 	// build the array of joints corresponding to the IK chain
-	convert_channels(ikscene, tree);
+	convert_channels(ikscene, tree, ctime);
 	if (ingame) {
 		// in the GE, set the initial joint angle to match the current pose
 		// this will update the jointArray in ikscene
@@ -1137,17 +1146,37 @@
 		BKE_pose_rest(ikscene);
 	}
 	rot = ikscene->jointArray(0);
+
 	for (a = 0, ikchan = ikscene->channels; a < tree->totchannel; ++a, ++ikchan) {
 		pchan = ikchan->pchan;
 		bone = pchan->bone;
 
 		KDL::Frame tip(iTaSC::F_identity);
+		// compute the position and rotation of the head from previous segment
 		Vector3 *fl = bone->bone_mat;
 		KDL::Rotation brot(
 		    fl[0][0], fl[1][0], fl[2][0],
 		    fl[0][1], fl[1][1], fl[2][1],
 		    fl[0][2], fl[1][2], fl[2][2]);
-		KDL::Vector bpos(bone->head[0], bone->head[1], bone->head[2]);
+		// if the bone is disconnected, the head is movable in pose mode
+		// take that into account by using pose matrix instead of bone
+		// Note that pose is expressed in armature space, convert to previous bone space
+		{
+			float R_parmat[3][3];
+			float iR_parmat[3][3];
+			if (pchan->parent)
+				copy_m3_m4(R_parmat, pchan->parent->pose_mat);
+			else
+				unit_m3(R_parmat);
+			if (pchan->parent)
+				sub_v3_v3v3(start, pchan->pose_head, pchan->parent->pose_tail);
+			else
+				start[0] = start[1] = start[2] = 0.0f;
+			invert_m3_m3(iR_parmat, R_parmat);
+			normalize_m3(iR_parmat);
+			mul_m3_v3(iR_parmat, start);
+		}
+		KDL::Vector bpos(start[0], start[1], start[2]);
 		bpos *= ikscene->blScale;
 		KDL::Frame head(brot, bpos);
 
@@ -1155,7 +1184,7 @@
 		length = bone->length * ikscene->blScale;
 		parent = (a > 0) ? ikscene->channels[tree->parent[a]].tail : root;
 		// first the fixed segment to the bone head
-		if (head.p.Norm() > KDL::epsilon || head.M.GetRot().Norm() > KDL::epsilon) {
+		if (!(ikchan->pchan->bone->flag & BONE_CONNECTED) || head.M.GetRot().Norm() > KDL::epsilon) {
 			joint = bone->name;
 			joint += ":H";
 			ret = arm->addSegment(joint, parent, KDL::Joint::None, 0.0, head);
@@ -1497,7 +1526,7 @@
 	return ikscene;
 }
 
-static void create_scene(Scene *scene, Object *ob)
+static void create_scene(Scene *scene, Object *ob, float ctime)
 {
 	bPoseChannel *pchan;
 
@@ -1508,7 +1537,7 @@
 		if (tree) {
 			IK_Data *ikdata = get_ikdata(ob->pose);
 			// convert tree in iTaSC::Scene
-			IK_Scene *ikscene = convert_tree(scene, ob, pchan);
+			IK_Scene *ikscene = convert_tree(scene, ob, pchan, ctime);
 			if (ikscene) {
 				ikscene->next = ikdata->first;
 				ikdata->first = ikscene;
@@ -1732,15 +1761,21 @@
 			count += initialize_scene(ob, pchan);
 	}
 	// if at least one tree, create the scenes from the PoseTree stored in the channels
-	if (count)
-		create_scene(scene, ob);
-	itasc_update_param(ob->pose);
+	// postpone until execute_tree: this way the pose constraint are included
+	//if (count)
+	//	create_scene(scene, ob, ctime);
+	//itasc_update_param(ob->pose);
 	// make sure we don't rebuilt until the user changes something important
 	ob->pose->flag &= ~POSE_WAS_REBUILT;
 }
 
 void itasc_execute_tree(struct Scene *scene, struct Object *ob,  struct bPoseChannel *pchan, float ctime)
 {
+	if (!ob->pose->ikdata) {
+		// IK tree not yet created, no it now
+		create_scene(scene, ob, ctime);
+		itasc_update_param(ob->pose);
+	}
 	if (ob->pose->ikdata) {
 		IK_Data *ikdata = (IK_Data *)ob->pose->ikdata;
 		bItasc *ikparam = (bItasc *) ob->pose->ikparam;

Modified: trunk/blender/source/blender/makesrna/intern/rna_pose.c
===================================================================
--- trunk/blender/source/blender/makesrna/intern/rna_pose.c	2012-12-29 18:25:03 UTC (rev 53410)
+++ trunk/blender/source/blender/makesrna/intern/rna_pose.c	2012-12-29 19:43:08 UTC (rev 53411)
@@ -786,14 +786,14 @@
 	RNA_def_property_editable_array_func(prop, "rna_PoseChannel_location_editable");
 	RNA_def_property_ui_text(prop, "Location", "");
 	RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
-	RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+	RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_IK_update");
 
 	prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
 	RNA_def_property_float_sdna(prop, NULL, "size");
 	RNA_def_property_editable_array_func(prop, "rna_PoseChannel_scale_editable");
 	RNA_def_property_float_array_default(prop, default_scale);
 	RNA_def_property_ui_text(prop, "Scale", "");
-	RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+	RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_IK_update");
 
 	prop = RNA_def_property(srna, "rotation_quaternion", PROP_FLOAT, PROP_QUATERNION);
 	RNA_def_property_float_sdna(prop, NULL, "quat");




More information about the Bf-blender-cvs mailing list