Optimization suggestion for the evalMorphs...() functions

Issue #317 closed
Xin created an issue

Here I attached a script that shows how you can avoid linear searches like these :
return sum([pg.eval(rig) for pg in pb.DazLocProps if pg.index == idx])

I think this would make these functions faster. Although I’m pretty sure that CollectionProperty is not a dictionary so it could be even faster if we find a way to get an actual dictionary with constant time lookup. I also attached a faster alternative that has constant time access but takes more space depending on the maximum index number.

How many indices are possible? one for each dimension? or can there be more? if it’s only 3, why not create a group collection for each dimension and get rid of the index lookup altogether? like DazLocPropsX, DazLocPropsY, DazLocPropsZ. If the maximum index never exceeds a low number then the faster attached alternative should work well too.


And just so I don’t open another issue:

I left a comment in one of your commits telling you about the mathutils.interpolate.poly_3d_calc() from Blender to calculate barycentric weights for polygons (https://docs.blender.org/api/current/mathutils.interpolate.html)..) I repeat this here just in case. You call it like poly_3d_calc( [list of lists with the coordinates of triangle vertices], [coordinates of point] )and it returns the weights directly, in this case a list of size 3 since the polygon is a triangle. I don’t know if that will be faster than solving the linear equations in Numpy as you are doing right now, I haven’t tested it. But Blender implements this function in C with an optimized algorithm (it returns gibberish if the point is not inside the triangle, but you already know the point is in the triangle when this addon tries to find such weights).

Also, it might be useful to take a look at the other geometric functions Blender implements (in C): https://docs.blender.org/api/current/mathutils.geometry.html . They might come in handy in the future.

Comments (7)

  1. Thomas Larsson repo owner

    To get rid of the index update is a no-brainer, and has been implemented. Your other suggestion is more complicated, and I have not understood it in detail. Are you sure that it will work, not only when executed linearly, but after garbage collections and a Blender restart?

    Then it is not clear how much this matters. I tested with G8F with visemes only, saying Hasta la vista, baby. The same file runs at around 7.0 fps in Blender 2.83 and 10.2 fps in Blender 2.91. There is no significant difference between index lookup at runtime or not. What does make a difference is excluding the meshes from the scene. The file then runs at a solid 60 fps, and maybe more since Blender seems to have some ceiling there.

  2. Xin reporter

    Oh nice, that was fast. Thanks again.

    I have attached a commented version of the faster version which should clarify what it is trying to do. I think it might still be worth looking into if only to test it (the comments describe two advantages relative to the new current version). I also think it would make the code cleaner and would avoid repetition. Shouldn’t be a priority though, just check it whenever you have time.

    As for problems with Blender restarts, I don’t think it should have problems since everything is stored in Blender’s types (CollectionProperty and PropertyGroup). You can treat them in that regard the same way you treat those types in the addon right now (i.e. storing them as bones' properties).

    In terms of performance, I don’t expect these eval functions to ever come close to the armature in terms of cost, even with the oldest versions of them. But since these eval functions are executed a lot, trying to clean up their execution never hurts.

    The other script version I had attached before is no longer worth considering since you already implemented the separated version, so I will delete it to not clutter the attachments.

  3. Log in to comment