4
$\begingroup$

I have created a rigged low-poly character which I intend to use for a crowd simulation, i.e. the plan is to create multiple linked instances of it, each with its own animation cycle, and add them to a group for particle instancing.

Some of the animation is based on shape keys which I can control via the armature. I did this by assigning a driver to the shape keys which evaluates the transforms of non-deform bones in the parent rig.

However, my drivers currently reference the armature object directly via a transform channel variable. This of course works fine for a single character but any (linked) copies I create will keep being influenced by the bone from the original rig rather than the one associated with that copy.

I saw in the Blender 2.78 release notes that driver expressions can now use "self" to refer to the object being processed. Can this be used to resolve this problem and create "instance-friendly" drivers? If so, what would the expression have to look like? How do I get from "self" (which in this case would be my mesh object) to a bone in the parent armature?

Update: I have attached a very simple demo file to illustrate the issue. There is an armature controlling the shape key of the default cube via a driver. I then created a linked copy (Alt-D) of both armature and mesh. As you can see, posing the armature of the copy (right) does nothing while the armature of the original (left) controls both instances.

illustration of driver issue with instances

For completeness' sake here's the current driver setup from the sample file:

Driver setup

The question is how to rephrase that expression, probably using "self", so that the driver works properly on instances as well.

$\endgroup$
2
  • $\begingroup$ Can you add an image of one of your driver setups, or better still a small example file. I can certainly expand on how to use self in drivers, but not sure re shape_keys. $\endgroup$
    – batFINGER
    Jan 2, 2017 at 12:17
  • $\begingroup$ Have a look at crowdmaster also the tube project done some work on crowd simulation for cockroaches. $\endgroup$
    – sambler
    Jan 3, 2017 at 8:54

2 Answers 2

5
$\begingroup$

TL;DR: read below ruler for straight-forward answer - however, this will not give you per-instance shape-keys as I was hoping - this has nothing to do with the self-option, though.

Longer version:

I've tried doing some RTFM'ing but apparently the "Use self" option has not yet been documented in the official manual (nor anywhere else AFAICT).

By lots of trial and error I now figured out that "self" in my case is actually not referring to the mesh object (instance) as I expected, but rather to the ShapeKey object that the driver sits on. The problem then becomes that the shape key itself sits on top of the mesh data block (that is shared between the linked instances) rather than the object instance...

If I'm not mistaken this means that it is not possible to have linked duplicates (and by extension: particle instances) with distinct shape key values, regardless of the whole self in driver expressions issue.

Please feel free to correct me if I'm wrong on this.


However, to answer the question as I originally worded it in the title, if we take the Shape Keys out of the equation and put a driver on a property of the mesh instance itself (e.g. the Y translation) then we could use a driver expression like the following:

self.parent.pose.bones['Bone'].location.z

If you do not mind that instances cannot have distinct shape key values, here's an expression I came up with that will get you from the shape key to the bone of the parent armature:

bpy.data.objects[self.id_data.user.name].pose.bones["Bone"].location.z

These are still very early steps for me finding my way around the Blender object hierarchy, so I strongly suspect there is a better way to express this - especially without the bpy.data.objects[]-lookup - but it was the best I could come up with so far.

Note that this expression relies on the assumption that the mesh data block is named the same as the object that uses it, as is usually the case if you haven't manually changed it.

Also note that Blender will display a warning saying "Driver expression may not work correctly" and also a hint to "Use variables instead of bpy.data paths" - which IMO would defeat the point of using "self" as it would again force you to statically refer to an explicit object...

$\endgroup$
1
  • $\begingroup$ Too bad about no per-instance shape-keys. But your answer just saved me a lot of time, since I had the same hopeful idea. $\endgroup$
    – Mentalist
    Feb 26, 2021 at 4:39
2
$\begingroup$

I have a different example with the same problem: how to determine what "self" refers to in a driver script expression. In my case it is actually referring to an array modifier that I added to the object.

To explore "self", I used the following expression values:

0 if print(type(self)) else 1

And

0 if print(self.__dir__()) else 1

Open the system console window to see the printed output. For example, the first expression produces:

<class 'bpy.types.ArrayModifier'>

The second expression produces:

['offset_object', 'show_in_editmode', 'curve', 'type', 'show_render', 'constant_offset_displace', 'count', 'show_expanded', 'merge_threshold', 'use_apply_on_spline', 'use_relative_offset', 'show_on_cage', 'fit_length', 'start_cap', '__module__', 'rna_type', 'use_merge_vertices_cap', 'use_object_offset', 'name', '__slots__', 'relative_offset_displace', 'use_merge_vertices', 'end_cap', 'use_constant_offset', 'bl_rna', '__doc__', 'show_viewport', 'fit_type']

The API documentation confirms these are the properties of the ArrayModifier class.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .