[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [24174] trunk/blender: New Track To Constraint: "Damped"

Joshua Leung aligorith at gmail.com
Fri Oct 30 07:33:41 CET 2009


Revision: 24174
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=24174
Author:   aligorith
Date:     2009-10-30 07:33:40 +0100 (Fri, 30 Oct 2009)

Log Message:
-----------
New Track To Constraint: "Damped"

This is effectively a C-port of Nathan Vegdahl's "No Twist" TrackTo PyConstraint, and has been added as a separate type of constraint to be consistent with the existing constraints (Locked Track, and Track To). 

In general, this works considerably better than the existing "Track To" constraint, since it works by determining the smallest rotation necessary to get the current orientation of the owner to an orientation which would be tracking the target. It is also a much more straightforward approach than the weird old method the old Track To uses.

I've made a few tweaks to the code to deal with the (hopefully rare) cases where the target and the constrained are coincident. These don't appear to cause too much trouble in general.

TODO:
- Probably the naming of the constraints will change, to better convey their purposes. Naming suggestions welcome.

Modified Paths:
--------------
    trunk/blender/release/scripts/ui/buttons_object_constraint.py
    trunk/blender/source/blender/blenkernel/intern/constraint.c
    trunk/blender/source/blender/blenlib/intern/arithb.c
    trunk/blender/source/blender/makesdna/DNA_constraint_types.h
    trunk/blender/source/blender/makesrna/RNA_access.h
    trunk/blender/source/blender/makesrna/intern/rna_constraint.c

Modified: trunk/blender/release/scripts/ui/buttons_object_constraint.py
===================================================================
--- trunk/blender/release/scripts/ui/buttons_object_constraint.py	2009-10-30 02:09:52 UTC (rev 24173)
+++ trunk/blender/release/scripts/ui/buttons_object_constraint.py	2009-10-30 06:33:40 UTC (rev 24174)
@@ -568,7 +568,14 @@
 			row.itemR(con, "axis_x")
 			row.itemR(con, "axis_y")
 			row.itemR(con, "axis_z")
+			
+	def DAMPED_TRACK(self, context, layout, con):
+		self.target_template(layout, con)
 		
+		row = layout.row()
+		row.itemL(text="To:")
+		row.itemR(con, "track", expand=True)
+		
 class OBJECT_PT_constraints(ConstraintButtonsPanel):
 	__label__ = "Constraints"
 	__context__ = "constraint"

Modified: trunk/blender/source/blender/blenkernel/intern/constraint.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/constraint.c	2009-10-30 02:09:52 UTC (rev 24173)
+++ trunk/blender/source/blender/blenkernel/intern/constraint.c	2009-10-30 06:33:40 UTC (rev 24174)
@@ -2179,7 +2179,7 @@
 					Projf(vec2, vec, cob->matrix[1]);
 					VecSubf(totmat[2], vec, vec2);
 					Normalize(totmat[2]);
-
+					
 					/* the y axis is fixed */
 					totmat[1][0] = cob->matrix[1][0];
 					totmat[1][1] = cob->matrix[1][1];
@@ -2311,20 +2311,20 @@
 					break;
 				default:
 				{
-						totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
-						totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
-						totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+					totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+					totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+					totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
 				}
 					break;
 			}
 		}
 			break;
 		default:
-			{
-				totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
-				totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
-				totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
-			}
+		{
+			totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+			totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+			totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+		}
 			break;
 		}
 		/* Block to keep matrix heading */
@@ -3327,8 +3327,125 @@
 	shrinkwrap_evaluate /* evaluate */
 };
 
+/* --------- Damped Track ---------- */
 
+static void damptrack_new_data (void *cdata)
+{
+	bDampTrackConstraint *data= (bDampTrackConstraint *)cdata;
+	
+	data->trackflag = TRACK_Y;
+}	
 
+static int damptrack_get_tars (bConstraint *con, ListBase *list)
+{
+	if (con && list) {
+		bDampTrackConstraint *data= con->data;
+		bConstraintTarget *ct;
+		
+		/* the following macro is used for all standard single-target constraints */
+		SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
+		
+		return 1;
+	}
+	
+	return 0;
+}
+
+static void damptrack_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+	if (con && list) {
+		bDampTrackConstraint *data= con->data;
+		bConstraintTarget *ct= list->first;
+		
+		/* the following macro is used for all standard single-target constraints */
+		SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
+	}
+}
+
+/* array of direction vectors for the tracking flags */
+static const float track_dir_vecs[6][3] = {
+	{+1,0,0}, {0,+1,0}, {0,0,+1},		/* TRACK_X,  TRACK_Y,  TRACK_Z */
+	{-1,0,0}, {0,-1,0}, {0,0,-1}		/* TRACK_NX, TRACK_NY, TRACK_NZ */
+};
+
+static void damptrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+	bDampTrackConstraint *data= con->data;
+	bConstraintTarget *ct= targets->first;
+	
+	if (VALID_CONS_TARGET(ct)) {
+		float obvec[3], tarvec[3], obloc[3];
+		float raxis[3], rangle;
+		float rmat[3][3], tmat[4][4];
+		
+		/* find the (unit) direction that the axis we're interested in currently points 
+		 *	- Mat4Mul3Vecfl() only takes the 3x3 (rotation+scaling) components of the 4x4 matrix 
+		 *	- the normalisation step at the end should take care of any unwanted scaling
+		 *	  left over in the 3x3 matrix we used
+		 */
+		VECCOPY(obvec, track_dir_vecs[data->trackflag]);
+		Mat4Mul3Vecfl(cob->matrix, obvec);
+		
+		if (Normalize(obvec) == 0.0f) {
+			/* exceptional case - just use the track vector as appropriate */
+			VECCOPY(obvec, track_dir_vecs[data->trackflag]);
+		}
+		
+		/* find the (unit) direction vector going from the owner to the target */
+		VECCOPY(obloc, cob->matrix[3]);
+		VecSubf(tarvec, ct->matrix[3], obloc);
+		
+		if (Normalize(tarvec) == 0.0f) {
+			/* the target is sitting on the owner, so just make them use the same direction vectors */
+			// FIXME: or would it be better to use the pure direction vector?
+			VECCOPY(tarvec, obvec);
+			//VECCOPY(tarvec, track_dir_vecs[data->trackflag]);
+		}
+		
+		/* determine the axis-angle rotation, which represents the smallest possible rotation
+		 * between the two rotation vectors (i.e. the 'damping' referred to in the name)
+		 *	- we take this to be the rotation around the normal axis/vector to the plane defined
+		 *	  by the current and destination vectors, which will 'map' the current axis to the 
+		 *	  destination vector
+		 *	- the min/max wrappers around (obvec . tarvec) result (stored temporarily in rangle)
+		 *	  are used to ensure that the smallest angle is chosen
+		 */
+		Crossf(raxis, obvec, tarvec);
+		
+		rangle= Inpf(obvec, tarvec);
+		rangle= acos( MAX2(-1.0f, MIN2(1.0f, rangle)) );
+		
+		/* construct rotation matrix from the axis-angle rotation found above 
+		 *	- this call takes care to make sure that the axis provided is a unit vector first
+		 */
+		AxisAngleToMat3(raxis, rangle, rmat);
+		
+		/* rotate the owner in the way defined by this rotation matrix, then reapply the location since
+		 * we may have destroyed that in the process of multiplying the matrix
+		 */
+		Mat4One(tmat);
+		Mat4MulMat34(tmat, rmat, cob->matrix); // m1, m3, m2
+		
+		Mat4CpyMat4(cob->matrix, tmat);
+		VECCOPY(cob->matrix[3], obloc);
+	}
+}
+
+static bConstraintTypeInfo CTI_DAMPTRACK = {
+	CONSTRAINT_TYPE_DAMPTRACK, /* type */
+	sizeof(bDampTrackConstraint), /* size */
+	"Damped Track", /* name */
+	"bDampTrackConstraint", /* struct name */
+	NULL, /* free data */
+	NULL, /* relink data */
+	NULL, /* copy data */
+	damptrack_new_data, /* new data */
+	damptrack_get_tars, /* get constraint targets */
+	damptrack_flush_tars, /* flush constraint targets */
+	default_get_tarmat, /* get target matrix */
+	damptrack_evaluate /* evaluate */
+};
+
 /* ************************* Constraints Type-Info *************************** */
 /* All of the constraints api functions use bConstraintTypeInfo structs to carry out
  * and operations that involve constraint specific code.
@@ -3361,6 +3478,7 @@
 	constraintsTypeInfo[18]= &CTI_CLAMPTO; 			/* ClampTo Constraint */	
 	constraintsTypeInfo[19]= &CTI_TRANSFORM;		/* Transformation Constraint */
 	constraintsTypeInfo[20]= &CTI_SHRINKWRAP;		/* Shrinkwrap Constraint */
+	constraintsTypeInfo[21]= &CTI_DAMPTRACK;		/* Damped TrackTo Constraint */
 }
 
 /* This function should be used for getting the appropriate type-info when only

Modified: trunk/blender/source/blender/blenlib/intern/arithb.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/arithb.c	2009-10-30 02:09:52 UTC (rev 24173)
+++ trunk/blender/source/blender/blenlib/intern/arithb.c	2009-10-30 06:33:40 UTC (rev 24174)
@@ -131,6 +131,7 @@
 	return d;
 }
 
+/* Crossf stores the cross product c = a x b */
 void Crossf(float *c, float *a, float *b)
 {
 	c[0] = a[1] * b[2] - a[2] * b[1];

Modified: trunk/blender/source/blender/makesdna/DNA_constraint_types.h
===================================================================
--- trunk/blender/source/blender/makesdna/DNA_constraint_types.h	2009-10-30 02:09:52 UTC (rev 24173)
+++ trunk/blender/source/blender/makesdna/DNA_constraint_types.h	2009-10-30 06:33:40 UTC (rev 24174)
@@ -219,6 +219,14 @@
 	char		subtarget[32];
 } bLockTrackConstraint;
 
+/* Damped Tracking constraint */
+typedef struct bDampTrackConstraint {
+	Object		*tar;
+	int			trackflag;
+	int			pad;
+	char		subtarget[32];
+} bDampTrackConstraint;
+
 /* Follow Path constraints */
 typedef struct bFollowPathConstraint {
 	Object		*tar;	/* Must be path object */
@@ -331,6 +339,7 @@
 	int 		pad;
 } bDistLimitConstraint;
 
+/* ShrinkWrap Constraint */
 typedef struct bShrinkwrapConstraint {
 	Object		*target;
 	float		dist;			/* distance to kept from target */
@@ -368,10 +377,10 @@
 	CONSTRAINT_TYPE_CLAMPTO, 			/* clampto constraint */	
 	CONSTRAINT_TYPE_TRANSFORM,			/* transformation (loc/rot/size -> loc/rot/size) constraint */	
 	CONSTRAINT_TYPE_SHRINKWRAP,			/* shrinkwrap (loc/rot) constraint */
+	CONSTRAINT_TYPE_DAMPTRACK,			/* New Tracking constraint that minimises twisting */
 	
-	
 	/* NOTE: everytime a new constraint is added, update this */
-	NUM_CONSTRAINT_TYPES= CONSTRAINT_TYPE_SHRINKWRAP
+	NUM_CONSTRAINT_TYPES= CONSTRAINT_TYPE_DAMPTRACK
 } B_CONSTRAINT_TYPES; 
 
 /* bConstraint->flag */

Modified: trunk/blender/source/blender/makesrna/RNA_access.h
===================================================================
--- trunk/blender/source/blender/makesrna/RNA_access.h	2009-10-30 02:09:52 UTC (rev 24173)
+++ trunk/blender/source/blender/makesrna/RNA_access.h	2009-10-30 06:33:40 UTC (rev 24174)
@@ -172,6 +172,7 @@
 extern StructRNA RNA_CurveMapping;
 extern StructRNA RNA_CurveModifier;
 extern StructRNA RNA_CurvePoint;
+extern StructRNA RNA_DampedTrackConstraint;
 extern StructRNA RNA_DecimateModifier;
 extern StructRNA RNA_DelaySensor;
 extern StructRNA RNA_DisplaceModifier;

Modified: trunk/blender/source/blender/makesrna/intern/rna_constraint.c
===================================================================
--- trunk/blender/source/blender/makesrna/intern/rna_constraint.c	2009-10-30 02:09:52 UTC (rev 24173)
+++ trunk/blender/source/blender/makesrna/intern/rna_constraint.c	2009-10-30 06:33:40 UTC (rev 24174)
@@ -49,8 +49,9 @@
 	{CONSTRAINT_TYPE_SIZELIMIT, "LIMIT_SCALE", ICON_CONSTRAINT_DATA, "Limit Scale", ""},
 	{CONSTRAINT_TYPE_DISTLIMIT, "LIMIT_DISTANCE", ICON_CONSTRAINT_DATA, "Limit Distance", ""},
 	{0, "", 0, "Tracking", ""},
-	{CONSTRAINT_TYPE_TRACKTO, "TRACK_TO", ICON_CONSTRAINT_DATA, "Track To", ""},
-	{CONSTRAINT_TYPE_LOCKTRACK, "LOCKED_TRACK", ICON_CONSTRAINT_DATA, "Locked Track", ""},

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list