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: blender/blender#104424
When an object has no UV layers and an anonymous UV layer is created,
the anonymous layer gets set as the default (render) layer. This is
very confusing because it then uses a hidden anonmous layer. This patch
suppresses the usage of anonymous layers for rendering.
Pull Request: blender/blender#105192
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: blender/blender#105708
This might've been a merge error, the result of color mixing
was being overwritten by a simple copy of source to destination
inside of layerCopyValue_propcol.
This might've been a merge error, the result of color mixing
was being overwritten by a simple copy of source to destination
inside of layerCopyValue_propcol.
This reverts commit 19222627c6.
Something went wrong here, seems like this commit merged the main branch
into the release branch, which should never be done.
This reverts commit 68181c2560.
I merged 3.6 into 3.5 by mistake. Basically I had a PR against main,
then changed it in the last minute to be against 3.5 via the
web-interface unaware that I shouldn't do it without updating the
patch.
Original Pull Request: #104889
Note that the node group has its sockets names
translated, while the built-in nodes don't.
So we need to use data_ for the built-in nodes names,
and the sockets of the created node groups.
Pull Request #104889
The existing logic to copy `BMesh` custom data layers to `Mesh`
attribute arrays was quite complicated, and incorrect in some cases
when the source and destinations didn't have the same layers.
The functions leave a lot to be desired in general, since they have
a lot of redundant complexity that ends up doing the same thing for
every element.
The problem in #104154 was that the "rest_position" attribute overwrote
the mesh positions since it has the same type and the positions weren't
copied. This same problem has shown up in boolean attribute conversion
in the past. Other changes fixed some specific cases but I think a
larger change is the only proper solution.
This patch adds preprocessing before looping over all elements to
find the basic information for copying the relevant layers, taking
layer names into account. The preprocessing makes the hot loops
simpler.
In a simple file with a 1 million vertex grid, I observed a 6%
improvement animation playback framerate in edit mode with a simple
geometry nodes modifier, from 5 to 5.3 FPS.
Fixes#104154, #104348
Pull Request #104421
Because of T95965, some attributes are stored as generic attributes
in Mesh but have special handling for the conversion to BMesh.
Expose a function to tell whether certain attribute names are handled
specially in the conversion, and refactor the error checking process
to use it. Also check for generic attributes on the face domain which
wasn't done before.
Author: Hans Goudey
Reviewed By: Joseph Eagar
Co-authored-by: Joseph Eagar <joeedh@gmail.com>
Pull Request #104567
Use a consistent style for declaring the names of struct members
in their declarations. Note that this convention was already used in
many places but not everywhere.
Remove spaces around the text (matching commented arguments) with
the advantage that the the spell checking utility skips these terms.
Making it possible to extract & validate these comments automatically.
Also use struct names for `bAnimChannelType` & `bConstraintTypeInfo`
which were using brief descriptions.
Currently you can retrieve a mutable array from a const CustomData.
That makes code unsafe since the compiler can't check for correctness
itself. Fix that by introducing a separate function to retrieve mutable
arrays from CustomData. The new functions have the `_for_write`
suffix that make the code's intention clearer.
Because it makes retrieving write access an explicit step, this change
also makes proper copy-on-write possible for attributes.
Notes:
- The previous "duplicate referenced layer" functions are redundant
with retrieving layers with write access
- The custom data functions that give a specific index only have
`for_write` to simplify the API
Differential Revision: https://developer.blender.org/D14140
Move the `ME_SHARP` flag for mesh edges to a generic boolean
attribute. This will help allow changing mesh edges to just a pair
of integers, giving performance improvements. In the future it could
also give benefits for normal calculation, which could more easily
check if all or no edges are marked sharp, which is helpful considering
the plans in T93551.
The attribute is generally only allocated when it's necessary. When
leaving edit mode, it will only be created if an edge is marked sharp.
The data can be edited with geometry nodes just like a regular edge
domain boolean attribute.
The attribute is named `sharp_edge`, aiming to reflect the similar
`select_edge` naming and to allow a future `sharp_face` name in
a separate commit.
Ref T95966
Differential Revision: https://developer.blender.org/D16921
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
Previously, the lifetimes of anonymous attributes were determined by
reference counts which were non-deterministic when multiple threads
are used. Now the lifetimes of anonymous attributes are handled
more explicitly and deterministically. This is a prerequisite for any kind
of caching, because caching the output of nodes that do things
non-deterministically and have "invisible inputs" (reference counts)
doesn't really work.
For more details for how deterministic lifetimes are achieved, see D16858.
No functional changes are expected. Small performance changes are expected
as well (within few percent, anything larger regressions should be reported as
bugs).
Differential Revision: https://developer.blender.org/D16858
Attributes are unifying around a name-based API, and we would like to
be able to move away from CustomData in the future. This patch moves
the identification of active and fallback (render) color attributes
to strings on the mesh from flags on CustomDataLayer. This also
removes some ugliness used to retrieve these attributes and maintain
the active status.
The design is described more here: T98366
The patch keeps forward compatibility working until 4.0 with
the same method as the mesh struct of array refactors (T95965).
The strings are allowed to not correspond to an attribute, to allow
setting the active/default attribute independently of actually filling
its data. When applying a modifier, if the strings don't match an
attribute, they will be removed.
The realize instances / join node and join operator take the names from
the first / active input mesh. While other heuristics may be helpful
(and could be a future improvement), just using the first is simple
and predictable.
Differential Revision: https://developer.blender.org/D15169
* Support bidirectional type lookups. E.g. finding the base type of a
field was supported, but not the other way around. This also removes
the todo in `get_vector_type`. To achieve this, types have to be
registered up-front.
* Separate `CPPType` from other "type traits". For example, previously
`ValueOrFieldCPPType` adds additional behavior on top of `CPPType`.
Previously, it was a subclass, now it just contains a reference to the
`CPPType` it corresponds to. This follows the composition-over-inheritance
idea. This makes it easier to have self-contained "type traits" without
having to put everything into `CPPType`.
Differential Revision: https://developer.blender.org/D16479
Previously the `CustomData_add_layer` function always returned
the existing layer data when used for types that can only have one
layer. This made it work like an "ensure layer exists" function for those
types. That was used in various places to make code more concise.
0a7308a0f1 changed that to always "recreate" the layer even
when it existed. Maybe this is more logical for an "add layer" function,
but that's not clear, and it breaks a bunch of existing code that relied
on the current behavior. Rather than spending a bunch of time going
through uses of the CustomData API, this patch resets the behavior
to what it was before, but adds an assert and a comment to help
avoid memory leaks and other issues. We should focus on moving
to the attribute API instead.
Differential Revision: https://developer.blender.org/D16458
Previously, the code would incorrectly free the passed in custom data
layer even when `CD_ASSIGN` was not used. Now the function actually
supports assigning the data to the layer. This only fixes the case for
custom data layer types that only support a single layer like `CD_MEDGE`.
Informally reviewed by Hans Goudey.
In some situations, layers were filled with their default value
when converting from Mesh to BMesh (entering edit mode, for example).
This was caused by the recently added "copy mesh to bmesh" or "merge
mesh to bmesh" custom data functions creating a difference custom
data format than was used for the copying functions used later.
`CustomData_to_bmesh_block` is not robust enough to handle simple
differences in layout between the layout of the source and result
CustomData layers, because it relies on the order of the types and
the number of layers within each type.
As a fix, make the "mesh to bmesh" special case more explicit in
the conversion functions. This makes the difference in the API
smaller, which is a nice improvement anwyay.
Fixes T101796
This is the conventional way of dealing with unused arguments in C++,
since it works on all compilers.
Regex find and replace: `UNUSED\((\w+)\)` -> `/*$1*/`
Due to increased usage of typed arrays in C++ and name/offset based
access for BMesh, these are unlikely to be used again, and haven't been
used in many years.
First, there can only be one crease layer, so remove the "default name",
since apparently that's how CustomData tests for that
(see `CustomData_layertype_is_singleton`).
Second, always propagate crease data because it can be used in arbitrary
situations by geometry nodes. That also has to be done for all generic
attribute layers.
Fixes T101340, T101373
Using the attribute name semantics from T97452, this patch moves the
selection status of mesh elements from the `SELECT` of vertices, and
edges, and the `ME_FACE_SEL` of faces to generic boolean attribute
Storing this data as generic attributes can significantly simplify and
improve code, as described in T95965.
The attributes are called `.select_vert`, `.select_edge`, and
`.select_poly`. The `.` prefix means they are "UI attributes",so they
still contain original data edited by users, but they aren't meant to
be accessed procedurally by the user in arbitrary situations. They are
also be hidden in the spreadsheet and the attribute list.
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when selection is used. When the flags are removed
completely, requirements will decrease.
Further notes:
* The `MVert` flag is empty at runtime now, so it can be ignored.
* `BMesh` is unchanged, otherwise the change would be much larger.
* Many tests have slightly different results, since the selection
attribute uses more generic propagation. Previously you couldn't
really rely on edit mode selections being propagated procedurally.
Now it mostly works as expected.
Similar to 2480b55f21
Ref T95965
Differential Revision: https://developer.blender.org/D15795
This is very similar to D14077. There are two differences though.
First is that vertex creases are already stored in a separate layer,
and second is that we can now completely remove use of `Mesh.cd_flag`,
since that information is now inherent to whether the layers exist.
There are two functional differences here:
* Operators are used to add and remove layers instead of a property.
* The "crease" attribute can be created and removed by geometry nodes.
The second change should make various geometry nodes slightly faster,
since the "crease" attribute was always processed before. Creases are
now interpolated generically in the CustomData API too, which should
help maintain the values across edits better.
Meshes get an `edge_creases` RNA property like the existing vertex
property, to provide more efficient access to the data in Cycles.
One test failure is expected, where different rounding between float
the old char storage means that 5 additional points are scattered in
a geometry nodes test.
Differential Revision: https://developer.blender.org/D15927
Similar to the other refactors from T95965, this commit moves sculpt
face sets to use a generic integer attribute named `".sculpt_face_set"`.
This makes face sets accessible in the Python API.
The attribute is not visible in the attributes list or the spreadsheet
because it is meant for internal use, though that could be an option
in the future along with other similar attributes. Currently the change
is small, but in the future this could simplify code by allowing use
of more generic attribute APIs.
Differential Revision: https://developer.blender.org/D16045
New unified attribute API for sculpt code.
= Basic Design =
The sculpt attribute API can create temporary or permanent attributes (only supported in `PBVH_FACES` mode). Attributes are created via `BKE_sculpt_attribute_ensure.`
Attributes can be explicit CustomData attributes or simple array-based pseudo-attributes (this is useful for PBVH_GRIDS and PBVH_BMESH).
== `SculptAttributePointers` ==
There is a structure in `SculptSession` for convenience attribute pointers, `ss->attrs`. Standard attributes should assign these; the attribute API will automatically clear them when the associated attributes are released. For example, the automasking code stores its factor attribute layer in `ss->attrs.automasking_factor`.
== Naming ==
Temporary attributes should use the SCULPT_ATTRIBUTE_NAME macro for naming, it takes an entry in `SculptAttributePointers` and builds a layer name.
== `SculptAttribute` ==
Attributes are referenced by a special `SculptAttribute` structure, which holds
all the info needed to look up elements of an attribute at run time.
All of these structures live in a preallocated flat array in `SculptSession`, `ss->temp_attributes`. This is extremely important. Since any change to the `CustomData` layout can in principle invalidate every extant `SculptAttribute`, having them all in one block of memory whose location doesn't change allows us to update them transparently.
This makes for much simpler code and eliminates bugs. To see why this is tricky to get right, imagine we want to create three attributes in PBVH_BMESH mode and we provide our own `SculptAttribute` structs for the API to fill in. Each new layer will invalidate the `CustomData` block offsets in the prior one, leading to memory corruption.
Reviewed by: Brecht Van Lommel
Differential Revision: https://developer.blender.org/D15496
Ref D15496