Revised mesh tension add-on

Hello, I’m trying to run the addon on a model that I just finished but it doesn’t work. I checked everything and I noticed that there is an error in the console whenever I try to play an animation.

Traceback (most recent call last):
  File "C:\Users\diogo\AppData\Roaming\Blender Foundation\Blender\3.0\scripts\addons\mesh_tension_1_5.py", line 267, in frame_post
    if ob.mode == 'OBJECT': tension_post(i,scene,dg)
  File "C:\Users\diogo\AppData\Roaming\Blender Foundation\Blender\3.0\scripts\addons\mesh_tension_1_5.py", line 193, in tension_post
    t = t/len(v.link_edges)
ZeroDivisionError: division by zero

if I try to edit the mesh, for example, separating a part of the mesh, it gives me another error

Array iterator out of range: (index 3319)
Traceback (most recent call last):
  File "C:\Users\diogo\AppData\Roaming\Blender Foundation\Blender\3.0\scripts\addons\mesh_tension_1_5.py", line 267, in frame_post
    if ob.mode == 'OBJECT': tension_post(i,scene,dg)
  File "C:\Users\diogo\AppData\Roaming\Blender Foundation\Blender\3.0\scripts\addons\mesh_tension_1_5.py", line 189, in tension_post
    e_def = bm.edges[e.index]
IndexError: bpy_prop_collection[index]: index 3319 out of range, size 1678

I also noticed that for some reason its deactivating every modifier I have except the armature

is there anyway I can fix this?

hmm. the first error looks like its dealing with not finding any linked edges on a particular vertex. this can be caused by loose verts, which you can usually find by going to select > select by trait > loose geometry.

also, the addon works by briefly disabling modifiers to compare how much they contribute to deformations. when it errors out, it can get stuck in the disabled modifier state. disabling the tension map checkbox should allow you to re-enable the modifiers.

anyway, i made a small update that should make it ignore floating verts in case you don’t want to delete them.

mesh_tension_1_5_1.py (14.3 KB)

3 Likes

Hi Steve,

Thanks for your work on this! Had a quick question about the frame/depsgraph pre handlers. While iterating over the objects that need tension computation, there is an execution path where the object list is refreshed and the function is immediately exited if any object is not found in the scene. Is this expected behavior? Because it seems like once this is done, other objects in the list won’t have their modifiers suspended, and I am not fully sure if there is another point at which the tension_pre function will be invoked once the handlers return. Thanks!

1 Like

i’ll have to take a peek at this, but that definitely sounds like the type of oversight i might make. i love open source for people being able to catch and problem solve issues like these though :smiley:

i’m so close to a massive update to my wiggle bones script too, but i’m also trying to work through some stubborn edge cases, so i should probably just put the code out there to get some other eyes on it :wink:

3 Likes

Haha no worries :slight_smile:

The more I look at it, I think it would be far simpler to simply call tension_pre and tension_post both in the post frame and depsgraph handlers unless I am missing something. Maybe you could force the list refresh there before doing so. It seems like the data relationships are anyways not finalized when frame_change_pre is invoked, so maybe the modifier suspension can be delayed until the post handlers are invoked. So what I am suggesting for the post handlers:

  1. Force list refresh
  2. Call tension_pre
  3. Call tension_post

Since the tension computation is done every frame anyways, this should work, and be a simpler setup to avoid different threads invoking the handlers for the render and viewport. But maybe that is already handled by the interface lock. Am I missing something?

its been a while since i coded this, but i believe the reasoning behind the pre handlers is because i’m doing some sneaky stuff with comparing deformed and undeformed mesh data without any generative modifiers (which change the vertex list removing the ability to make comparisons), and i take advantage of both updates to sample the needed states and still deliver a proper mesh result.

basically what happens is the following:

  • on “pre” i turn off the generative modifiers (as well as modifiers that the user tags as not wanting to contribute to tension)
  • blender does its usual internal data update between pre and post, giving a mesh that has the same vert order as the raw geo and only deformed by things the user wants to contribute to tension
  • on post, i compare the raw geo to this deformed mesh to determine the tension caused by these deformations and write them to the vertex colors or groups. then i turn the modifiers back on
  • blender does its usual internal update after post which regenerates the intended mesh with the full modifier stack

doing everything in post would mean i would need to call an additional forced update to get the deformed mesh, which slows performance, and essentially causes an evaluation of depsgraph pre- and post- all over again anyway.

but your initial catch i think is still correct: i run tension_pre on some objects but not others in a loop that i abandon if i encounter an object that the user may have deleted or renamed since the last update. the easiest solution is to validate the list first, refreshing it if necessary, and THEN run my tension code on a list that is now ensured to be up to date.

its not the greatest because its running through a loop twice, but that list is kept tight to the objects that have tension enabled, and only has to iterate through all scene objects in the case where the list has changed, which shouldn’t affect general performance.

mesh_tension_1_5_2.py (14.5 KB)

2 Likes

Haha that’s how I fixed it locally as well, except I just pre-emptively refreshed the list to prevent an internal second iteration over the objects; largely inconsequential I think. I did also fix a few other bugs I found and overhauled things to remove code duplication to make it easier to catch errors, along with separating controls for stretch / compression propagation. I’ll document the updates and share shortly.

1 Like

Hi Steve, I’ve shared the script with my refactor here: mesh-tension (github.com). I’ve of course credited you both in the README and the bl_info (do let me know if you have an issue with any of this nevertheless).

Here’s a brief set of changes:

  • Code refactor
    Remove duplicate code through reusable functions and module level constants. Remove multiple return paths. Add type annotations and Pep8 compliant documentation. Clean up code execution paths. Simplify data-structures replacing lists with dictionaries.

  • Tension Props Setup and Cleanup
    Explicitly add, and remove, tension properties on objects in response to enabling or disabling mesh tension. The addition didn’t work for me on 2.93 until the frame change handlers were triggered. Disabling tension also left the tension properties on the object, these are now cleaned up.

  • Independent stretch and compression propagation
    Control stretch and compression propagation through separate parameters to allow for interaction of the effects. For each, positive iterations denote dilation, negative denote erosion. The effects are additively blended for vertices that end up with both tension measures after tension propagation. Here’s a quick demo:

15 Likes

oh my gosh! this is awesome! plus i suspect there are a lot of new best practices that i can pick up from this. excited to take a look!

and absolutely thrilled to see it being modified and updated! :smiley:

4 Likes

Haha, my pleasure! Really glad to know you are excited :slight_smile:

3 Likes

Hi I just installed the new version of the addon to try it out but I noticed that just by having the addon installed I get instant crashes when I hit F12 on any scene.
Disabled the addon and everything works fine again.

Do you know why that could be happening?

Thanks for checking it out, could you give me some more information? Seems to be rendering fine for me. Does the system console log something? Or could you share a blend?

I tried with 10 different scenes and even a new file with just a cube and a camera, but all crashed immediately after hitting F12. I honestly don’t know how to narrow it down :sweat_smile:

How can I check the system console after the crash…?

I know render crashes can be caused by not having lock interface enabled. i’d tried to prompt users to enable lock interface in the tension panel, but maybe an edge case has crept in around that?

Tried with lock interface enabled as well and still have the crashes. I’m thinking that it’s maybe a conflict with another addon, so I’ll try on a fresh Blender install later tonight and see if the issue persists.

I think the following might help to further investigate:

  1. What Blender version are you on?
  2. Does 1.5.2 work fine for you?

The System Console can be accessed through ‘Window > Toggle System Console’ on Windows, or this might help if you’re on a Mac. You should see some warnings in there that I wanted to remove but couldn’t get to it last weekend, I’ll get around to a few TODOs I had left this weekend. But it shouldn’t crash on 2.93, at least not with a simple default cube. Thanks for the information nevertheless :slight_smile:
[Edit: I meant to check it before rendering to see if something has already gone wrong]

Pushed a few minor code changes for v1.5.4. Here is the changelog:

  • Use logger instead of warnings
  • Fix load_post to use bpy.context.scene since the arg is None.
  • Add checks before registering and unregistering handlers

I still can’t reproduce the crash on render, if there is some new information that helps reproduce it I can look into it again.

1 Like

Hey @calanir I finally found the source of my crashes, as I suspected it had nothing to do with this addon, it was a very old script I had installed as an addon to clean up meshes that was causing the issue.

After uninstalling that one everything works fine now with v1.5.4, thanks!

1 Like

Thanks for the update @julperado! Great to know! I just pushed 1.5.5 with a minor bug fix that was preventing the handlers from firing on frame change (had to flip a flag). You might want to update to that version, you can download the zip over on github :slight_smile:

5 Likes

Tried this addon, both versions. It looks like some meshes doesn’t working with it. If I create basic cube subdivide it then deform it with armature or simply deform it works ok. But in some cases it refuse to work on some of my existing meshes.

Here is blend example

tension map not working.blend (1.3 MB)