3

Alright, what I have is an array of cubes that I want to animate scaling vertically depending on proximity to an empty I'll move around the scene. Like this:

enter image description here

As I move the empty sphere around, the cubes will scale down to a flat almost plane or up to an elongated cube. What is the best way to do this? Shape keys and some sort of driver setup? I don't know how to approach this.

With first answer solution:

enter image description here

blue
  • 1,287
  • 1
  • 20
  • 40
  • 1
    Hello :). Are they supposed to move in real-time? Or is it meant to be a rendered animation? And what have you tried so far? :) – jachym michal Oct 30 '20 at 06:47

2 Answers2

6

Can do it using a "shrinkwrap" modifier driven by a "vertex weight proximity" modifier.

enter image description here

Each cube is a separate object like this with a vertex group (only the top vertices are attached to this group with a 0 value):

enter image description here

Each cube as the following modifiers:

enter image description here

  • "vertex weight proximity" that influences the vertex group values, using the empty proximity in "object" proximity (so that all vertices of the group will have the same weight)

  • "shrinkwrap" to a plane placed above in "project" mode along Z. Tune the "offset" value to vary the height influence

If you need to set the modifiers to several selected objects from the active one, use CtrlL then "modifiers".

lemon
  • 60,295
  • 3
  • 66
  • 136
  • Gorgeous thank you – blue Oct 30 '20 at 18:15
  • What can I do to increase the max height? When I change the 'Lowest' value they dont fall off in a linear manner, rather its too steep – blue Oct 30 '20 at 19:08
  • You can either move the plane up or decrease "offset" in the shrinkwrap modifier. – lemon Oct 30 '20 at 19:11
  • Increasing "lowest" of vertex weight. And for non linear, use the falloff type. Or you can lower the empty Z position (which is locked in the blend file I provided: so unlock it) – lemon Oct 30 '20 at 19:14
4

Make a unit, use self in drivers.

Recommend first making a driven unit.

For this example I have used a plane added a solidify modifier and driven the modifier thickness. Similarly could use a cube and drive object scale, after moving the origin to the bottom face of the cube

If we check use self in a driver it is the object being driven. In this case it is the solidify modifier, to get the plane instead, we use self.id_data (The blender ID object that owns the modifier.)

The matrix world of the empty is added as the variable mt Every object has a matrix world that contains the global transform of the object. (Similar to using the world location transform channel)

enter image description here

The driver expression

-max(3 - (self.id_data.matrix_world.translation.xy - mt.translation.xy).length , 0) * mt.translation.z / 3

This part of the expression

max(3 - (self.id_data.matrix_world.translation.xy - mt.translation.xy).length , 0)

confines the result to be within 3 units of the 2d xy circle around the plane origin. If the empty goes outside this it will have 0 influence.

It is then mulitiplied by the global z location of the empty, and divided by 3 to normalize it such that at best the solidified plane can touch the empty.

I've assumed for simplicity the plane will sit on the z=0 plane, (other wise would need to subtract the planes global z coordinate)

Finally it is negated since we are solidifying against the plane normal. (Flip in edit mode to use +ve)

enter image description here

Ok, if happy with out unit, add an array modifier to it, apply the modifier, in edit mode, P separate by loose parts. In object mode Object > Set Origin > Origin to Geometry to make each plane have its origin at its center, not that of the original unit.

enter image description here Quick example with 5 x 5 applied array mods

Extending.

enter image description here

Have arbitrarily chosen 3 as the XY radius of influence. Could add a custom property "radius" to the empty add another single property variable in the expression in place of 3. Can now also animate the radius of influence of the empty.

Another tip is if the expression gets too long to see in the driver field, try using the python console to check them out.

>>> mt = D.objects['Empty'].matrix_world
>>> self = C.object.modifiers['Solidify']
>>> (mt.translation.xy - self.id_data.matrix_world.translation.xy).length
1.9968496634438566

>>>

batFINGER
  • 84,216
  • 10
  • 108
  • 233