Caused by 84c7684871.
Previously we could count on adding the attributes to the result mesh
not failing. Now, since the vertex group names are copied, they might
fail because a name would cause the attribute to already exist with a
float type on the point domain, which might not match the most
complex domain/type we'd use otherwise.
The fix is to only create attributes as vertex groups if the domain and
type combination from all the input meshes is correct.
Pull Request: https://projects.blender.org/blender/blender/pulls/132506
I had written a comment years ago mentioning that this behavior would be
preferrable, but I mistakenly assumed it was complicated to implement.
It turns out the sampled points subdividing a Bezier segment will have
symmetric "aligned" handle positions. Generally it's better to keep the
handles aligned where possible since the editing experience is a bit better.
In geometry nodes this shouldn't make an important difference because
the handle types are changed as necessary for in the set handle position
node.
Pull Request: https://projects.blender.org/blender/blender/pulls/132204
The realize instances code didn't have a way to use the existing
`#BuiltinAttributeProvider::default_value()`s to initialize attributes that
have to be created.
Now this writes default values of builtin attributes to the curve `attribute_fallbacks`.
Removes the need for the code to explicitly write the `resolution` and
`nurbs_weight`.
The other attributes that are written explicitly (like `radius`) don't have
builtin default values unfortunately. Ideally those would also just be provided
by the respective `BuiltinAttributeProvider`.
Pull Request: https://projects.blender.org/blender/blender/pulls/131799
Currently the realize instances code (which is also used by the join
geometry node) always creates generic attributes instead of vertex
groups. The expectation was that vertex groups would be replaced
by some form of generic attribute sooner rather than later. However,
it's clear that won't happen for some time, and this issue causes users
a lot of trouble. This commit preserves the vertex groups through the
operation. Any attribute name that was a vertex group on any of the
input meshes will become a vertex group in the result.
In the code this is a simple change because the attribute writer
abstraction allows writing to vertex groups as if the were just like
other contiguous arrays. In the future we could optimize the code
specifically for vertex groups.
This resolves the "bug" part of #99197 where the nodes remove vertex
groups. However, this doesn't change the fact that generating
primitive meshes in geometry nodes won't create vertex groups.
In general the property editor settings on the original mesh have
no effect on meshes created from scratch in geometry nodes.
Pull Request: https://projects.blender.org/blender/blender/pulls/131692
Grease Pencil v3 did not have crazyspace support yet. Without this sculpting on
deformed geometry (e.g. on top of an armature modifier) will yield incorrect
offsets because the tool writes to original data based on deformed positions.
This patch adds computation of local deformation matrices which are stored in
the `GeometryComponentEditData`. Those matrices are then used to convert local
deformation of the evaluated geometry back to a deformation of the original
geometry. All the relevant sculpt tools support the crazyspace correction now,
using the `compute_orig_delta` helper function.
Computing the deformation matrices should happen alongside modifier evaluation
for any deforming modifier. This has been implemented for the armature modifier,
others can be added.
A fallback implementation for curves could also be added for modifiers that
don't have an easy way to calculate local transformation. A "natural"
orientation for both the original and deformed positions is calculated, then the
difference yields deform matrices. For meshes the approach is to use the surface
normal and a stable tangent space. For curves the common local coordinate frame
based on parallel transport might be used.
Currently crazyspace correction for the _Clone_ tool does not work because of
#131496.
Pull Request: https://projects.blender.org/blender/blender/pulls/131499
Avoid rebuilding BVH trees when meshes are copied.
Similar to the other uses of the shared cache system,
this can arbitrarily improve performance when meshes
are copied but not deformed and BVH building is the
main bottleneck. In a simple test file I got a 6x speedup.
The amount of code is also reduced and the system is
much simpler overall-- built out of common threading
patterns like `SharedCache` with its double-checked lock.
RAII is used in a few places to simplify memory management
too.
The downside is storing more `SharedCache` items in the
mesh runtime struct. That has a slight cost when copying
a small mesh many times, but we have ideas to improve that
in the future anyway (#104327).
Pull Request: https://projects.blender.org/blender/blender/pulls/130865
I'm not quite sure what was wrong about the old implementation, but it was confusing
because it also depended on the user counts of drawings and other more high level
functions like `duplicate_layer`.
This fix just reimplements the functionality using the grease pencil API that we use in
more places in geometry nodes.
Pull Request: https://projects.blender.org/blender/blender/pulls/131291
Add a Mesh implementation of triangulation, which is currently just
implemented for BMesh. The main benefit of this is performance and
decreased memory usage. The benefit is especially large because the
node currently converts to BMesh, triangulates, and then converts back.
But the BMesh implementation is entirely single threaded, so it will
always be much slower.
The new implementation uses the principle of "never just process a
single element at a time" but it also tries to avoid processing _too_
many elements at once, to decrease the size of temporary buffers.
Practically that means the work is organized into chunks of selected
faces, but within each chunk, each task is done in a separate loop.
Arguably I went a bit far with some optimizations, and some of the
complexity isn't necessary, but I hope everything is clear anyway.
Unlike some other Mesh ports like the extrude node or the split edges
code, this generates a new mesh. I still go back and forth on that
aspect, but reusing the same mesh would have required reallocating
face attributes from scratch anyway. Implicit sharing is used to
avoid copying vertex attributes though.
The result mesh is reorganized a bit. Unselected face data comes first,
then selected triangles, then triangulated NGons, then triangulated
quads. This makes attribute interpolation and internal calculations
more efficient.
The "Minimum Vertices" socket is replaced with versioning. In the new
implementation it would have an impact on code complexity, and for a
builtin "atomic" node it makes more sense as part of the selection.
The performance difference depends on the number of CPU threads, the
number of attributes, and the selection size. As all of those numbers
go up, the benefit will grow. The "modes" also affect the performance,
obviously.
With a Ryzen 7950x, I tested performance in a few situations (in ms):
| | Selection | Before | After | Change |
| -------------------------- | --------- | ------ | ----- | ------ |
| 1.4 m quads (fixed) | 50% | 1533 | 15.9 | 96x |
| 10 m quads (shortest) | 100% | 9700 | 165.0 | 59x |
| 1 m 10-side Ngons (beauty) | 90% | 3785 | 115.9 | 33x |
| 1 m quads many attributes | 100% | 54600 | 332.3 | 164x |
In follow-up commits, I'll move other areas to use mesh triangulation
instead of BMesh. This is the last geometry node using BMesh besides
the Ico Sphere primitive.
Pull Request: https://projects.blender.org/blender/blender/pulls/112264
There is not really a good definition for what an "attribute kind". There are
many possibilities, it could include domain, type, geometry type, default value,
usage, ...
So it's better not to use this generic name. With the current name, one always
has to look at the definition again to be sure what it contains and what it does
not.
The name `AttributeDomainAndType` is way more explicit and does not have the
same problems. It's a bit longer, but that does not seem to be a problem in the
places where we use it.
Pull Request: https://projects.blender.org/blender/blender/pulls/130505
The length modifier was not handling 2 point curves correctly.
This change does two things:
1) Fix the crash by copying the original indices for 2 point curves into `dst_to_src_point`.
2) Fallback to `extend_curves_straight` for extending 2 point curves.
Pull Request: https://projects.blender.org/blender/blender/pulls/130122
Previously, some places used `curves.points_num() == 0` some other
places `curves.curves_num() == 0` to check if the geometry is empty.
Rather than having these two ways, add an `is_empty()` function
that replaces all these different checks.
Also update the curves geometry tests to use this function.
Pull Request: https://projects.blender.org/blender/blender/pulls/130168
In `execute_realize_grease_pencil_tasks` we create a new `GreasePencil`
but don't copy the parameters of (one of) the source grease pencils.
The fix adds `BKE_grease_pencil_copy_parameters` to copy the parameters
of the last src grease pencil.
Note: `BKE_grease_pencil_copy_parameters` copies the materials array. We
might want to remove this and always do the copy of this using a separate
function because some callers need their own way of copying them.
Pull Request: https://projects.blender.org/blender/blender/pulls/129977
Interpolating these attributes as integer values isn't meaningful or
helpful and is potentially problematic. So far I'd guess this is unlikely
to happen in practice which is why it probably hasn't been noticed yet.
Fixes part of #129691.
Pull Request: https://projects.blender.org/blender/blender/pulls/129809
Only retrieve a mutable copy of the attribute if we're actually able to change it.
If topology changes and there are no IDs, we can't mix the attribute and we
should avoid retrieving it in case it's shared. This is more of a hypothetical
change, I didn't actually observe a real world performance change.
Pull Request: https://projects.blender.org/blender/blender/pulls/129811
The 4x4 matrix type has a larger alignment requirement of 16 bytes
than the default, but it was stored in a generic vector of bytes. There
are a few solutions that reduce the memory reuse in this code path--
the chosen solution uses a custom allocator which always allocates
with an alignment that should be large enough for anything.
Generally I think this resampling loop could be rewritten to be a bit
simpler, avoiding these problems in the first place. Some performance
testing would show whether this "fancy" memory use between types
and loop structure is actually worth it. For now though, just correcting
the existing logic seems like the best choice.
Pull Request: https://projects.blender.org/blender/blender/pulls/129628
Unwrapping warned that a non 0/1 boolean value was being set.
Initialize all members of PVert since they would be accessed
when duplicating a PVert causing the uninitialized memory to be read.
This makes it so the stroke selection is taken into account by the
interpolation tool.
This does NOT use the selection _order_, just limits interpolation by
index to the selection. The result will be the subset of selected
strokes, excluding non-selected strokes, which is closer to the GPv2
behavior.
The `sample_curve_attribute` function was using the target curve index
for both the src and dst curves. This worked when all the curves are
interpolated, but with selections the dst curve is generally not the
same index as the src curve. The `from_curve_indices` array must be
passed along as well to retrieve the correct source index.
Pull Request: https://projects.blender.org/blender/blender/pulls/129096
The issue was that the `merge_layers` function assumed that the
`src_grease_pencil` always returns a drawing when calling
`get_eval_drawing` which can return `nullptr`.
The fix makes sure to check that the `src_drawing` exists.
Pull Request: https://projects.blender.org/blender/blender/pulls/129074
This fixes#127629. It's still a bit slower than it used to be when there are
lots of instances, but that fixes the main bottleneck that was introduced in
#116582. The issue was that we iterated over all attributes of all instances,
but it should only be necessary to iterate over the instances of each unique
geometry only once.
There is still quite some optimization potential in the Realize Instances code
for the case when realizing lots of instances. Especially the code to gather all
geometries that should be realized can still be made more efficient by reducing
redundant work and using multi-threading.
Pull Request: https://projects.blender.org/blender/blender/pulls/128699
This patch improves working with grease pencil layers in geometry nodes.
* Allow layers to have duplicate names in geometry nodes. In original data, unique names are enforced.
* This allows e.g. duplicating layers and then merging them by name in the end.
* It also resolves a big serial bottleneck when working with many grease pencil layers in geometry nodes. Enforcing unique names is inefficient.
* New `Merge Layers` node that can merge multiple layers by name or by a custom group id.
* Applying a grease pencil modifier now first merges all layers with the same name to ensure all names are unique.
Co-authored-by: Jacques Lucke <jacques@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/127873
The material handling on curves was not super strong yet because there was not a
lot of need for it. However, now with Grease Pencil it's much more likely that
material selections are used on curves.
The patch is larger than one might expect at first, because we have to pass more
information into the field context in many places, because the materials are
stored on `Curves` and not `CurvesGeometry`.
Related to #128109.
Pull Request: https://projects.blender.org/blender/blender/pulls/128182
This improve the API in multiple aspects:
* No need for an additional `lookup` call to get the current attribute. This
would internally iterate over all attributes again. This leads to O(n^2)
behavior. Note that there are still other reasons for O(n^2) behavior when
processing attributes (where n is the number of attributes).
* Remove the need to return a value from the iteration code to indicate that the
iteration should continue. This is now the default behavior. The iteration can
still be stopped by calling `iter.stop()`.
* Easier access to `is_builtin` property.
* Iterator callback only has a single parameter instead of two (of which one is
sometimes unused).
Pull Request: https://projects.blender.org/blender/blender/pulls/128128
This adds a new type of zone to Geometry Nodes that allows executing some nodes
for each element in a geometry.
## Features
* The `Selection` input allows iterating over a subset of elements on the set
domain.
* Fields passed into the input node are available as single values inside of the
zone.
* The input geometry can be split up into separate (completely independent)
geometries for each element (on all domains except face corner).
* New attributes can be created on the input geometry by outputting a single
value from each iteration.
* New geometries can be generated in each iteration.
* All of these geometries are joined to form the final output.
* Attributes from the input geometry are propagated to the output
geometries.
## Evaluation
The evaluation strategy is similar to the one used for repeat zones. Namely, it
dynamically builds a `lazy_function::Graph` once it knows how many iterations
are necessary. It contains a separate node for each iteration. The inputs for
each iteration are hardcoded into the graph. The outputs of each iteration a
passed to a separate lazy-function that reduces all the values down to the final
outputs. This final output can have a huge number of inputs and that is not
ideal for multi-threading yet, but that can still be improved in the future.
## Performance
There is a non-neglilible amount of overhead for each iteration. The overhead is
way larger than the per-element overhead when just doing field evaluation.
Therefore, normal field evaluation should be preferred when possible. That can
partially still be optimized if there is only some number crunching going on in
the zone but that optimization is not implemented yet.
However, processing many small geometries (e.g. each hair of a character
separately) will likely **always be slower** than working on fewer larger
geoemtries. The additional flexibility you get by processing each element
separately comes at the cost that Blender can't optimize the operation as well.
For node groups that need to handle lots of geometry elements, we recommend
trying to design the node setup so that iteration over tiny sub-geometries is
not required.
An opposite point is true as well though. It can be faster to process more
medium sized geometries in parallel than fewer very large geometries because of
more multi-threading opportunities. The exact threshold between tiny, medium and
large geometries depends on a lot of factors though.
Overall, this initial version of the new zone does not implement all
optimization opportunities yet, but the points mentioned above will still hold
true later.
Pull Request: https://projects.blender.org/blender/blender/pulls/127331
Integrate an existing implementation of the SLIM unwrapping algorithm
into Blender. More info about SLIM here:
https://igl.ethz.ch/projects/slim/
This commit is based on the integration code written by Aurel Gruber
for Blender 2.7x (unfinished and never merged with the main branch).
This commit is based on Aurel's code, rebased and further improved.
Details:
- Unwrap has been moved into a sub-menu,
slim unwrapping is exposed as: "Minimum Stretch".
- Live unwrap with SLIM refines the solutions using a timer.
- When using SLIM there are options to:
- Set the number of iterations.
- Weight the influence using vertex weights.
- SLIM can be disabled using the `WITH_UV_SLIM` build option.
Co-authored-by: Aurel Gruber <aurel.gruber@infix.ch>
Ref !114545