2
$\begingroup$

Object A is constrained to -20 degrees and +15 degrees rotation on the X axis.

Object B is constrained to -90 degrees and +90 degrees rotation on the X axis.

I would like the rotation of A to be driven by the rotation of B. Normally, this is a simple enough procedure, but I lack the mathematical understanding to write the correct expression. Here's my intention:

When Object B is at 0 degrees, Object A is also at 0 degrees. I'd then like to take the percentage of Object B's rotation to rotate Object A to it's constraint by that same percentage.

For example: If Object B rotates +45 degrees, that's halfway to its constraint of +90, so the value should be 0.5. I then want to apply this 0.5 to the +15 degree limit of Object A, so 0.5 of +15 is +7.5, but if Object B rotates -45, it's now -0.5, which when applied to Object A's -20 degree limit, is -10.

EDIT:

The closest expression I can get is -var/90*20. This takes the percentage of rotation to Object B's +90 degree limit, then applies that to Object A's constraint of -20 degrees. Only problem is, that expression needs to be -var/90*15 when Object B's rotation is negative. Is there a way to write an if statement along the lines of if var<0, then -var/90*15, else -var/90*20? I'm unfamiliar with the syntax.

$\endgroup$
4
  • $\begingroup$ Actually, this isn't a rigging exercise. No bones or anything. I'm creating a model of an aircraft, and some of the control surfaces deflect more in one direction, than another. This deflection is driven by rotating the yoke. Not sure how to illustrate that, but if needed, I could upload the .blend file. $\endgroup$
    – hiigaran
    Aug 23 at 8:59
  • $\begingroup$ Also, see my edit. It might be an easier way to solve this. $\endgroup$
    – hiigaran
    Aug 23 at 9:11
  • $\begingroup$ I saw a comment on my answer briefly earlier today when I didn't have time to get to it.... Don't forget, you can always use an f-curve for complex relationships.. avoiding expressions for them. $\endgroup$ Aug 23 at 13:38
  • $\begingroup$ @RobinBetts: Yeah, I had a follow up question as I was trying to apply your solution to a similar need, except X position drove another object's X rotation instead. I managed to figure it out though. $\endgroup$
    – hiigaran
    Aug 23 at 15:44
4
$\begingroup$

It sounds as if you need two ranges, one for negative angles and one for positive?

You can avoid if clauses in limited-space driver expressions by using the implicit cast of Boolean True and False to integer 1 and 0, and multiplying:

((20/90) * (B_rZ < 0) + (15/90) * (B_rZ >= 0)) * B_rZ

where B_rZ is B's Z rotation.

enter image description here

$\endgroup$
2
  • $\begingroup$ This would do if you don't need your movement to be smooth across 0 .. it's just a straight-line function on either side. $\endgroup$ Aug 23 at 9:31
  • 1
    $\begingroup$ Correct. For the purposes of what I'm trying to achieve in my file, this is sufficient. Did some research on Python syntax, and I was pretty much ready to go with -var/90*15 if var<0 else -var/90*20, but modifying your suggestion to ((15/90) * (var < 0) + (20/90) * (var >= 0)) * -var works just as well, and looks like a more elegant solution. Wouldn't have thought to use true/false as 1 and 0 to multiply away the irrelevant part. Thank you. $\endgroup$
    – hiigaran
    Aug 23 at 9:37
4
$\begingroup$

Linear interpolation.

After seeking clarification in a comment, I've come to that what you seek is linear interpolation, ie if we are some ratio between A and B, what is the point at the same ratio between C and D.

The lerp is available to the driver namespace, ie it can be used in driver expressions.

>>> import bl_math
>>> bl_math.lerp(
lerp(from, to, factor)
.. function:: lerp(from, to, factor)
Linearly interpolate between two float values based on factor.
:arg from: The value to return when factor is 0.
:type from: float
:arg to: The value to return when factor is 1.
:type to: float
:arg factor: The interpolation value, normally in [0.0, 1.0].
:type factor: float
:return: The interpolated value.
:rtype: float

And its partner in crime. smooth_step

>>> bl_math.smoothstep(
smoothstep(from, to, value)
.. function:: smoothstep(from, to, value)
Performs smooth interpolation between 0 and 1 as value changes between from and to.
Outside the range the function returns the same value as the nearest edge.
:arg from: The edge value where the result is 0.
:type from: float
:arg to: The edge value where the result is 1.
:type to: float
:arg factor: The interpolation value.
:type factor: float
:return: The interpolated value in [0.0, 1.0].
:rtype: float

To get the values as driver vars: Mouse over one of the limit rotation constraint axis rotation limits, right click and choose "Copy Data Path" it copies

pose.bones["Bone"].constraints["Limit Rotation"].min_x 

to the clipboard. Paste that into a single property driver variable datapath. (The object chosen is the rig.) and the driver variable will have the constraints min x value

enter image description here

In example minimum is set to 45 degrees. Blender uses radians as base unit (the degrees are converted and displayed if scene unit for rotation is degrees (the default))

>>> radians(45)
0.7853981633974483

Finally,

If we set up a driver with variables

  • A current value of A

  • Amin lower limit of A

  • Amax upper limit of A

  • Bmin lower limit of B

  • Bmax upper limit of B

, to find rotation B which is rotation of B that is same ration between Bmin, Bax as A is between Amin, Amax

Then our ratio toward Amax from Amin is

smoothstep(Amin, Amax, A)

And finally, to the driver expression to set B rotation

lerp(Bmin, Bmax, smoothstep(Amin, Amax, A))

or hardcode in the values if they dont change, eg A is some rot between 0 and 180 what is the same ratio between -45 and 45 degrees

radians(lerp(-45, 45, smoothstep(0, 180, degrees(A)))

A path.

Instead of limit rotation constraints consider using a curve path as part of your rig. Can be parented to a bone. A follow path constraint fixed offset 0 is one end of the path 1 the other. the rotation bone instead tracks to an object (or bone) following the path. Driving another is simply a matter of using offset of other.

$\endgroup$
4
  • $\begingroup$ Ahhh, so @hiigaran wants a continuous function, over 0? $\endgroup$ Aug 23 at 9:24
  • 1
    $\begingroup$ Not sure, its one of those questions that I can read a zillion times and still not be sure. Talked myself into linear interpolation while seeking clarification, Haven't bothered with clamp (the other member of the sneaky bl_maths since limit constraint should deal with. Once again I'm going to be foiled by the Master of Illustration .. lol got that right.... bloody BSR. $\endgroup$
    – batFINGER
    Aug 23 at 9:38
  • $\begingroup$ Pure luck, in the circumstances :D $\endgroup$ Aug 23 at 9:41
  • $\begingroup$ missed the dual range part too. $\endgroup$
    – batFINGER
    Aug 23 at 9:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.