[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [23141] branches/blender2.5/blender: 2. 5 - Rotation Locking for Bones

Joshua Leung aligorith at gmail.com
Sat Sep 12 14:30:23 CEST 2009


Revision: 23141
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=23141
Author:   aligorith
Date:     2009-09-12 14:30:23 +0200 (Sat, 12 Sep 2009)

Log Message:
-----------
2.5 - Rotation Locking for Bones

* Added Transform Locks panel. The layout for rotation I'm not satisfied with yet, though it is the best alternative so far.

* Rotations can now be locked per-component for quats/axis-angle instead of going through eulers. This is currently enabled by the checkbox for the 'label' of the Lock Rotation column. 
- The naming of the property in RNA + the way this is presented in the UI can get some work done.
- The setting for the 'w' component for quats/axis-angle is currently a separate flag in RNA, since I can't figure out how to lump this in under the 'lock_rotation' property instead (i.e. getting that to be either 3 or 4 components, depending on whether per-component locking is enabled).
- Editing values directly should not be possible when these locks are set...

* Fixed some tools which made use of this

Modified Paths:
--------------
    branches/blender2.5/blender/release/ui/buttons_data_bone.py
    branches/blender2.5/blender/source/blender/editors/armature/editarmature.c
    branches/blender2.5/blender/source/blender/editors/armature/poseobject.c
    branches/blender2.5/blender/source/blender/editors/transform/transform.c
    branches/blender2.5/blender/source/blender/makesdna/DNA_object_types.h
    branches/blender2.5/blender/source/blender/makesrna/intern/rna_pose.c

Modified: branches/blender2.5/blender/release/ui/buttons_data_bone.py
===================================================================
--- branches/blender2.5/blender/release/ui/buttons_data_bone.py	2009-09-12 10:21:55 UTC (rev 23140)
+++ branches/blender2.5/blender/release/ui/buttons_data_bone.py	2009-09-12 12:30:23 UTC (rev 23141)
@@ -71,6 +71,35 @@
 				col = layout.column(align=True)
 				col.itemL(text="Euler:")
 				col.row().itemR(pchan, "euler_rotation", text="")
+				
+class BONE_PT_transform_locks(BoneButtonsPanel):
+	__label__ = "Transform Locks"
+	
+	def poll(self, context):
+		return context.bone
+	
+	def draw(self, context):
+		layout = self.layout
+		
+		ob = context.object
+		bone = context.bone
+		pchan = ob.pose.pose_channels[context.bone.name]
+		
+		row = layout.row()
+		col = row.column()
+		col.itemR(pchan, "lock_location")
+		col.active = not (bone.parent and bone.connected)
+		
+		col = row.column()
+		if pchan.rotation_mode in ('QUATERNION', 'AXIS_ANGLE'):
+			col.itemR(pchan, "lock_rotations_4d", text="Lock Rotation")
+			if pchan.lock_rotations_4d:
+				col.itemR(pchan, "lock_rotation_w", text="W")
+			col.itemR(pchan, "lock_rotation", text="")
+		else:
+			col.itemR(pchan, "lock_rotation", text="Rotation")
+		
+		row.column().itemR(pchan, "lock_scale")
 
 class BONE_PT_bone(BoneButtonsPanel):
 	__label__ = "Bone"
@@ -243,6 +272,7 @@
 
 bpy.types.register(BONE_PT_context_bone)
 bpy.types.register(BONE_PT_transform)
+bpy.types.register(BONE_PT_transform_locks)
 bpy.types.register(BONE_PT_bone)
 bpy.types.register(BONE_PT_deform)
 bpy.types.register(BONE_PT_inverse_kinematics)

Modified: branches/blender2.5/blender/source/blender/editors/armature/editarmature.c
===================================================================
--- branches/blender2.5/blender/source/blender/editors/armature/editarmature.c	2009-09-12 10:21:55 UTC (rev 23140)
+++ branches/blender2.5/blender/source/blender/editors/armature/editarmature.c	2009-09-12 12:30:23 UTC (rev 23141)
@@ -4849,43 +4849,57 @@
 	
 	/* only clear those channels that are not locked */
 	CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) {
-		if (pchan->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ)) {
-			float eul[3], oldeul[3], quat1[4];
-			
-			if (pchan->rotmode == PCHAN_ROT_QUAT) {
-				QUATCOPY(quat1, pchan->quat);
-				QuatToEul(pchan->quat, oldeul);
+		if (pchan->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) {
+			/* check if convert to eulers for locking... */
+			if (pchan->protectflag & OB_LOCK_ROT4D) {
+				/* perform clamping on a component by component basis */
+				if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
+					pchan->quat[0]= (pchan->rotmode == PCHAN_ROT_AXISANGLE) ? 0.0f : 1.0f;
+				if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+					pchan->quat[1]= 0.0f;
+				if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+					pchan->quat[2]= 0.0f;
+				if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+					pchan->quat[3]= 0.0f;
 			}
-			else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
-				continue; // XXX
-			}
 			else {
-				VECCOPY(oldeul, pchan->eul);
-			}
-			
-			eul[0]= eul[1]= eul[2]= 0.0f;
-			
-			// TODO: for 4 channel rotations, we need special flags for those too...
-			if (pchan->protectflag & OB_LOCK_ROTX)
-				eul[0]= oldeul[0];
-			if (pchan->protectflag & OB_LOCK_ROTY)
-				eul[1]= oldeul[1];
-			if (pchan->protectflag & OB_LOCK_ROTZ)
-				eul[2]= oldeul[2];
-			
-			if (pchan->rotmode == PCHAN_ROT_QUAT) {
-				EulToQuat(eul, pchan->quat);
-				/* quaternions flip w sign to accumulate rotations correctly */
-				if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
-					QuatMulf(pchan->quat, -1.0f);
+				/* perform clamping using euler form (3-components) */
+				float eul[3], oldeul[3], quat1[4];
+				
+				if (pchan->rotmode == PCHAN_ROT_QUAT) {
+					QUATCOPY(quat1, pchan->quat);
+					QuatToEul(pchan->quat, oldeul);
 				}
+				else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
+					AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT);
+				}
+				else {
+					VECCOPY(oldeul, pchan->eul);
+				}
+				
+				eul[0]= eul[1]= eul[2]= 0.0f;
+				
+				if (pchan->protectflag & OB_LOCK_ROTX)
+					eul[0]= oldeul[0];
+				if (pchan->protectflag & OB_LOCK_ROTY)
+					eul[1]= oldeul[1];
+				if (pchan->protectflag & OB_LOCK_ROTZ)
+					eul[2]= oldeul[2];
+				
+				if (pchan->rotmode == PCHAN_ROT_QUAT) {
+					EulToQuat(eul, pchan->quat);
+					/* quaternions flip w sign to accumulate rotations correctly */
+					if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) {
+						QuatMulf(pchan->quat, -1.0f);
+					}
+				}
+				else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
+					AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT);
+				}
+				else {
+					VECCOPY(pchan->eul, eul);
+				}
 			}
-			else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) {
-				// TODO...
-			}
-			else {
-				VECCOPY(pchan->eul, eul);
-			}
 		}						
 		else { 
 			if (pchan->rotmode == PCHAN_ROT_QUAT) {

Modified: branches/blender2.5/blender/source/blender/editors/armature/poseobject.c
===================================================================
--- branches/blender2.5/blender/source/blender/editors/armature/poseobject.c	2009-09-12 10:21:55 UTC (rev 23140)
+++ branches/blender2.5/blender/source/blender/editors/armature/poseobject.c	2009-09-12 12:30:23 UTC (rev 23141)
@@ -998,7 +998,6 @@
 				pchan->flag= chan->flag;
 				
 				/* check if rotation modes are compatible (i.e. do they need any conversions) */
-				// FIXME: add axis-angle here too...
 				if (pchan->rotmode == chan->rotmode) {
 					/* copy the type of rotation in use */
 					if (pchan->rotmode > 0) {

Modified: branches/blender2.5/blender/source/blender/editors/transform/transform.c
===================================================================
--- branches/blender2.5/blender/source/blender/editors/transform/transform.c	2009-09-12 10:21:55 UTC (rev 23140)
+++ branches/blender2.5/blender/source/blender/editors/transform/transform.c	2009-09-12 12:30:23 UTC (rev 23141)
@@ -1610,29 +1610,88 @@
 		eul[2]= oldeul[2];
 }
 
+
+/* this function only does the delta rotation */
+/* axis-angle is usually internally stored as quats... */
+static void protectedAxisAngleBits(short protectflag, float *quat, float *oldquat)
+{
+	/* check that protection flags are set */
+	if ((protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) == 0)
+		return;
+	
+	if (protectflag & OB_LOCK_ROT4D) {
+		/* axis-angle getting limited as 4D entities that they are... */
+		if (protectflag & OB_LOCK_ROTW)
+			quat[0]= oldquat[0];
+		if (protectflag & OB_LOCK_ROTX)
+			quat[1]= oldquat[1];
+		if (protectflag & OB_LOCK_ROTY)
+			quat[2]= oldquat[2];
+		if (protectflag & OB_LOCK_ROTZ)
+			quat[3]= oldquat[3];
+	}
+	else {
+		/* axis-angle get limited with euler... */
+		float eul[3], oldeul[3], quat1[4];
+		
+		QUATCOPY(quat1, quat);
+		AxisAngleToEulO(quat+1, quat[0], eul, EULER_ORDER_DEFAULT);
+		AxisAngleToEulO(oldquat+1, oldquat[0], oldeul, EULER_ORDER_DEFAULT);
+		
+		if (protectflag & OB_LOCK_ROTX)
+			eul[0]= oldeul[0];
+		if (protectflag & OB_LOCK_ROTY)
+			eul[1]= oldeul[1];
+		if (protectflag & OB_LOCK_ROTZ)
+			eul[2]= oldeul[2];
+		
+		EulOToAxisAngle(eul, EULER_ORDER_DEFAULT, quat+1, quat);
+		
+		/* when converting to axis-angle, we need a special exception for the case when there is no axis */
+		if (IS_EQ(quat[1], quat[2]) && IS_EQ(quat[2], quat[3])) {
+			/* for now, rotate around y-axis then (so that it simply becomes the roll) */
+			quat[2]= 1.0f;
+		}
+	}
+}
+
+/* this function only does the delta rotation */
 static void protectedQuaternionBits(short protectflag, float *quat, float *oldquat)
 {
-	/* quaternions get limited with euler... */
-	/* this function only does the delta rotation */
+	/* check that protection flags are set */
+	if ((protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) == 0)
+		return;
 	
-	// FIXME: need special checks for quality here...
-	if(protectflag) {
+	if (protectflag & OB_LOCK_ROT4D) {
+		/* quaternions getting limited as 4D entities that they are... */
+		if (protectflag & OB_LOCK_ROTW)
+			quat[0]= oldquat[0];
+		if (protectflag & OB_LOCK_ROTX)
+			quat[1]= oldquat[1];
+		if (protectflag & OB_LOCK_ROTY)
+			quat[2]= oldquat[2];
+		if (protectflag & OB_LOCK_ROTZ)
+			quat[3]= oldquat[3];
+	}
+	else {
+		/* quaternions get limited with euler... (compatability mode) */
 		float eul[3], oldeul[3], quat1[4];
-
+		
 		QUATCOPY(quat1, quat);
 		QuatToEul(quat, eul);
 		QuatToEul(oldquat, oldeul);
-
-		if(protectflag & OB_LOCK_ROTX)
+		
+		if (protectflag & OB_LOCK_ROTX)
 			eul[0]= oldeul[0];
-		if(protectflag & OB_LOCK_ROTY)
+		if (protectflag & OB_LOCK_ROTY)
 			eul[1]= oldeul[1];
-		if(protectflag & OB_LOCK_ROTZ)
+		if (protectflag & OB_LOCK_ROTZ)
 			eul[2]= oldeul[2];
-
+		
 		EulToQuat(eul, quat);
+		
 		/* quaternions flip w sign to accumulate rotations correctly */
-		if( (quat1[0]<0.0f && quat[0]>0.0f) || (quat1[0]>0.0f && quat[0]<0.0f) ) {
+		if ( (quat1[0]<0.0f && quat[0]>0.0f) || (quat1[0]>0.0f && quat[0]<0.0f) ) {
 			QuatMulf(quat, -1.0f);
 		}
 	}
@@ -1733,17 +1792,24 @@
 			else
 				return;
 		}
-		else if (td->tdi) {
+		else if (td->tdi) { // XXX depreceated
 			/* ipo-keys eulers */
 			TransDataIpokey *tdi= td->tdi;
 			float eul[3];
-
+			
 			eul[0]= tdi->rotx[0];
 			eul[1]= tdi->roty[0];
 			eul[2]= tdi->rotz[0];
-
+			
 			EulOToMat4(eul, td->rotOrder, cob.matrix);
 		}
+		else if (td->rotOrder == PCHAN_ROT_AXISANGLE) {
+			/* axis angle */
+			if (td->ext)
+				AxisAngleToMat4(&td->ext->quat[1], td->ext->quat[0], cob.matrix);
+			else
+				return;
+		}
 		else {
 			/* eulers */
 			if (td->ext)
@@ -1751,22 +1817,22 @@
 			else
 				return;
 		}
-
+		
 		/* Evaluate valid constraints */
 		for (con= td->con; con; con= con->next) {
 			/* only consider constraint if enabled */
 			if (con->flag & CONSTRAINT_DISABLE) continue;
 			if (con->enforce == 0.0f) continue;
-
+			
 			/* we're only interested in Limit-Rotation constraints */
 			if (con->type == CONSTRAINT_TYPE_ROTLIMIT) {
 				bRotLimitConstraint *data= con->data;
 				float tmat[4][4];
-
+				
 				/* only use it if it's tagged for this purpose */
 				if ((data->flag2 & LIMIT_TRANSFORM)==0)
 					continue;
-
+				
 				/* do space conversions */
 				if (con->ownspace == CONSTRAINT_SPACE_WORLD) {

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list