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
According to reports and testing in blender/blender-addons#104434, DCCs
tend to behave badly when rebuilding normals from 'bitflags'
smoothgroups, if different smoothgroups using the same bitflag value share
(are connected by) some common vertices, even if there are no common
edges between them.
This commit adds a new option to the RNA API generating smooth groups,
to also consider smooth groups only sharing vertices as neighbors.
It also makes related required change to implementation, and some
refactor of the API, splitting public functions between 'normal' and
'bitflags' versions.
This should make changes proposed in blender/blender-addons#105516
much simpler, and allow for a matching behavior in smoothgroups
generated by the OBJ exporter as well.
Pull Request: https://projects.blender.org/blender/blender/pulls/135248
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
The result of cross_poly_v2 was flipped compared with cross_tri_v2 &
cross_poly_v3 (with the Z values zeroed).
Ensure cross_poly_v2/3, cross_tri_v2/3 return compatible results and
updating the doc-strings noting that a negative Z is for clock-wise
polygons.
Along with the 4.1 libraries upgrade, we are bumping the clang-format
version from 8-12 to 17. This affects quite a few files.
If not already the case, you may consider pointing your IDE to the
clang-format binary bundled with the Blender precompiled libraries.
Except for vertex groups and a few older color types, these
are generally replaced by newer generic attribute types.
Also remove some includes of DNA_mesh_types.h, since it's
included indirectly by BKE_mesh.hh currently.
Make the naming consistent with the recent change from "loop" to
"corner". Avoid the need for a special type for these triangles by
conveying the semantics in the naming instead.
- `looptris` -> `corner_tris`
- `lt` -> `tri` (or `corner_tri` when there is less context)
- `looptri_index` -> `tri_index` (or `corner_tri_index`)
- `lt->tri[0]` -> `tri[0]`
- `Span<MLoopTri>` -> `Span<int3>`
- `looptri_faces` -> `tri_faces` (or `corner_tri_faces`)
If we followed the naming pattern of "corner_verts" and "edge_verts"
exactly, we'd probably use "tri_corners" instead. But that sounds much
worse and less intuitive to me.
I've found that by using standard vector types for this sort of data,
the commonalities with other areas become much clearer, and code ends
up being naturally more data oriented. Besides that, the consistency
is nice, and we get to mostly remove use of `DNA_meshdata_types.h`.
Pull Request: https://projects.blender.org/blender/blender/pulls/116238
The term `looptri` was used ambiguously for both single & arrays.
The term `tri` was also used, causing `tri->tri`.
Use terms:
- `looptris` for an array or when dealing with multiple items.
- `looptri` is used when dealing with a single item.
- `lt` for a single MLoopTri variables & arguments.
This was already a convention but not followed closely.
This gives better asserts in debug builds through use of Span, more
safety when name convention attributes happen to have different types
or domains, and simpler code in some cases. But the main reasoning is to
avoid relying on the specifics of CustomData more to allow us to replace
it in the future.
Similar to [0], but also including the further optimizations from [1],
parallelize the vertex to edge, vertex to face, and edge to face
topology map index creation (the first part of the maps was already
parallelized). Vertex to face index creation went from 9.8 ms to 1.7 ms
on average, for a 1 million vertex grid. That's nice, since this map
is used for vertex normals after [2].
[0]: 226359ec48
[1]: 98e33adac2
[2]: 5052e0d407
We need a separate array that we can change in during the parallel
group construction. That array tells where in each group the index
is added. Building this array is expensive, since construcing a new
`Array` fills its elements serially. There are two possible solutions:
1. Use a copy of the offsets to increment result indices directly
2. Rely on OS-optimized `calloc` instead of `malloc` and a copy/fill
Both depend on using `fetch_and_add` instead of `add_and_fetch`.
The vertex to corner and edge to corner map creation is optimized
by this commit, though the benefits will be useful elsewhere in the
future.
| | Before | 1. offsets copy | 2. calloc |
| -------- | ------- | --------------- | --------------- |
| Grid 1m | 3.1 ms | 1.9 ms (1.63x) | 1.8 ms (1.72x) |
| Grid 16m | 51.8 ms | 33.3 ms (1.55x) | 32.7 ms (1.58x) |
This commit implements the calloc solution, since it's slightly faster
and simpler. In the future, `Array` could do this optimization itself
when it detects that its fill value is just zero bytes.
Pull Request: https://projects.blender.org/blender/blender/pulls/112065
Add three cached topology maps to `Mesh`, to avoid computations when
mesh data isn't changed. Choosing the right maps to cache is a bit
arbitrary, but generally we have to start somewhere. The limiting
factor is memory usage (all the new caches combined have a
comparable footprint to a UV map).
For now, the caches added are:
- Vertex to face corner
- Vertex to face
- Face corner to face
These caches are used in quite a few places already;
- Face corner normal calculation
- UV value merging
- Setting sharp edges from face angles
- Data transfer modifier
- Voxel remesh attribute remapping
- Sculpt mode painting
- Sculpt mode normal calculation
- Vertex paint mode
- Split edges geometry node
- Mesh topology geometry nodes
Caching topology maps means they don't have to be rebuilt every time
they're used. Meshes copied but without topology changes can share
the cache, further reducing re-computations. For example, FPS with a
large mesh using the "Corners of Vertex" node went from 1.8 to 2.3.
Entering sculpt mode is slightly faster too.
There is some obvious work for future commits:
- Use caches in attribute domain interpolation
- More multithreading of second phase of map building
- Update/build caches eagerly in some geometry nodes
Pull Request: https://projects.blender.org/blender/blender/pulls/107816
Change the algorithm to make better use of multiple CPU cores. First
offsets are created by counting the number of elements using each
vertex. Those offsets are used during the next phase that adds indices
to each group in parallel. Atomic increments are used to add elements
to each group. Since the order in each group is non-deterministic,
they are sorted in parallel afterwards.
The performance improvement depends on the number of cores, CPU caches,
memory bandwidth, single threaded performance, and mesh topology. In
our tests, performance improved by 3-4.5x for large grid-like meshes.
See [1] for investigation of this algorithm and potential alternatives.
1. https://hackmd.io/@s0TMIS4lTAGwHVO20ECwpw/build_edge_to_loop_map_tests.
Pull Request: https://projects.blender.org/blender/blender/pulls/110707
Listing the "Blender Foundation" as copyright holder implied the Blender
Foundation holds copyright to files which may include work from many
developers.
While keeping copyright on headers makes sense for isolated libraries,
Blender's own code may be refactored or moved between files in a way
that makes the per file copyright holders less meaningful.
Copyright references to the "Blender Foundation" have been replaced with
"Blender Authors", with the exception of `./extern/` since these this
contains libraries which are more isolated, any changed to license
headers there can be handled on a case-by-case basis.
Some directories in `./intern/` have also been excluded:
- `./intern/cycles/` it's own `AUTHORS` file is planned.
- `./intern/opensubdiv/`.
An "AUTHORS" file has been added, using the chromium projects authors
file as a template.
Design task: #110784
Ref !110783.
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
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
This utility counts the number of occurrences of each index in an array.
This is used for building mesh topology maps offsets, or for counting
the number of connected elements. Some users are geometry nodes,
the subdivision draw cache, and mesh to curve conversion.
See #109628
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/
Combine the newer less efficient C++ implementations and the older
less convenient C functions. The maps now contain one large array of
indices, split into groups by a separate array of offset indices.
Though performance of creating the maps is relatively unchanged, the
new implementation uses 4 bytes less per source element than the C
maps, and 20 bytes less than the newer C++ functions (which also
had more overhead with larger N-gons). The usage syntax is simpler
than the C functions as well.
The reduced memory usage is helpful for when these maps are cached
in the near future. It will also allow sharing the offsets between
maps for different domains like vertex to corner and vertex to face.
A simple `GroupedSpan` class is introduced to make accessing the
topology maps much simpler. It combines offset indices and a separate
span, splitting it into chunks in an efficient way.
Pull Request: https://projects.blender.org/blender/blender/pulls/107861
For derived mesh triangulation information, currently the three face
corner indices are stored in the same struct as index of the mesh
polygon the triangle is part of. While those pieces of information are
often used together, they often aren't, and combining them prevents
the indices from being used with generic utilities. It also means that
1/3 more memory has to be written when recalculating the triangulation
after deforming the mesh, and that the entire triangle data has to be
read when only the polygon indices are needed.
This commit splits the polygon index into a separate cache on `Mesh`.
The triangulation data isn't saved to files, so this doesn't affect
.blend files at all.
In a simple test deforming a mesh with geometry nodes, the time used
to recalculate the triangulation reduced from 2.0 ms to 1.6 ms,
increasing overall FPS from 14.6 to 15.
Pull Request: https://projects.blender.org/blender/blender/pulls/106774
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
The "reverse map" of corners to faces and points to curves is the same
for meshes and curves now. Move it to the offset indices header to
reflect this.
This unification can go further in the future, but I'd rather wait
until the design is clearer for now.
Pull Request: https://projects.blender.org/blender/blender/pulls/106570
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
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: https://projects.blender.org/blender/blender/pulls/104422
Similar to the previous commit, this simplifies future refactoring
to change the way edges are stored, and further differentiates
single poly variables from array pointers.
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.
As part of #95966, move the `ME_SEAM` flag on mesh edges
to a generic boolean attribute, called `.uv_seam`. This is the
last bit of extra information stored in mesh edges. After this
is committed we can switch to a different type for them and
have a 1/3 improvement in memory consumption.
It is also now possible to see that a mesh has no UV seams in
constant time, and like other similar refactors, interacting with
only the UV seams can be done with less memory.
The attribute name starts with a `.` to signify that the attribute,
like face sets, isn't meant to be used in arbitrary procedural
situations (with geometry nodes for example). That gives us more
freedom to change things in the future.
Pull Request #104728
Using callback functions didn't scale well as more arguments are added.
It got very confusing when to pass tehmarguments weren't always used.
Instead use a `FunctionRef` with indices for arguments. Also remove
unused edge arguments to topology mapping functions.
Add a new node that groups faces inside of boundary edge regions.
This is the opposite action as the existing "Face Group Boundaries"
node. It's also the same as some of the "Initialize Face Sets"
options in sculpt mode.
Discussion in #102962 has favored "Group" for a name for these
sockets rather than "Set", so that is used here.
Pull Request #104428
Also minor changes in comments:
- Reference BLENDER_HISTORY_FILE instead of the literal file-name
(simplifies looking up usage).
- Use usernames in tags, as noted in code-style.
Simplify `BM_uv_element_map_create` by using `BM_face_calc_area_uv_signed`.
Remove unused UV winding code in `BM_uv_vert_map_create`.
Fixes unlikely memory leak in `BKE_mesh_uv_vert_map_create`.
No functional changes.
Differential Revision: https://developer.blender.org/D17137
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