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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to