Refactor to prepare for slotted action support to the evaluation of
quaternion F-Curves.
Since slotted Actions store F-Curves in an array, you cannot iterate over
them any more via the `ListBase` pointer `fcurve.next`. Quaternion
evaluation code has been refactored to work on a span of F-Curves instead
of just getting the first one.
For now, slotted Actions just evaluate their first slot only. A future
commit will add a slot handle parameter to evaluate the correct slot.
Implements the legacy `weight_data_add` button for GPv3.
Note: This PR properly accounts for the bone's transformation when applying so that the stroke does not appear to teleport after drawing, unlike the legacy system.
Pull Request: https://projects.blender.org/blender/blender/pulls/119302
Updating the node bounds just after deforming the vertices in the
node is faster because the position data is still fresh in CPU caches.
Updating it later on means all the other nodes have been processed
in the meantime which will evict that position data from the caches.
This results in a 1.11x improvement in the brush benchmark timing,
from 0.495s to 0.438s on a Ryzen 7950x (best of 5 runs).
As part of the change, the update tagging has completely moved
to each brush implementation. This continues the process of
making each brush more independent.
Part of #118145.
Pull Request: https://projects.blender.org/blender/blender/pulls/127536
The normals were not allocated before the brush code starts, which is
necessary to store the initial normals in the undo step, among other
things. Previously normals were calculated as part of building the PBVH.
That doesn't make sense anymore because that process shouldn't change
the mesh. For now just add the recalculation in a code path called by
`BKE_sculpt_update_object_for_edit`, called at the beginning of each
stroke, and other places.
I've done this a few times and would have benefited from a utility
function for it, apparently it's done in a few more places too. The
utilities aren't multithreaded for now, it doesn't seem important
and often multithreading happens at a different level of the call
stack anyway.
Pull Request: https://projects.blender.org/blender/blender/pulls/127517
Implements setting the armature parent and generating
vertex groups for the bones in the armature.
Note: This does not implement the `Envelope` or `Automatic Weights` options.
Pull Request: https://projects.blender.org/blender/blender/pulls/127515
Current the automasking code stores temporary data as geometry
attributes (except for multires where that doesn't work) in order to
persist the cached factors for cavity and occlusion accross multiple
strokes. However, the benefits of this aren't clear, compared to
improving the performance of these calculations. It's also the last
usage of the sculpt attribute API which we plan to remove. The system
is also hard to understand, to make a more solid cache of automasking
values it would be better to start from scratch.
This commit removes the sculpt attribute API and the automasking stroke
ID system, and moves the cached factors to be cached per stroke rather
than more permanently.
Pull Request: https://projects.blender.org/blender/blender/pulls/127470
Joining many geometries was O(n^2) because of deduplication of the same
components was not done using a map. My test file that generates 1000
stars in a repeat zone got 10x faster, but it's possible to create a file for any
speedup.
Grease Pencil armature deformation has to use the correct
`vertex_group_names` list from the `Curves` (i.e. drawings) rather than
the names from its parent `GreasePencil` data block.
The ancient armature deformation code used a `defbase` list (`ListBase`
of type `bDeformGroup`) from the object via `BKE_id_defgroup_list_get`.
This function does not have enough information to determine the correct
vertex groups for GPv3, and it's use inside supposedly generic code is
highly questionable.
This patch removes the `defbase` lookup inside
`armature_deform_coords_impl` and instead passes an explicit list of
vertex group names to be used for resolving indices. We already have
context in every place this is called to determine the correct vertex
groups, without having to make assumptions down the line based on just
the object type.
Pull Request: https://projects.blender.org/blender/blender/pulls/127509
Properly track Action and Slot assignment when entering/exiting NLA
tweak mode.
This doesn't properly sync the length of the NLA strip when exiting
tweak mode. This and more NLA work is tracked at #127489.
Pull Request: https://projects.blender.org/blender/blender/pulls/127498
For an NLA strip to use a slotted Action, it needs to specify which slot
to use in that action. This is now handled by two new properties on the
strip in DNA & RNA: `action_slot_handle` and `action_slot_name`.
These serve the same purpose as their counterparts on the `AnimData`
struct.
Note that this commit does NOT add NLA evaluation support for slotted
Actions. It merely allows assigning them. Evaluation, tweak mode
support, etc. will be implemented in future commits.
Pull Request: https://projects.blender.org/blender/blender/pulls/127359
Prior to 0df133559c, the `active_vert_` property was only ever
invalidated if the entire `SculptSession` was refreshed, even if the
cursor moved off of the mesh or if the underlying mesh type changed.
The Sculpt Expand operator was dependent on this value not being cleared
to still behave in a reasonable way from a user perspective
This commit introduces a new variable, `last_active_vert_` and
corresponding accessor methods to `SculptSession` to specifically fix
this usecase. When the active vert is cleared, if it had a valid value,
we store it in the new `last_active_vert_` variable.
Pull Request: https://projects.blender.org/blender/blender/pulls/127433
For `SubdivCCG`, replace the dynamic array-of-struct data with separate
arrays for positions, normals, and masks. This decreases memory
bandwidth requirements for loops that only access one of these arrays.
It also significantly simplifies data access, making it more similar
to mesh data where it can just be accessed with indices.
In a simple test this change speeds up the multires sculpt brush
benchmark by 32%. It also slightly reduced BVH build time by about 12%.
In practice this means completely replacing usage of `CCGElem` for
`SubdivCCG`. The struct is still used in the older subsurf baking code
though. Removing that is a much trickier task that doesn't have short
term benefits.
Part of #118145.
Pull Request: https://projects.blender.org/blender/blender/pulls/127262
Structure the multires grids PBVH build to be similar to meshes,
splitting face indices into groups instead of grid indices. This
removes one step of indexing, decreases the amount of temporary
data, and allows sharing the majority of the implementation with
the mesh BVH build.
In a test file with 4 million faces at multires level 1, this reduced
BVH build time from 149 to 70 ms. The improvement will be
significantly lower for higher subdivision levels.
Pull Request: https://projects.blender.org/blender/blender/pulls/127429
Fix a crash that happens when drawing Action groups in the dope sheet, when
Blender is built without experimental features (hence without Action
slots) and it has loaded a blend file with slotted Actions.
Basically a pointer needs to be set to `nullptr` when reading such a file,
as it ensures that the rest of the code treats the group as "from a legacy
Action".
Pull Request: https://projects.blender.org/blender/blender/pulls/127339
Use `std::partition` instead of implementing something similar
ourselves. This is much easier to understand, and it's also much
faster and requires less memory during the build.
I observed a change in the runtime building a 16 million face
BVH from 492 to 389 ms, a 1.27x improvement (with a Ryzen
7950x).
`std::partition` is not multithreaded. I expect there would be
some improvement from multithreading this, at least for the
first few splits.
Currently this only applies to Mesh sculpting.
Pull Request: https://projects.blender.org/blender/blender/pulls/127332
Each time the face bounds are used after they're initially computed, we
recompute the center of the bounds. We only use the actual bounds to
calculate the bounds of each node to decide how it should be split.
This commit changes to store the bounds centers instead, and just use
the full bounds as a type for the parallel reduction.
In a test with a 16 million face grid on a Ryzen 7840U, I observed a
1.28x decrease in BVH build time, from 1072 to 836 ms.
I didn't apply a similar change to multires grids BVH building because
it's not clear the same bottleneck exists due to the lower ratio of
"primitives" (grids) to final subdivided vertices.
Part of #118145.
In the future we want to move the ownership of the BVH tree to the
original mesh rather than `SculptSession`, in order to persist it
across some more general non-topology changing operations like
node tools. The first step of that change is replacing all places
that used `SculptSession::pbvh` for access with a function.
Add `.faces()`, `.verts()`,`.all_verts()`, and `.grids()` functions to nodes.
Don't change BMesh data access yet. More complex const correctness
makes that situation more difficult.
Pull Request: https://projects.blender.org/blender/blender/pulls/127201
Currently each sculpt BVH node stores the indices of its triangles.
It also stores triangles of vertex indices local to the node, and also
potentially the indices of the face corners in the node.
The problem with this is that the leaf nodes store plenty of redundant
information. The triangles in each face aren't split up between multiple
nodes, so storing triangle instead of face indices is unnecesssary. For
the local vertex triangles, there is also duplicate information-- twice
the number of indices as necessary for quad meshes. We also often need
a node's faces, which is currently done with a triangle to face map
using 4 bytes per triangle.
This "double storage" results in extra processing too. For example,
during BVH builds we need to combine twice the number of "Bounds"
objects for a quad mesh. And we have to recalculate a node's face
indices every time we want them.
This commit replaces the PBVH triangle indices with face indices, and
replaces the local vertex triangles array by using a `VectorSet` to store
each node's vertex indices. This results in significant performance and
memory usage improvements.
| | Before | After | Improvement |
| ----------------- | -------- | -------- | ----------- |
| BVH build time | 1.29 s | 0.552 s | 2.3x |
| Brush stroke time | 3.57 s | 2.52 s | 1.4x |
| Memory usage | 4.14 GiB | 3.66 GiB | 1.3x |
All testing is done with a 16 million vertex grid and a Ryzen 7950x.
My guess is that the brush stroke time is improved by the added sorting
of node vertex indices, and by the overall increase in memory bandwidth
availability for mesh data. Personally I'm pleasantly surprised by the
whole improvement, since I usually try to avoid hash table data
structures for this sort of use case. But a lookup into this set ends up
just being a boolean and with an array lookup, so it's quite cheap.
Pull Request: https://projects.blender.org/blender/blender/pulls/127162
This introduces the concept of an #AttributeFilter. It's used to tell a geometry
algorithm which attributes it should process/propagate and which can be ignored.
We already had something similar before named
`AnonymousAttributePropagationInfo`. However, as the name implies, this was
specific to anonymous attributes. This had some downsides:
* A lot of code had to be aware of the concept of anonymous attributes even if
it did nothing special with anonymous attributes.
* For non-anonymous attributes we often had a separate `Set<std::string> skip`
parameter. It's not nice to have to pass two kinds of filters around and to
have to construct a `Set<std::string>` in many cases.
`AttributeFilter` solves both of these downsides.
Technically, `AttributeFilter` could also just be a `FunctionRef<bool(StringRef
attribute_name)>`, but that also has some issues:
* The `bool` return value is often ambiguous, i.e. it's not clear if it means
that the attribute should be processed or not. Using an enum works better.
* Passing function refs around and combining them works, but can very easily
lead to dangling references.
* The default value of a `FunctionRef` is "empty", i.e. it can't be called. It's
generally more nice to not have a special case for the default value. Now the
default `AttributeFilter` propagates all attributes without any extra handling
on the call-site.
Pull Request: https://projects.blender.org/blender/blender/pulls/127155
Move the functions
* `BKE_pose_apply_action_selected_bones`
* `BKE_pose_apply_action_all_bones`
* and `BKE_pose_apply_action_blend`
out of the blender kernel and into animrig.
This will allow solving #126969 without having to include
animrig code in the blender kernel.
Pull Request: https://projects.blender.org/blender/blender/pulls/126978
Between 2.93 & 3.2 a regression was introduced where evaluated
meshes from the modifier stack would always have their deformed_only
value set to false.
Resolve by enabling for meshes returned by
BKE_mesh_wrapper_from_editmesh and ensure the value is kept when the
modifier duplicates the cage mesh.
Resolves#123138.