[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [21997] branches/itasc: iTaSC: use a much simpler and more stable formula for joint limit.

Benoit Bolsee benoit.bolsee at online.be
Tue Jul 28 23:07:39 CEST 2009


Revision: 21997
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=21997
Author:   ben2610
Date:     2009-07-28 23:07:39 +0200 (Tue, 28 Jul 2009)

Log Message:
-----------
iTaSC: use a much simpler and more stable formula for joint limit. Simply use constant weight when the joint enters the limit: it preserves the linearity of the system on each side of the limit. Consistency of the weight is ensured by splitting the timestep so that the weight is changed exactly when the joint crosses the limit.

Modified Paths:
--------------
    branches/itasc/intern/itasc/Armature.cpp
    branches/itasc/source/blender/ikplugin/intern/itasc_plugin.cpp

Modified: branches/itasc/intern/itasc/Armature.cpp
===================================================================
--- branches/itasc/intern/itasc/Armature.cpp	2009-07-28 21:06:23 UTC (rev 21996)
+++ branches/itasc/intern/itasc/Armature.cpp	2009-07-28 21:07:39 UTC (rev 21997)
@@ -260,6 +260,21 @@
 	// update the parameters
 	LimitConstraintParam_struct* pLimit = (LimitConstraintParam_struct*)_param;
 	double y = _values->values->y;
+#if 1
+	if (y > pLimit->maxThreshold-0.001) {
+		_values->alpha = pLimit->maxWeight;
+		// change the limit to the threshold value so that there is no oscillation
+		_values->values->yd = pLimit->maxThreshold;
+	} else if (y < pLimit->minThreshold-0.001) {
+		_values->alpha = pLimit->maxWeight;
+		// change the limit to the threshold value so that there is no oscillation
+		_values->values->yd = pLimit->minThreshold;
+	} else {
+		_values->alpha = 0.0;
+	}
+#else
+	// more complex formula to avoid discontinuity of velocity
+	// not needed in animation, disable for now as it creates instability
 	double x;
 	if (y > pLimit->maxThreshold) {
 		if (y < pLimit->max) {
@@ -282,6 +297,7 @@
 	} else {
 		_values->alpha = 0.0;
 	}
+#endif
 	return true;
 }
 
@@ -526,6 +542,27 @@
 				double q = m_qKdl(cs->segment->second.q_nr);
 				double dq = qdot*timestep;
 				double newq = q+dq;
+#if 1
+				if (((q > pLimit->maxThreshold) ^ (newq > pLimit->maxThreshold)) ||
+					((q < pLimit->minThreshold) ^ (newq < pLimit->minThreshold))) {
+					if (q > pLimit->maxThreshold) {
+						newq = pLimit->maxThreshold-0.0011;
+					} else if (q < pLimit->minThreshold) {
+						newq = pLimit->minThreshold+0.0011;
+					} else if (newq > pLimit->maxThreshold && cs->values.alpha == 0.0) {
+						newq = pLimit->maxThreshold+0.0011;
+					} else if (cs->values.alpha == 0.0){
+						newq = pLimit->minThreshold-0.0011;
+					}
+					double newdq = fabs(newq-q);
+					dq = fabs(dq);
+					if (newdq < dq) {
+						timestep *= newdq/dq;
+					}
+				}
+#else
+				// more complex formula to avoid discontinuity of velocity
+				// not needed in animation, disable for now as it creates instability
 				double alpha = cs->values.alpha;
 				double newalpha;
 				if (q    > pLimit->maxThreshold || q    < pLimit->minThreshold ||
@@ -555,6 +592,7 @@
 						timestep *= newdq/dq;
 					}
 				}
+#endif
 			}
 		}
 	}

Modified: branches/itasc/source/blender/ikplugin/intern/itasc_plugin.cpp
===================================================================
--- branches/itasc/source/blender/ikplugin/intern/itasc_plugin.cpp	2009-07-28 21:06:23 UTC (rev 21996)
+++ branches/itasc/source/blender/ikplugin/intern/itasc_plugin.cpp	2009-07-28 21:07:39 UTC (rev 21997)
@@ -785,19 +785,19 @@
 		if ((flag & IK_XDOF) && (pchan->ikflag & BONE_IK_XLIMIT)) {
 			joint = bone->name;
 			joint += ":RX";
-			if (arm->addLimitConstraint(joint, pchan->limitmin[0], pchan->limitmax[0], 5.0, 50.0, 5.0) < 0)
+			if (arm->addLimitConstraint(joint, pchan->limitmin[0], pchan->limitmax[0], 0.5, 50.0, 5.0) < 0)
 				break;
 		}
 		if ((flag & IK_YDOF) && (pchan->ikflag & BONE_IK_YLIMIT)) {
 			joint = bone->name;
 			joint += ":RY";
-			if (arm->addLimitConstraint(joint, pchan->limitmin[1], pchan->limitmax[1], 5.0, 50.0, 5.0) < 0)
+			if (arm->addLimitConstraint(joint, pchan->limitmin[1], pchan->limitmax[1], 0.5, 50.0, 5.0) < 0)
 				break;
 		}
 		if ((flag & IK_ZDOF) && (pchan->ikflag & BONE_IK_ZLIMIT)) {
 			joint = bone->name;
 			joint += ":RZ";
-			if (arm->addLimitConstraint(joint, pchan->limitmin[2], pchan->limitmax[2], 5.0, 50.0, 5.0) < 0)
+			if (arm->addLimitConstraint(joint, pchan->limitmin[2], pchan->limitmax[2], 0.5, 50.0, 5.0) < 0)
 				break;
 		}
 		//  no error, so restore





More information about the Bf-blender-cvs mailing list