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
Refactoring mesh code, it has become clear that local cleanups and
simplifications are limited by the need to keep a C public API for
mesh functions. This change makes code more obvious and makes further
refactoring much easier.
- Add a new `BKE_mesh.hh` header for a C++ only mesh API
- Introduce a new `blender::bke::mesh` namespace, documented here:
https://wiki.blender.org/wiki/Source/Objects/Mesh#Namespaces
- Move some functions to the new namespace, cleaning up their arguments
- Move code to `Array` and `float3` where necessary to use the new API
- Define existing inline mesh data access functions to the new header
- Keep some C API functions where necessary because of RNA
- Move all C++ files to use the new header, which includes the old one
In the future it may make sense to split up `BKE_mesh.hh` more, but for
now keeping the same name as the existing header keeps things simple.
Pull Request: blender/blender#105416
Currently the shade smooth status for mesh faces is stored as part of
`MPoly::flag`. As described in #95967, this moves that information
to a separate boolean attribute. It also flips its status, so the
attribute is now called `sharp_face`, which mirrors the existing
`sharp_edge` attribute. The attribute doesn't need to be allocated
when all faces are smooth. Forward compatibility is kept until
4.0 like the other mesh refactors.
This will reduce memory bandwidth requirements for some operations,
since the array of booleans uses 12 times less memory than `MPoly`.
It also allows faces to be stored more efficiently in the future, since
the flag is now unused. It's also possible to use generic functions to
process the values. For example, finding whether there is a sharp face
is just `sharp_faces.contains(true)`.
The `shade_smooth` attribute is no longer accessible with geometry nodes.
Since there were dedicated accessor nodes for that data, that shouldn't
be a problem. That's difficult to version automatically since the named
attribute nodes could be used in arbitrary combinations.
**Implementation notes:**
- The attribute and array variables in the code use the `sharp_faces`
term, to be consistent with the user-facing "sharp faces" wording,
and to avoid requiring many renames when #101689 is implemented.
- Cycles now accesses smooth face status with the generic attribute,
to avoid overhead.
- Changing the zero-value from "smooth" to "flat" takes some care to
make sure defaults are the same.
- Versioning for the edge mode extrude node is particularly complex.
New nodes are added by versioning to propagate the attribute in its
old inverted state.
- A lot of access is still done through the `CustomData` API rather
than the attribute API because of a few functions. That can be
cleaned up easily in the future.
- In the future we would benefit from a way to store attributes as a
single value for when all faces are sharp.
Pull Request: blender/blender#104422
With the goal of clearly differentiating between arrays and single
elements, improving consistency across Blender, and using wording
that's easier to read and say, change variable names for Mesh edges
and polygons/faces.
Common renames are the following, with some extra prefixes, etc.
- `mpoly` -> `polys`
- `mpoly`/`mp`/`p` -> `poly`
- `medge` -> `edges`
- `med`/`ed`/`e` -> `edge`
`MLoop` variables aren't affected because they will be replaced
when they're split up into to arrays in #104424.
Originally caused by 6514bb05ea
More cases where the active/default color attributes were not set
correctly:
[1] Using the old Python vertex_colors API (vertex_colors.new)
[2] OBJ importer
[3] Collada importer
[4] Data Transfer layout (both standalone operator and "Generate Data
Layers" from the modifier)
Similar to 101d04f41f.
Brought over from https://archive.blender.org/developer/D16977, see
discussion there why some of the code for data transfer is not for the
genereal attribute API.
Pull Request #105020
As described in #95966, replace the `ME_EDGEDRAW` flag with a bit
vector in mesh runtime data. Currently the the flag is only ever set
to false for the "optimal display" feature of the subdivision surface
modifier. When creating an "original" mesh in the main data-base,
the flag is always supposed to be true.
The bit vector is now created by the modifier only as necessary, and
is cleared for topology-changing operations. This fixes incorrect
interpolation of the flag as noted in #104376. Generally it isn't
possible to interpolate it through topology-changing operations.
After this, only the seam status needs to be removed from edges before
we can replace them with the generic `int2` type (or something similar)
and reduce memory usage by 1/3.
Related:
- 10131a6f62
- 145839aa42
In the future `BM_ELEM_DRAW` could be removed as well. Currently it is
used and aliased by other defines in some non-obvious ways though.
Pull Request #104417
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
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
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
As part of T95966, this patch moves loose edge information out of the
flag on each edge and into a new lazily calculated cache in mesh
runtime data. The number of loose edges is also cached, so further
processing can be skipped completely when there are no loose edges.
Previously the `ME_LOOSEEDGE` flag was updated on a "best effort"
basis. In order to be sure that it was correct, you had to be sure
to call `BKE_mesh_calc_edges_loose` first. Now the loose edge tag
is always correct. It also doesn't have to be calculated eagerly
in various places like the screw modifier where the complexity
wasn't worth the theoretical performance benefit.
The patch also adds a function to eagerly set the number of loose
edges to zero to avoid building the cache. This is used by various
primitive nodes, with the goal of improving drawing performance.
This results in a few ms shaved off extracting draw data for some
large meshes in my tests.
In the Python API, `MeshEdge.is_loose` is no longer editable.
No built-in addons set the value anyway. The upside is that
addons can be sure the data is correct based on the mesh.
**Tests**
There is one test failure in the Python OBJ exporter: `export_obj_cube`
that happens because of existing incorrect versioning. Opening the
file in master, all the edges were set to "loose", which is fixed
by this patch.
Differential Revision: https://developer.blender.org/D16504
The weird code dealing with `MeshPrimitive` didn't increment the
material indices pointer for geometry types besides triangle fans.
Also use a proper accessor to avoid adding a duplicate material
indices attribute, just in case this code is used on existing meshes.
Currently there are both "EDGERENDER" and "EDGEDRAW" flags, which are
almost always used together. Both are runtime data and not exposed to
RNA, used to skip drawing some edges after the subdivision surface
modifier. The render flag is a relic of the Blender internal renderer.
This commit removes the render flag and replaces its uses with the
draw flag.
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
We now import and apply custom normals using a similar strategy
to the STL importer. We store custom normal data for each loop
as we read each MPoly and then apply it to the mesh after
`BKE_mesh_calc_edges()` is called.
The new behavior is optional and may be disabled in the Collada import
UI. When disabled, we use the old behavior of only using normals
to determine whether or not to smooth shade an MPoly.
----
Patch as requested in {T49814}.
The Collada import UI now has an additional checkbox, similar to the glTF and FBX import UIs:
{F13428264}
Here is a test Collada file with a simple test cube with flipped custom normals:
{F13428260}
{F13428282}
And a sphere where the two halves are disconnected geometry, but has custom normals that make the halves appear to be connected:
{F13436363}
{F13436368}
I've tested it on a number of my own meshes, and the custom normals appear to be imported
correctly. I'm not too sure about how I've plumbed the option down, though, or whether this
is the most proper way to apply custom normals.
Reviewed By: gaiaclary
Differential Revision: https://developer.blender.org/D15804
As described in T95966, the goal is to move to a "struct of arrays"
approach rather than gathering an arbitrary set of data in hard-coded
structs. This has performance benefits, but also code complexity
benefits (this patch removes plenty of code, though the boilerplate
for the new operators outweighs that here).
To mirror the internal change, the options for storing mesh bevel
weights are converted into operators that add or remove the layer,
like for some other layers.
The most complex change is to the solidify modifier, where bevel
weights had special handling. Other than that, most changes are
removing clearing of the weights, boilerplate for the add/remove
operators, and removing the manual transfer of bevel weights
in bmesh - mesh conversion.
Eventually bevel weights can become a fully generic attribute,
but for now this patch aims to avoid most functional changes.
Bevel weights are still written and read from the mesh in the old way,
so neither forward nor backward compatibility are affected. As described
in T95965, writing in the old format will be done until 4.0.
Differential Revision: https://developer.blender.org/D14077
Use `verts` instead of `vertices` and `polys` instead of `polygons`
in the API added in 05952aa94d. This aligns better with
existing naming where the shorter names are much more common.
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7, 410a6efb74). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
This patch moves material indices from the mesh `MPoly` struct to a
generic integer attribute. The builtin material index was already
exposed in geometry nodes, but this makes it a "proper" attribute
accessible with Python and visible in the "Attributes" panel.
The goals of the refactor are code simplification and memory and
performance improvements, mainly because the attribute doesn't have
to be stored and processed if there are no materials. However, until
4.0, material indices will still be read and written in the old
format, meaning there may be a temporary increase in memory usage.
Further notes:
* Completely removing the `MPoly.mat_nr` after 4.0 may require
changes to DNA or introducing a new `MPoly` type.
* Geometry nodes regression tests didn't look at material indices,
so the change reveals a bug in the realize instances node that I fixed.
* Access to material indices from the RNA `MeshPolygon` type is slower
with this patch. The `material_index` attribute can be used instead.
* Cycles is changed to read from the attribute instead.
* BMesh isn't changed in this patch. Theoretically it could be though,
to save 2 bytes per face when less than two materials are used.
* Eventually we could use a 16 bit integer attribute type instead.
Ref T95967
Differential Revision: https://developer.blender.org/D15675
When allocating new `CustomData` layers, often we do redundant
initialization of arrays. For example, it's common that values are
allocated, set to their default value, and then set to some other
value. This is wasteful, and it negates the benefits of optimizations
to the allocator like D15082. There are two reasons for this. The
first is array-of-structs storage that makes it annoying to initialize
values manually, and the second is confusing options in the Custom Data
API. This patch addresses the latter.
The `CustomData` "alloc type" options are rearranged. Now, besides
the options that use existing layers, there are two remaining:
* `CD_SET_DEFAULT` sets the default value.
* Usually zeroes, but for colors this is white (how it was before).
* Should be used when you add the layer but don't set all values.
* `CD_CONSTRUCT` refers to the "default construct" C++ term.
* Only necessary or defined for non-trivial types like vertex groups.
* Doesn't do anything for trivial types like `int` or `float3`.
* Should be used every other time, when all values will be set.
The attribute API's `AttributeInit` types are updated as well.
To update code, replace `CD_CALLOC` with `CD_SET_DEFAULT` and
`CD_DEFAULT` with `CD_CONSTRUCT`. This doesn't cause any functional
changes yet. Follow-up commits will change to avoid initializing
new layers where the correctness is clear.
Differential Revision: https://developer.blender.org/D15617
Many thanks to the original Author of this patch: Christian Aguilera
The COLLADA importer was silently ignoring the alpha component in the
vertex data.
The `stride` variable holds the component count (3 for RGB; 4 for RGBA),
and can be used for honouring the alpha channel in the vertex data.
Test plan:
- Open Blender.
- Clear the scene.
- Add a plane.
- Enter **Vertex Paint** mode.
- Switch to the **Erase Alpha** blending mode.
- Select a tone of gray.
- Turn strength down to less than 1
- Paint [some of] the vertices of the plane.
- Export project as a COLLADA file (`.dae`).
- Clear the scene.
- Re-import the COLLADA file again.
- Export the project again (with different name).
**Without** this patch, the second exported project will have lost the
alpha component in their vertex data:
```lang=xml, counterexample
<float_array id="Plane-mesh-colors-Col-array" count="24">1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1</float_array>
```
**With** the patch, the first and the second exported projects retain
the alpha values painted previously:
```lang=xml
<float_array id="Plane-mesh-colors-Col-array" count="24">1 1 1 1 1 1 1 0.5490196 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0.5490196</float_array>
```
Reviewed By: cristian64, SonnyCampbell_Unity
Authored by: Christian Aguilera
Differential Revision: https://developer.blender.org/D14246
The "PROP" in the name reflects its generic status, and removing
"LOOP" makes sense because it is no longer associated with just
mesh face corners. In general the goal is to remove extra semantic
meaning from the custom data types.
This is mostly a cleanup to avoid hardcoding the eager calculation of
normals it isn't necessary, by reducing calls to `BKE_mesh_calc_normals`
and by removing calls to `BKE_mesh_normals_tag_dirty` when the mesh
is newly created and already has dirty normals anyway. This reduces
boilerplate code and makes the "dirty by default" state more clear.
Any regressions from this commit should be easy to fix, though the
lazy calculation is solid enough that none are expected.
Use a shorter/simpler license convention, stops the header taking so
much space.
Follow the SPDX license specification: https://spdx.org/licenses
- C/C++/objc/objc++
- Python
- Shell Scripts
- CMake, GNUmakefile
While most of the source tree has been included
- `./extern/` was left out.
- `./intern/cycles` & `./intern/atomic` are also excluded because they
use different header conventions.
doc/license/SPDX-license-identifiers.txt has been added to list SPDX all
used identifiers.
See P2788 for the script that automated these edits.
Reviewed By: brecht, mont29, sergey
Ref D14069
Modernize loops by using the `for(type variable : container)` syntax.
Some loops were trivial to fix, whereas others required more attention
to avoid semantic changes. I couldn't address all old-style loops, so
this commit doesn't enable the `modernize-loop-convert` rule.
Although Clang-Tidy's auto-fixer prefers to use `auto` for the loop
variable declaration, I made as many declarations as possible explicit.
To me this increases local readability, as you don't need to fully
understand the container in order to understand the loop variable type.
No functional changes.
Corrects incorrect usages of the word 'loose' when 'lose' was required.
Differential Revision: https://developer.blender.org/D9243
Reviewed by Campbell Barton