Can i animate hundreds of objects based on proximity another object?

Ive been trying to figure out how to create a constraint that animates a channel based on how close it is to a specified object. Like setting an empty to cause the hundreds of boxes around it to grow taller as the empty gets closer to each one.
Here is an example of a maya script called proximityAnim.mel that does something similar.

I have a large group of objects that i want to scale on their x axis between 0 and 1, or, better yet, be able to drive an action between 0 and 100% based on how close a “controller” empty gets to them.
Any ideas on how i can accomplish this? Thanks!

Couldn’t you do that with drivers and a scripted expression?

import bpy

def processProximal(passedDistance):
    # Could add more advanced processing here.
    result = passedDistance
    return result['processProximal'] = processProximal

In this scene the Empty acts as the proximal location. The drivers are applied to the cube scale-z axis. Blender’s driver system already has built in distance calculation for bones. In this case we can cheat the system by using objects instead of bones. So the Empty is considers bone #1 and the object (any of the cubes) is considered bone #2. The distance calculation is placed in a variable called dist which is passed to the processProxinal def which returns the actual value for the z-scale at any given time.

Here is an example setup.


26_empty_proximal.blend (457 KB)

Atom, your awesome!!

It looks like this would work. After playing with it iniitally, I found I could clamp the maximum scale distance by adding a limit scaling constraint.

I’m pretty dumb at math, apparently, so I’m a bit stumped at this next thing. I actually need the cubes to be scaled to 0% and invisible until the empty gets close to them, at which point they begin to grow. Now, I think I can add this expression to the “visibilty” channel of each object, but it will need to be an inverted value somehow. For example, for the box to be scaled to 0 and invisible, scale is at 0, “Restrict view” and “restrict render” are set to 1.

One other little production issue I’m having with this, is that I’ve already created about a hundred shapes for this project, with hundreds more to go. Any suggestions on how I may be able to apply this expression/constraint combo to all at once?

Thanks again for all of your help and suggestions.

Test this first before applying it to the entire group of objects:

  1. Before applying your driver, select all the objects and use Join to make them a single object.

  2. Apply your driver to the Joined object.

  3. In Edit Mode, Select All and Separate (P-KEY), choose the “by loose parts” option.

Caveats: I’m not sure the driver will persist in all the Separated loose parts. Also, object centers of the Separated parts will be changed to that of the Joined object as a whole, and will need to be reset if they were located elsewhere and it’s critical where they’re placed. Be sure to test first!

Another idea (test first!): Add the driver to a single cube, put an Array modifier on it to generate many instances, Apply the modifier. Object center issues may still apply.

Thanks for the suggestions, but i dont think they will work i this case. Each object is specially placed and modeled, with several modifiers and an associated path for each.

Im actually very impressed with how stable blender is through all of this, but i fear for its performance as this scene gets heavier. By the end of the project i will have hundreds of objects, each with several modifiers and expressions… Ulp. Makes me really dream of a multithreaded blender. :slight_smile:

Ill keep my fingers crossed. If push comes to shove i can add each expression manually to the ones ive done so far, but i would rather not. :stuck_out_tongue:

Given the additional info about the existing objects, you’re right, my suggestions won’t work. If you’re so inclined, BPython scripting can often take care of automated special-case situations like this. Can’t say it’d be any faster in the long run than manually adding the driver, but that depends a lot on your coding ability. But once written and de-bugged, scripts can work very fast, and Python is a very versatile language.

Heh, did some rough estimates and it looks like when I’ve modeled all of these objects I will have between 1000-2000 individual objects with 3-5 animated modifiers on each one. Setting up a script to refine this cluster of objects might actually be worth learning python better, lol.

Or you might try finding a practiced scripter to help you out, especially if you have no scripting/coding background.

here is a different approach, run script and press play to test
just place the objects you need to scale under OBJECTS empty…

@chipmasque: FYI: Drivers do persist after a separate. I created a variation on this scene using an array modifier. After I issued the separate I was pleased to see that each new object had it’s own mesh and the driver setup was still intact.

@liero: That is a nice setup Liero. Here is a slight modification to your code to link the empty size to the radius value in your script. Then you could animate the influence simply by animating the empty display size.

def stuff(scene)
    ob_target =["TARGET"]
    radius = ob_target.empty_draw_size

That script is pretty slick leiro, thanks!

Can you explain a bit what exactly it’s doing? Does it simply add drivers to everything inside the OBJECTS empty at runtime, or is more dynamic, allowing the user to drop objects in and out of the empty as they build the scene?

I REALLY have to learn python someday. :slight_smile: I do have a rather basic question concerning working with python scripts in blender. This script appears to be somewhat “destructive”. Meaning that it runs and applies a bunch of settings and that’s it. There’s no going back, or iterating on the script, tweaking values, etc. What is the general workflow for working with scripts in python?

As I understand it so far, you write your script into the editor and save it inside the blender scene as a .py file. The blender scene can save an unlimited number of scripts in the scene and if I want the script to run upon loading the scene, I click the “register” button, correct?

Just trying to understand some python basics as I try to reverse engineer these terrific examples for use in my scene. :slight_smile:

Thanks again!

@Atom good idea, moved those variables inside function and added them as custom properties, now you can animate from there…

@fahr the empty parenting is just a way to filter the objects, you could code this to use a prefix for instance… it does not use drivers but a frame change event, that’s why you need to press play to see it working

problem here is to reset your objects scale :stuck_out_tongue: -it is destructive as you said- but you could just use Alt+S, or don’t run it until render time…? this is not the way usual scripts works in blender, but it could be adapted to your needs -and see you can now animate some properties-

edit: I guess using deltas for scaling plus a reset button would be more workflow friendly… easy fix
edit: did those changes, get file again, this is the way many of Atoms scripts work

ok now it’s up, dropbox wasn’t updating my files: scale.blend

A little old topic but may this help.

Without writing a script, there is an only driver way for proximity.
I’m using it on Shapekeys value.
Set a driver on the target field and in the driver properties, set the variable to compute on distance and select the two objects to deal with.
For now, this act has a negative proximity way, more far the objects are, more efficient is the effect.
To turn this on the right path, in the driver Modifier field, set the starting value on 1 (or the maximum effect is desired) and the coefficient must be lower than 1.
The goal here, is to have a positive curve going down.
More low is the coefficient, more the trigger object must be close.
On properties which can be negative live classic transforms, a solution is using custom properties, drived by this driver, and driving the transform property, and set to 0 as minimal value.

For custom properties :

Hope it’ll help.