0

There are two objects, Object A and Object B. Object A has Track To constraint and its target is Object B, then I would like to control this Track To constraints influence based on the distance between Object A and Object B.

I tried this driver expression 1-var**-1 if var < 50 else 1

enter image description here

Left cube is Object B and right one is Object A.

Constraint influence works on 0 - 1 range but this driver expression has a problem.As you can see,to lessen the influence value, Object B needs to come closer to Object A, but I would like them to keep a distance.

In this situation constraints influence needs to be 0.1 and distance between them needs to be at least value 20 or more. I don't know much about this kind of mathematics, so if you know much better way please tell me.

This driver function works fine. This solved my problem.

def InfluenceControl(infbase,distance,expo,distanceMax):
    if distance < distanceMax:
        return infbase - distance**expo
    else:
        return infbase - distanceMax**expo

bpy.app.driver_namespace['InfluenceControl'] = InfluenceControl

expression 1-var**-1 if var < 50 else 1 will be like InfluenceControl(1,var,-1,50) and it returns 0.9796 when var is 49 and it returns 0.9796 too when var is 50.1.

Duarte Farrajota Ramos
  • 59,425
  • 39
  • 130
  • 187
Yokomizo
  • 391
  • 1
  • 9
  • could you please describe in non-mathematical words what you want to achieve? e.g. like: i don't want Object A nearer than 1 m to Object b...because sorry, but i don't understand what you are trying to do...maybe some sketches would help – Chris Dec 11 '21 at 15:53
  • I need to increase or control influence decreasing speed.as you can see both objects need to be close to decrease influence value. – Yokomizo Dec 11 '21 at 15:56
  • it's really hard to explain but right now,

    influence value is 0.95 when distance value is 17 influence value is 0.75 when distance value is 4.2 influence value is 0.1 when distance value is 1.

    it needs to be like

    influence value is 0.95 when distance value is 40 influence value is 0.5 when distance value is 30 influence value is 0.1 when distance value is 20

    – Yokomizo Dec 11 '21 at 16:08
  • var**-1 can be written as 1/var. 1/1.116 = 0.8960573476702508 ; 1 - 0.8960573476702508 = 0.1039426523297492 which rounds to 0.104, the result you get. – Markus von Broady Dec 11 '21 at 23:30
  • it only works if exponentiation number is 1. – Yokomizo Dec 12 '21 at 06:49
  • 1-var-1 if var < 50 else 1 this expression problem is return number keeps changing if var number is under 50 but if var get like 50.1 return number get 1 so influence number changes too much in this situation. for example 1-49-1 = 0.9795919. this gets 1 right after var gets higher than 50. 1-0.9795919 = 0.0204081.This is the added value when var goes from 49 to 50.1.This is huge gap for constraints influence value and animation looks terrible when this transition occurs. I want to smooth the transition between var = 49 and var = 50.1 situation. – Yokomizo Dec 12 '21 at 07:03

1 Answers1

1

It's not perfectly clear what's your problem, so let's solve it from the end - which is your answer to your own problem - your function:

def InfluenceControl(infbase,distance,expo,distanceMax):
    if distance < distanceMax:
        return infbase - distance**expo
    else:
        return infbase - distanceMax**expo

Can be rephrased as a single line with the condition moved to a conditional operator controlling only the usage of distance vs distanceMax rather than alternating between whole formulas:

def InfluenceControl(infbase,distance,expo,distanceMax):
    return infbase - (distance if distance < distanceMax else distanceMax)**expo

You use your "driver function" this way: InfluenceControl(1,var,-1,50) - the way you describe, the arguments never change (except the value under the name var changes). If that's the case, you can put those values inside the function:

def InfluenceControl(distance):
    return 1 - (distance if distance < 50 else 50)**-1

What does distance if distance < 50 else 50 mean? It means: use distance, but make it no more than 50. So it can be replaced with clamping done by min function:

def InfluenceControl(distance):
    return 1 - min(distance, 50)**-1

As you can see, not only it has become a one-liner, which you can use directly as a driver (and so you don't need to run a script that adds a function to the driver namespace, which makes the project easier to maintain), but is also more readable. Though an argument could be made, that using your original function is more readable if you used it with keyword arguments: InfluenceControl(infbase=1, distance=var, expo=-1, distanceMax=50).

Moreover, your original function allows to use it in various places, with various exponents and so on. You also reply to my remark in comments (var**-1 can be written as 1/var) with "it only works if exponentiation number is 1", which suggests you want to easily change it. If so, you should put it in your question!, and describe why, to avoid an XY Problem.

Arguably, a formula 1 - min(distance, 50)**-1 (if used in a driver, remember to rename var to distance!) is no less, and in fact much more readable than InfluenceControl(1, distance, -1, 50). Also I don't think a simple formula like that justifies a function that would guard consistency between different places where it's used, because IMHO the consistency is guaranteed by the logic of the formula. So just change an exponent, or max distance (I don't imagine you may want to change the 1 number) wherever you copy-paste the driver...

Finally, using either an external function InfluenceControl or the ** operator makes the driver a slow expression. Instead, use the function pow, so the driver becomes:

1 - pow(min(distance, 50), -1)
Markus von Broady
  • 36,563
  • 3
  • 30
  • 99
  • thank you. to be honest when I asked this question, I didn't understand exactly what was the problem. I wrote var**-1 but it's an example. driver controlled cubes situation is simplified example too. I always ask using simplified things. sorry. I I will read your post. I don't understand all you said right now but min() and pow() will be useful. – Yokomizo Dec 13 '21 at 00:44
  • I will use yours as driver function because I always forget what my driver scripts mean. I can add annotations if I use it as .py file. thank you. I re-wrote other functions using min() and max(). much simpler now. – Yokomizo Dec 13 '21 at 07:36