Previously, `VArrayImpl` had a `materialize` and `materialize_to_uninitialized`
function. Now both are merged into one with an additional `bool
dst_is_uninitialized` parameter. The same is done for the
`materialize_compressed` method as all as `GVArrayImpl`.
While this kind of merging is typically not ideal, it reduces the binary size by
~200kb while being basically free performance wise. The cost of this predictable
boolean check is expected to be negligible even if only very few indices are
materialized. Additionally, in most cases, this parameter does not even have to
be checked, because for trivial types it does not matter if the destination
array is already initialized or not when overwriting it.
It saves this much memory, because there are quite a few implementations being
generated with e.g. `VArray::from_func` and a lot of code was duplicated for
each instantiation.
This changes only the actual `(G)VArrayImpl`, but not the `VArray` and `GVArray`
API which is typically used to work with virtual arrays.
Pull Request: https://projects.blender.org/blender/blender/pulls/145144
When manually setting a group's vertex weight, auto-normalization would
fail in some circumstances, such as when all other groups are locked.
The root cause of this issue was our approach for ensuring that the
weight specified by the user remained as-is when possible during
normalization. Rather than "when possible", it erroneously *always*
ensured the weight stayed as-is even when that made normalization
impossible. It came down to this:
1. Normalization is done as a post process, with no knowledge of what
changes were just made to the weights.
2. In order to (try to) make up for that and ensure that the just-set
weight remains as the user specified, the active group was
temporarily locked during normalization, which could prevent
normalization in some cases.
This PR fixes the issue by introducing a new internal-only concept of
"soft locked" vertex groups to the normalization functions, intended to
be used in exactly these cases where there are weights that have just
been set and we want to avoid altering them when possible. Soft-locked
groups are left untouched whenever normalization is achievable without
touching them, but are still modified if normalization can't be achieved
otherwise.
This has been implemented by introducing a new bool array alongside the
"locked" bool array in the core normalization functions. Although all
uses in this PR only ever specify a single group as "soft locked", using
a bool array will make it easy to use this concept in other weight
painting tools in the future, which may modify more than one group at
once.
Pull Request: https://projects.blender.org/blender/blender/pulls/141045
- Add code documentation.
- Use Span and references rather than pointers everywhere.
- Move all core normalization logic into
`BKE_defvert_normalize_lock_map()`, and have the other variants call
that. This keeps all the logic in one place, which will help make
future changes easier since they only need to be made in one place.
- Add unit tests for `BKE_defvert_normalize_lock_map()`.
- Refactor `vgroup_normalize_all()` to be clearer and avoid an
unnecessary `goto`.
- Make both `vgroup_normalize_all()` and `paint_weight_gradient_exec()`
only call into a single core vertex normalization function, rather
than branching into one of many.
No functional change intended.
* Move colorband and theme DNA to own headers
* Move some anim, curve, modifier and space enums to new headers
* Move data transfer enums to DNA
* Duplicate imbuf proxy and GPU backend enums
For a few reasons:
* Reduce number of includes in DNA headers
* Don't define enums used in DNA outside of DNA
* Move theme settings to separate header for userdef_default_theme.c
* Prepare for using default initializers in DNA headers. (#134531)
Pull Request: https://projects.blender.org/blender/blender/pulls/138831
The main issue of 'type-less' standard C allocations is that there is no check on
allocated type possible.
This is a serious source of annoyance (and crashes) when making some
low-level structs non-trivial, as tracking down all usages of these
structs in higher-level other structs and their allocation is... really
painful.
MEM_[cm]allocN<T> templates on the other hand do check that the
given type is trivial, at build time (static assert), which makes such issue...
trivial to catch.
NOTE: New code should strive to use MEM_new (i.e. allocation and
construction) as much as possible, even for trivial PoD types.
Pull Request: https://projects.blender.org/blender/blender/pulls/136134
The general idea is to keep the 'old', C-style MEM_callocN signature, and slowly
replace most of its usages with the new, C++-style type-safer template version.
* `MEM_cnew<T>` allocation version is renamed to `MEM_callocN<T>`.
* `MEM_cnew_array<T>` allocation version is renamed to `MEM_calloc_arrayN<T>`.
* `MEM_cnew<T>` duplicate version is renamed to `MEM_dupallocN<T>`.
Similar templates type-safe version of `MEM_mallocN` will be added soon
as well.
Following discussions in !134452.
NOTE: For now static type checking in `MEM_callocN` and related are slightly
different for Windows MSVC. This compiler seems to consider structs using the
`DNA_DEFINE_CXX_METHODS` macro as non-trivial (likely because their default
copy constructors are deleted). So using checks on trivially
constructible/destructible instead on this compiler/system.
Pull Request: https://projects.blender.org/blender/blender/pulls/134771
Same was true for SimpleDeform.
Invert vertex group influence should only have an effect if there is a
group specified.
Shrinkwrap always uses a weight (gets weights via
`BKE_defvert_array_find_weight_safe` -- which gets full weight for no
group specified, rightfully so), if this gets inverted, we get no
influence at all.
Now move the inverting of the weights to `BKE_defvert_array_find_weight_safe`,
adjust the other callers accordingly (Bevel also does not need to check for a valid
vertexgroup beforehand).
Pull Request: https://projects.blender.org/blender/blender/pulls/121625
Previously, there was a `StringRef.copy` method which would copy the string into
the given buffer. However, it was not defined for the case when the buffer was
too small. It moved the responsibility of making sure the buffer is large enough
to the caller.
Unfortunately, in practice that easily hides bugs in builds without asserts
which don't come up in testing much. Now, the method is replaced with
`StringRef.copy_utf8_truncated` which has much more well defined semantics and
also makes sure that the string remains valid utf-8.
This also renames `unsafe_copy` to `copy_unsafe` to make the naming more similar
to `copy_utf8_truncated`.
Pull Request: https://projects.blender.org/blender/blender/pulls/133677
GPv3 stores the vertex group inside `CurvesGeometry`.
When the object level vertex group name is changed, we have to loop over
the vertex group list of each drawing. If a matching name is
found, copy the new name to the vertex group in `CurvesGeometry`. A separate
function is created to handle this: `BKE_grease_pencil_vgroup_name_update`.
Pull Request: https://projects.blender.org/blender/blender/pulls/129038
Fixes incorrect usage of StringRef in new grease pencil code, where
`.data()` was passed as a null terminated C string. Removes the now
unnecessary `std::string` creation that attribute accessors used to
fix that problem.
Pull Request: https://projects.blender.org/blender/blender/pulls/128298
This makes the read and write API functions match more closely, and adds
asserts to check that the data size is as expected.
There are still a few places remaining that use BLO_read_data_address
and similar generic functions, these should eventually be replaced as well.
Pull Request: https://projects.blender.org/blender/blender/pulls/120994
Adds vertex groups and basic operator support to the `GreasePencil` data
block.
Vertex groups in the `GreasePencil` ID are used as the source of truth
for vertex groups names and ordering in the UI. Individual drawings also
have vertex group lists, but they should not be modified directly by
users or the API. The main purpose of storing vertex group names in in a
drawing's `CurveGeometry` is to make it self-contained, so that vertex
weights can be associated with names without requiring the
`GreasePencil` parent data.
Vertex group operators are implemented generically for some ID types.
Grease Pencil needs its own handling in these operators. After
manipulating `vertex_group_names` the `validate_drawing_vertex_groups`
utility function should be called to ensure that drawings only contain a
true subset of the `GreasePencil` data block.
Operators for assigning/removing/selecting/deselecting vertices are also
implemented here. To avoid putting grease pencil logic into the generic
`object_deform.cc` file a number of utility functions have been added in
`BKE_grease_pencil_vgroup.hh`.
Fixes#117337
Pull Request: https://projects.blender.org/blender/blender/pulls/117476
Add separate functions that deal with the vertex domain and copy vertex
groups without using the attribute API which has a large overhead when
abstracting the access of many vertex groups.
In a 1m vertex mesh with 20 vertex groups, I observed an improvement
in the node's runtime from 399 ms to 64 ms.
Also resolves#117553. That was an error when adding weight data to a
mesh without any weight data would invalidate custom data layers. That
is solved more simply now by just doing nothing in that case.
"mesh" reads much better than "me" since "me" is a different word.
There's no reason to avoid using two more characters here. Replacing
all of these at once is better than encountering it repeatedly and
doing the same change bit by bit.
This PR adds vertex groups to `CurvesGeometry` as well as an attribute read/write accessor.
This is also in preparation for GPv3. Since the goal is to have full compatibility with the current grease pencil features, vertex groups need to be supported.
Grease Pencil allows filtering by vertex group for modifiers.To support this, it also makes sense to have read/write access for vertex groups in the attributes API.
In the future, vertex groups should be just another custom attribute on meshes/curves/grease pencil. There are some more issues to be solved before that can happen. This step gets us a bit closer since the vertex weight data is stored in `CustomData`.
Pull Request: https://projects.blender.org/blender/blender/pulls/106944
This was discussed in #112022 and on devtalk:
https://devtalk.blender.org/t/vertex-groups-generic-attributes-and-name-clashing/31073
While vertex groups with the same name as attributes should be avoided, since
it can cause ambiguities when using attributes, it's something we can handle
gracefully for now. Enforcing unique names for vertex groups resulted in breaking
other functionality under some circumstances.
This effectively reverts 12ef20990b, except for
the bug fix in `BKE_id_attribute_new`.
#112891 adds a warning to avoid make users aware of duplicate names so that they
can be avoided in practice.
Pull Request: https://projects.blender.org/blender/blender/pulls/112889
When using a pointer offset that may be out-of-bounds the integer
must not truncate the offset.
Issue raised by !111193.
Co-authored-by: Loren Osborn <linux_dr>
After 12ef20990b, attributes and vertex group names were checked
simultaneously to fix the name collision. But this results in crash when
new attribute is added to curve object (it searches for vertex group
list). To avoid the crash, check for supported id types in new function
`BKE_id_supports_vertex_groups`.
Pull Request: https://projects.blender.org/blender/blender/pulls/111036
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
These name collisions should be avoided with attributes, all sorts of
issues can arise from those. We already warned in the attributes
(but not the vertex groups) list if those were found.
Previously, creating a vertex group with the same name as an already
existing attribute would allow this (and give said warning), and creating
an attribute with the same name as an already existing vertex group
would silently fail (as in: not return a layer) -- and then due to an oversight
in 101d04f41f (which assumed a valid layer would always be returned
by `BKE_id_attribute_new`) would even crash.
Now name collisions between vertex groups and attributes are avoided,
unique names will be found across attributes and vertex groups if either
`BKE_id_attribute_calc_unique_name` or `BKE_object_defgroup_unique_name`
is called.
This is done by unifying the checks and callbacks for both into a single.
Pull Request: https://projects.blender.org/blender/blender/pulls/109910
Implements part of #101689.
The "poly" name was chosen to distinguish the `MLoop` + `MPoly`
combination from the `MFace` struct it replaced. Those two structures
persisted together for a long time, but nowadays `MPoly` is gone, and
`MFace` is only used in some legacy code like the particle system.
To avoid unnecessarily using a different term, increase consistency
with the UI and with BMesh, and generally make code a bit easier to
read, this commit replaces the `poly` term with `poly`. Most variables
that use the term are renamed too. `Mesh.totface` and `Mesh.fdata` now
have a `_legacy` suffix to reduce confusion. In a next step, `pdata`
can be renamed to `face_data` as well.
Pull Request: https://projects.blender.org/blender/blender/pulls/109819
A lot of files were missing copyright field in the header and
the Blender Foundation contributed to them in a sense of bug
fixing and general maintenance.
This change makes it explicit that those files are at least
partially copyrighted by the Blender Foundation.
Note that this does not make it so the Blender Foundation is
the only holder of the copyright in those files, and developers
who do not have a signed contract with the foundation still
hold the copyright as well.
Another aspect of this change is using SPDX format for the
header. We already used it for the license specification,
and now we state it for the copyright as well, following the
FAQ:
https://reuse.software/faq/
Implements #95966, as the final step of #95965.
This commit changes the storage of mesh edge vertex indices from the
`MEdge` type to the generic `int2` attribute type. This follows the
general design for geometry and the attribute system, where the data
storage type and the usage semantics are separated.
The main benefit of the change is reduced memory usage-- the
requirements of storing mesh edges is reduced by 1/3. For example,
this saves 8MB on a 1 million vertex grid. This also gives performance
benefits to any memory-bound mesh processing algorithm that uses edges.
Another benefit is that all of the edge's vertex indices are
contiguous. In a few cases, it's helpful to process all of them as
`Span<int>` rather than `Span<int2>`. Similarly, the type is more
likely to match a generic format used by a library, or code that
shouldn't know about specific Blender `Mesh` types.
Various Notes:
- The `.edge_verts` name is used to reflect a mapping between domains,
similar to `.corner_verts`, etc. The period means that it the data
shouldn't change arbitrarily by the user or procedural operations.
- `edge[0]` is now used instead of `edge.v1`
- Signed integers are used instead of unsigned to reduce the mixing
of signed-ness, which can be error prone.
- All of the previously used core mesh data types (`MVert`, `MEdge`,
`MLoop`, `MPoly` are now deprecated. Only generic types are used).
- The `vec2i` DNA type is used in the few C files where necessary.
Pull Request: https://projects.blender.org/blender/blender/pulls/106638
Implements #95967.
Currently the `MPoly` struct is 12 bytes, and stores the index of a
face's first corner and the number of corners/verts/edges. Polygons
and corners are always created in order by Blender, meaning each
face's corners will be after the previous face's corners. We can take
advantage of this fact and eliminate the redundancy in mesh face
storage by only storing a single integer corner offset for each face.
The size of the face is then encoded by the offset of the next face.
The size of a single integer is 4 bytes, so this reduces memory
usage by 3 times.
The same method is used for `CurvesGeometry`, so Blender already has
an abstraction to simplify using these offsets called `OffsetIndices`.
This class is used to easily retrieve a range of corner indices for
each face. This also gives the opportunity for sharing some logic with
curves.
Another benefit of the change is that the offsets and sizes stored in
`MPoly` can no longer disagree with each other. Storing faces in the
order of their corners can simplify some code too.
Face/polygon variables now use the `IndexRange` type, which comes with
quite a few utilities that can simplify code.
Some:
- The offset integer array has to be one longer than the face count to
avoid a branch for every face, which means the data is no longer part
of the mesh's `CustomData`.
- We lose the ability to "reference" an original mesh's offset array
until more reusable CoW from #104478 is committed. That will be added
in a separate commit.
- Since they aren't part of `CustomData`, poly offsets often have to be
copied manually.
- To simplify using `OffsetIndices` in many places, some functions and
structs in headers were moved to only compile in C++.
- All meshes created by Blender use the same order for faces and face
corners, but just in case, meshes with mismatched order are fixed by
versioning code.
- `MeshPolygon.totloop` is no longer editable in RNA. This API break is
necessary here unfortunately. It should be worth it in 3.6, since
that's the best way to allow loading meshes from 4.0, which is
important for an LTS version.
Pull Request: https://projects.blender.org/blender/blender/pulls/105938
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
This simplifies the usage of the API and is preparation for #104478.
The `CustomData_add_layer` and `CustomData_add_layer_named` now have corresponding
`*_with_data` functions that should be used when creating the layer from existing data.
Pull Request: https://projects.blender.org/blender/blender/pulls/105708