Monday, February 23, 2026

Performance Boost

I recently learned about the foreach_get and foreach_set functions that makes access to Blender arrays much faster. The latest versions of the Daz Importer (5.1.0) use these functions to loop over vertices, shapekeys, polygons etc. This had led to a quite nice performance boost.

A a test case I import a Genesis 9 Female character with eyebrows card style 06 and dForce Pixie cut hair. All global settings were set to the factory values (except the DAZ root paths), and the Genesis 9 preset was used for Easy import. I imported the character twice and hit ctrl-Z inbetween. Here are the results.

Blender 4.4:
addon 5.1:    39.398 seconds    37.200 seconds
addon 5.0:    75.642 seconds    75.424 seconds
addon 4.4:    70.669 seconds    70.991 seconds

Blender 5.0:
addon 5.1:    34.721 seconds    35.120 seconds
addon 5.0:    85.280 seconds    77.256 seconds

Blender 5.1 beta:
addon 5.1:    60.276 seconds    60.069 seconds

Notes:

1. The addon is backward but not forward compatible. Newer versions of the addon can be used in old blender versions, but not vice versa.

2. Version 5.1 (development version) of the addon is significantly faster than version 5.0.

3. Blender 5.1 beta is slower than previous Blender versions. This probably only reflects that a beta is not as optimized as a proper release.

The old method of loading shapekeys used to loop over the nonzero shapekeys in Blender, whereas the new method uses foreach_set to copy a numpy array in one sweep. However, for small morphs like the FACS, i.e. morphs that a localized to a small part of the full mesh, the old method may actually be faster. A python loop is much slower than the builtin method, but it only needs to access the nonzero shapekeys. For example, for the first Genesis 9 FACS morph, facs_bs_BrowDownLeft:
Mesh size:       25182
Morph size:     661
In that case the slow python loop is actually faster than using numpy.

For this reason, there is a new global setting, "Numpy Morph Fraction". The old method is used if the shapekey size (i.e. the number of nonzero deltas) is smaller than this fraction, otherwise the new method is used.


Tuesday, January 6, 2026

Active Morphs Panel

In the previous post I described how the Head and FACS morphs can be organized in subpanels; this is now the default behaviour. Another change is that the currently active morphs are collected in a separate panel, in the same way as in DAZ Studio. 

Here we have several active morphs, both head morphs (brows, mouth, tongue, visemes), an expression, and even some custom morphs like elf ears. All active morphs are present in a single place. 

The data structures needed to display the active morphs are built when the morphs are imported. If you have an old character, or if the active morphs have been corrupted for some reason, you can rebuild this data structure with the "Update Active Morphs" button at the top of the Morphs panel.

The existence of the "Active Morphs" panel is also governed by the global setting "Face Morphs Subpanels". If that option is disabled, the "Update Active Morphs" button is replaced by the old "Show Used Morphs Only" checkbox. The Morphs panel now looks like it did before, where the active morphs are spread out over the various panels.
One thing that I found annoying with the legacy behaviour was that a morphs disappeared when you drag the slider to zero, and "Show Active Morphs Only" had to be disabled to turn the morph back on. With the new setup a zero morph disappears from the "Active Morphs" panel, but the slider is still available in its native location.