[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [29024] trunk/blender: == Pivot Constraint ==

Joshua Leung aligorith at gmail.com
Thu May 27 12:50:07 CEST 2010


Revision: 29024
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=29024
Author:   aligorith
Date:     2010-05-27 12:50:06 +0200 (Thu, 27 May 2010)

Log Message:
-----------
== Pivot Constraint ==

This constraint allows an object or bone to have their rotations applied as if their origin/pivot-point was located elsewhere. The most obvious uses include foot-roll, see-saws, but could also include more complicated rolling-box examples.  

== Usage Examples ==
=== Foot Roll ===
1. Add 'Pivot' Constraint to the bone without any target.
2. Set the 'Y' value of the offset to the length of the bone. Usually this should be negative (if you rig with feet facing 'forwards' along -Y axis). This gives you a pivot point relative to the bone's (preconstraint) location, which should be at the tip of the bone here. Disabling the 'Use Relative Offset' would make this offset be relative to 0,0,0 instead of to the owner/bone-head.
3. Ensure that the 'Pivot When' setting is set to '-X Rot', (default) which means that the pivot will only used when the rotation on the X-Axis is negative to get tip-toe 'roll'. 

=== See Saw ===
1. Add a 'Pivot' constraint too see-saw plank object, this time with a target that you wish to have as the pivot-point. It's possible to do this without too (as before), but is less intuitive.
2. Optionally, if you want the plank slightly raised, set the z-offset value, which should make the pivot-point used to be relative to the target with the z-offset applied.
3. Ensure that 'Pivot When' is set to 'Always', which means that the pivot will always be used, irrespective of the rotation.

== Notes ==
* The 'Pivot When' setting has been integrated in the constraint, since this is something that will often be required for these setups. Having to set up additional drivers to drive the constraint to do this kindof beats the purpose of providing this.

* The 'Offset' functionality is probably not presented as clearly as it could be. We may need to go over this again.

* For foot-roll - if any scaling of the foot is required, simply set up a driver on the y-offset to make this dynamically respond to the "scale" RNA property of the bones (don't use the "Transform Channel" vartype since that won't work correct here). However, this shouldn't be common enough to warrant special treatment.

Modified Paths:
--------------
    trunk/blender/release/scripts/ui/properties_object_constraint.py
    trunk/blender/source/blender/blenkernel/intern/constraint.c
    trunk/blender/source/blender/editors/object/object_constraint.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/properties_object_constraint.py
===================================================================
--- trunk/blender/release/scripts/ui/properties_object_constraint.py	2010-05-27 09:23:26 UTC (rev 29023)
+++ trunk/blender/release/scripts/ui/properties_object_constraint.py	2010-05-27 10:50:06 UTC (rev 29024)
@@ -76,7 +76,7 @@
                 else:
                     layout.prop_object(con, "subtarget", con.target.data, "bones", text="")
 
-                if con.type in ('COPY_LOCATION', 'STRETCH_TO', 'TRACK_TO'):
+                if con.type in ('COPY_LOCATION', 'STRETCH_TO', 'TRACK_TO', 'PIVOT'):
                     row = layout.row()
                     row.label(text="Head/Tail:")
                     row.prop(con, "head_tail", text="")
@@ -730,7 +730,23 @@
             col.prop(con, "xz_scaling_mode", text="")
         col.prop(con, "use_curve_radius")
 
+    def PIVOT(self, context, layout, con, wide_ui):
+        self.target_template(layout, con, wide_ui)
 
+        if con.target:
+            col = layout.column()
+            col.prop(con, "offset", text="Pivot Offset")
+        else:
+            col = layout.column()
+            col.prop(con, "use_relative_position")
+            if con.use_relative_position:  
+                col.prop(con, "offset", text="Relative Pivot Point")
+            else:
+                col.prop(con, "offset", text="Absolute Pivot Point")
+
+        col = layout.column()
+        col.prop(con, "enabled_rotation_range", text="Pivot When")
+
 class OBJECT_PT_constraints(ConstraintButtonsPanel):
     bl_label = "Object Constraints"
     bl_context = "constraint"

Modified: trunk/blender/source/blender/blenkernel/intern/constraint.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/constraint.c	2010-05-27 09:23:26 UTC (rev 29023)
+++ trunk/blender/source/blender/blenkernel/intern/constraint.c	2010-05-27 10:50:06 UTC (rev 29024)
@@ -3831,6 +3831,118 @@
 	NULL /* evaluate - solved as separate loop */
 };
 
+/* ----------- Pivot ------------- */
+
+static void pivotcon_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
+{
+	bPivotConstraint *data= con->data;
+	
+	/* target only */
+	func(con, (ID**)&data->tar, userdata);
+}
+
+static int pivotcon_get_tars (bConstraint *con, ListBase *list)
+{
+	if (con && list) {
+		bPivotConstraint *data= con->data;
+		bConstraintTarget *ct;
+		
+		/* standard target-getting macro for single-target constraints */
+		SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
+		
+		return 1;
+	}
+	
+	return 0;
+}
+
+static void pivotcon_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+	if (con && list) {
+		bPivotConstraint *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)
+	}
+}
+
+static void pivotcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+	bPivotConstraint *data= con->data;
+	bConstraintTarget *ct= targets->first;
+	
+	float pivot[3], vec[3];
+	float rotMat[3][3];
+	
+	/* firstly, check if pivoting should take place based on the current rotation */
+	if (data->rotAxis != PIVOTCON_AXIS_NONE) {
+		float rot[3];
+		
+		/* extract euler-rotation of target */
+		mat4_to_eulO(rot, cob->rotOrder, cob->matrix);
+		
+		/* check which range might be violated */
+		if (data->rotAxis < PIVOTCON_AXIS_X) {
+			/* negative rotations (data->rotAxis = 0 -> 2) */
+			if (rot[data->rotAxis] > 0.0f)
+				return;
+		}
+		else {
+			/* positive rotations (data->rotAxis = 3 -> 5 */
+			if (rot[data->rotAxis - PIVOTCON_AXIS_X] < 0.0f)
+				return;
+		}
+	}
+	
+	/* find the pivot-point to use  */
+	if (VALID_CONS_TARGET(ct)) {
+		/* apply offset to target location */
+		add_v3_v3v3(pivot, ct->matrix[3], data->offset);
+	}
+	else {
+		/* no targets to worry about... */
+		if ((data->flag & PIVOTCON_FLAG_OFFSET_ABS) == 0) {
+			/* offset is relative to owner */
+			add_v3_v3v3(pivot, cob->matrix[3], data->offset);
+		}
+		else {
+			/* directly use the 'offset' specified as an absolute position instead */
+			VECCOPY(pivot, data->offset);
+		}
+	}
+	
+	/* get rotation matrix representing the rotation of the owner */
+	// TODO: perhaps we might want to include scaling based on the pivot too?
+	copy_m3_m4(rotMat, cob->matrix);
+	normalize_m3(rotMat);
+	
+	/* perform the pivoting... */
+		/* 1. take the vector from owner to the pivot */
+	sub_v3_v3v3(vec, pivot, cob->matrix[3]);
+		/* 2. rotate this vector by the rotation of the object... */
+	mul_m3_v3(rotMat, vec);
+		/* 3. make the rotation in terms of the pivot now */
+	add_v3_v3v3(cob->matrix[3], pivot, vec);
+}
+
+
+static bConstraintTypeInfo CTI_PIVOT = {
+	CONSTRAINT_TYPE_PIVOT, /* type */
+	sizeof(bPivotConstraint), /* size */
+	"Pivot", /* name */
+	"bPivotConstraint", /* struct name */
+	NULL, /* free data */
+	NULL, /* relink data */
+	pivotcon_id_looper, /* id looper */
+	NULL, /* copy data */
+	NULL, /* new data */ // XXX: might be needed to get 'normal' pivot behaviour...
+	pivotcon_get_tars, /* get constraint targets */
+	pivotcon_flush_tars, /* flush constraint targets */
+	default_get_tarmat, /* get target matrix */
+	pivotcon_evaluate /* evaluate */
+};
+
 /* ************************* Constraints Type-Info *************************** */
 /* All of the constraints api functions use bConstraintTypeInfo structs to carry out
  * and operations that involve constraint specific code.
@@ -3867,6 +3979,7 @@
 	constraintsTypeInfo[22]= &CTI_SPLINEIK;			/* Spline IK Constraint */
 	constraintsTypeInfo[23]= &CTI_TRANSLIKE;		/* Copy Transforms Constraint */
 	constraintsTypeInfo[24]= &CTI_SAMEVOL;			/* Maintain Volume Constraint */
+	constraintsTypeInfo[25]= &CTI_PIVOT;			/* Pivot Constraint */
 }
 
 /* This function should be used for getting the appropriate type-info when only

Modified: trunk/blender/source/blender/editors/object/object_constraint.c
===================================================================
--- trunk/blender/source/blender/editors/object/object_constraint.c	2010-05-27 09:23:26 UTC (rev 29023)
+++ trunk/blender/source/blender/editors/object/object_constraint.c	2010-05-27 10:50:06 UTC (rev 29024)
@@ -322,6 +322,23 @@
 				/* targets have already been checked for this */
 				continue;
 			}
+			else if (curcon->type == CONSTRAINT_TYPE_PIVOT) {
+				bPivotConstraint *data = curcon->data;
+				
+				/* target doesn't have to exist, but if it is non-null, it must exist! */
+				if (data->tar && exist_object(data->tar)==0) {
+					data->tar = NULL;
+					curcon->flag |= CONSTRAINT_DISABLE;
+				}
+				else if (data->tar == owner) {
+					if (!get_named_bone(get_armature(owner), data->subtarget)) {
+						curcon->flag |= CONSTRAINT_DISABLE;
+					}
+				}
+				
+				/* targets have already been checked for this */
+				continue;
+			}
 			else if (curcon->type == CONSTRAINT_TYPE_ACTION) {
 				bActionConstraint *data = curcon->data;
 				

Modified: trunk/blender/source/blender/makesdna/DNA_constraint_types.h
===================================================================
--- trunk/blender/source/blender/makesdna/DNA_constraint_types.h	2010-05-27 09:23:26 UTC (rev 29023)
+++ trunk/blender/source/blender/makesdna/DNA_constraint_types.h	2010-05-27 10:50:06 UTC (rev 29024)
@@ -174,6 +174,7 @@
 
 
 /* Single-target subobject constraints ---------------------  */
+
 /* Track To Constraint */
 typedef struct bTrackToConstraint {
 	Object		*tar;
@@ -336,6 +337,24 @@
 	float		to_max[3];	
 } bTransformConstraint;
 
+/* Pivot Constraint */
+typedef struct bPivotConstraint {
+	/* Pivot Point:
+	 *	Either target object + offset, or just offset is used
+	 */
+	Object 		*tar;			/* target object (optional) */
+	char	 	subtarget[32];		/* subtarget name (optional) */
+	float 		offset[3];		/* offset from the target to use, regardless of whether it exists */
+	
+	/* Rotation-driven activation:
+	 *	This option provides easier one-stop setups for footrolls
+	 */
+	short 		rotAxis;		/* rotation axes to consider for this (ePivotConstraint_Axis) */
+	
+	/* General flags */
+	short 		flag;			/* ePivotConstraint_Flag */
+} bPivotConstraint;
+
 /* transform limiting constraints - zero target ----------------------------  */
 /* Limit Location Constraint */
 typedef struct bLocLimitConstraint {
@@ -419,6 +438,7 @@
 	CONSTRAINT_TYPE_SPLINEIK,			/* Spline-IK - Align 'n' bones to a curve */
 	CONSTRAINT_TYPE_TRANSLIKE,			/* Copy transform matrix */
 	CONSTRAINT_TYPE_SAMEVOL,			/* Maintain volume during scaling */
+	CONSTRAINT_TYPE_PIVOT,				/* Pivot Constraint */
 	
 	/* NOTE: no constraints are allowed to be added after this */
 	NUM_CONSTRAINT_TYPES
@@ -469,11 +489,6 @@
 
 /* -------------------------------------- */
 
-/**
- * The flags for ROTLIKE, LOCLIKE and SIZELIKE should be kept identical
- * (that is, same effect, different name). It simplifies the Python API access a lot.
- */
-
 /* bRotateLikeConstraint.flag */
 typedef enum eCopyRotation_Flags {
 	ROTLIKE_X			= (1<<0),
@@ -688,6 +703,35 @@
 	CHILDOF_SIZEZ	= (1<<8),
 } eChildOf_Flags;
 
+/* Pivot Constraint */
+	/* Restrictions for Pivot Constraint axis to consider for enabling constraint */
+typedef enum ePivotConstraint_Axis {
+	/* do not consider this activity-clamping */
+	PIVOTCON_AXIS_NONE = -1,	
+	
+	/* consider -ve x-axis rotations */
+	PIVOTCON_AXIS_X_NEG,
+	/* consider -ve y-axis rotations */
+	PIVOTCON_AXIS_Y_NEG,
+	/* consider -ve z-axis rotations */
+	PIVOTCON_AXIS_Z_NEG,
+	
+	/* consider +ve x-axis rotations */
+	PIVOTCON_AXIS_X,
+	/* consider +ve y-axis rotations */
+	PIVOTCON_AXIS_Y,
+	/* consider +ve z-axis rotations */
+	PIVOTCON_AXIS_Z,
+} ePivotConstraint_Axis;
+
+	/* settings for Pivot Constraint in general */
+typedef enum ePivotConstraint_Flag {
+	/* offset is to be interpreted as being a fixed-point in space */
+	PIVOTCON_FLAG_OFFSET_ABS	= (1<<0),
+	/* rotation-based activation uses negative rotation to drive result */
+	PIVOTCON_FLAG_ROTACT_NEG	= (1<<1),
+} ePivotConstraint_Flag;
+
 /* Rigid-Body Constraint */
 #define CONSTRAINT_DRAW_PIVOT 0x40
 #define 	CONSTRAINT_DISABLE_LINKED_COLLISION 0x80

Modified: trunk/blender/source/blender/makesrna/RNA_access.h
===================================================================

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list