When initially coding this functionality, I was aware of the potential for
infinite recursion here, just not how frequently such setups are actually
used/created out in the wild (nodetree.ma_node -> ma -> ma.nodetree is all too
common, and often even with several levels of indirection!).
However, the best fix for these problems was not immediately clear. Alternatives
considered included...
1) checking for common recursive cases. This was the solution employed for one
of the early patches committed to try and get around this. However, it's all too
easy to defeat these measures (with all the possible combinations of indirection
node groups bring).
2) arbitrarily restricting recursion to only go down 2/3 levels? Has the risk
of missing some deeply chained/nested drivers, but at least we're guaranteed to
not get too bad. (Plus, who creates such setups anyway ;)
*3) using the generic LIB_DOIT flag (check for tagged items and not recurse down
there). Not as future-proof if some new code suddenly decides to start adding
these tags to materials along the way, but is easiest to add, and should be
flexible enough to catch most cases, since we only care that at some point those
drivers will be evaluated if they're attached to stuff we're interested in.
4) introducing a separate flag for Materials indicating they've been checked
already. Similar to 3) and solves the future-proofing, but this leads to...
5) why bother with remembering to clear flags before traversing for drivers to
evaluate, when they should be tagged for evaluation like everything else?
Downside - requires depsgraph refactor so that we can actually track the fact
that there are dependencies to/from the material datablock, and not just to the
object using said material. (i.e. Currently infeasible)
It was wrongly calculated bucket number per side in cases when some
of segments is filling the whole bounding box across some of dimension.
Solved by limiting buckets at least to 1 in such cases.
Made some minor optimization such as:
- Avoid using "%" operation in loops, replace with a check
for index "overflow".
- Use pre-computed values for scaling feather coordinates
to 0 .. 1 space.
This allowed to reach couple of milliseconds of boost.
Another change is to use higher number of buckets (up to 512).
This doesn't took significantly more memory (like uses only 10MB
of memory for average splines) and allows to have 30-50x boost
for average splines.
Use dynamically calculated number of buckets for this, to be
sure segments would fit two buckets.
Also fixed intersection detection in some cases when edge is
shared between two buckets -- it is possible that such edge
would cross third bucket and intersect edge from there.
Real fix would be to find a point which is definitely now on loop
to be collapsed, but that's for a bit later. This commit should
remove possible stoppers.
This implements simple function which collapses internal loops
caused by self-intersections into a singularity.
This loops can't be removed because rasterizer expects points
of feather be aligned with points from spline itself.
When OpenMP is enabled, memory allocation needs to be protected.
Fixes bug [#32111] Memory management regression from svn_46520
projects.blender.org/tracker/index.php?func=detail&aid=32111&group_id=9&atid=498