Commit Graph

150 Commits

Author SHA1 Message Date
Hans Goudey
d3f84449ad Mesh: Add "free" custom normals
Add a "dumb vector" storage option for custom normals, with the
"custom_normal" attribute. Adjust the mesh normals caching to
provide this attribute if it's available, and add a geometry node to
store custom normals.

## Free Normals
They're called "free" in the sense that they're just direction vectors
in the object's local space, rather than the existing "smooth corner
fan space" storage. They're also "free" in that they make further
normals calculation very inexpensive, since we just use the custom
normals instead. That's a big improvement from the existing custom
normals storage, which usually significantly decreases
viewport performance. For example, in a simple test file just storing
the vertex normals on a UV sphere, using free normals gives 25 times
better playback performance and 10% lower memory usage.

Free normals are adjusted when applying a transformation to the entire
mesh or when realizing instances, but in general they're not updated for
vertex deformations.

## Set Mesh Normal Node
The new geometry node allows storing free custom normals as well as
the existing corner fan space normals. When free normals are chosen,
free normals can be stored on vertices, faces, or face corners. Using
the face corner domain is necessary to bake existing mixed sharp and
smooth edges into the custom normal vectors.

The node also has a mode for storing edge and mesh sharpness, meant
as a "soft" replacement to the "Set Shade Smooth" node that's a bit
more convenient.

## Normal Input Node
The normal node outputs free custom normals mixed to whatever domain is
requested. A "true normal" output that ignores custom normals and
sharpness is added as well.

Across Blender, custom normals are generally accessed via face and
vertex normals, when "true normals" are not requested explicitly.
In many cases that means they are mixed from the face corner domain.

## Future Work
1. There are many places where propagation of free normals could be
   improved. They should probably be normalized after mixing, and it
   may be useful to not just use 0 vectors for new elements. To keep
   the scope of this change smaller, that sort of thing generally isn't
   handled here. Searching `CD_NORMAL` gives a hint of where better
   propagation could be useful.
2. Free normals are displayed properly in edit mode, but the existing
   custom normal editing operators don't work with free normals yet.
   This will hopefully be fairly straightforward since custom normals
   are usually converted to `float3` for editing anyway. Edit mode
   changes aren't included here because they're unnecessary for the
   procedural custom normals use cases.
3. Most importers can probably switch to using free normals instead,
   or at least provide an option for it. That will give a significant
   import performance improvement, and an improvement of Blender's
   FPS for imported scenes too.

Pull Request: https://projects.blender.org/blender/blender/pulls/132583
2025-04-04 19:16:51 +02:00
Hans Goudey
b36eb69038 Geometry Nodes: Output proper face corner normals
Previously, when evaluated on the face corner domain, the normal input
node just returned the face normals, as if the mesh was completely flat
shaded. This ignores face and edge smoothness, and custom face corner
normals. In the past couple years the expected behavior of accessing
normals has become much clearer and this behavior is clearly a mistake
in retrospect.

This commit exposes the same face corner normals used everywhere else
in Blender when the node is evaluated on the corner domain. The old
behavior is accessible with a node property in the sidebar. There is
versioning so old files have the property set and get the same results.

This is split from !132583.

Pull Request: https://projects.blender.org/blender/blender/pulls/133340
2025-01-20 23:57:32 +01:00
Hans Goudey
9dd3c64c36 Cleanup: Remove unused includes in some blenkernel files
Pull Request: https://projects.blender.org/blender/blender/pulls/133067
2025-01-14 19:55:11 +01:00
Jacques Lucke
4da580236b Refactor: Attributes: split attribute accessors to separate files
Previously, the attribute accessor were defined in the `geometry_component_*.cc`
files. This made sense back in the day, because this attribute API was only used
through `GeometryComponent`. However, nowadays this attribute API is independent
of `GeometryComponent`. E.g. one can use `mesh.attributes()` without ever
creating a component.

The refactor contains the following changes:
* Move attribute accessors to separate files for each geometry type. E.g. from
  `geometry_component_mesh.cc` to `mesh_attributes.cc`.
* Move implementations of e.g. `Mesh::attributes()` to `mesh.cc`.
* Provide access to the `AttributeAccessorFunctions` without actually having a
  geometry. This will be useful to e.g. implement
  `attribute_is_builtin_on_component_type` without dummy components.

Pull Request: https://projects.blender.org/blender/blender/pulls/130516
2024-11-19 14:28:01 +01:00
Jacques Lucke
8528407a18 Cleanup: rename ComponentAttributeProviders to GeometryAttributeProviders
This API is used even without `GeometryComponent` nowadays.
2024-11-19 11:37:29 +01:00
Hans Goudey
d24483e0cf Geometry: Use StringRef for vertex group lookup
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
2024-09-28 20:58:34 +02:00
Hans Goudey
68be2d9af1 Cleanup: Add helper function to access vertex group index from name
In addition to the existing function which takes an ID argument.
2024-09-28 10:39:04 -04:00
Jacques Lucke
6810084a47 Attributes: improve API to iterate over attributes
This improve the API in multiple aspects:
* No need for an additional `lookup` call to get the current attribute. This
  would internally iterate over all attributes again. This leads to O(n^2)
  behavior. Note that there are still other reasons for O(n^2) behavior when
  processing attributes (where n is the number of attributes).
* Remove the need to return a value from the iteration code to indicate that the
  iteration should continue. This is now the default behavior. The iteration can
  still be stopped by calling `iter.stop()`.
* Easier access to `is_builtin` property.
* Iterator callback only has a single parameter instead of two (of which one is
  sometimes unused).

Pull Request: https://projects.blender.org/blender/blender/pulls/128128
2024-09-26 12:59:00 +02:00
Jacques Lucke
89ae1ba38a Attributes: remove AttributeIDRef in favor of just using strings
Previously, the `AttributeIDRef` wrapper was needed because it also had to
contain a pointer to an `AnonymousAttributeID`. However, since
b279a6d703 this is not necessary anymore.
Therefore we can use "raw" `StringRef` now which reduces the mental overhead
when working with attributes and also simplifies code.

Pull Request: https://projects.blender.org/blender/blender/pulls/127140
2024-09-04 16:13:03 +02:00
Jacques Lucke
a8667aa03f Core: introduce MemoryCounter API
We often have the situation where it would be good if we could easily estimate
the memory usage of some value (e.g. a mesh, or volume). Examples of where we
ran into this in the past:
* Undo step size.
* Caching of volume grids.
* Caching of loaded geometries for import geometry nodes.

Generally, most caching systems would benefit from the ability to know how much
memory they currently use to make better decisions about which data to free and
when. The goal of this patch is to introduce a simple general API to count the
memory usage that is independent of any specific caching system. I'm doing this
to "fix" the chicken and egg problem that caches need to know the memory usage,
but we don't really need to count the memory usage without using it for caches.
Implementing caching and memory counting at the same time make both harder than
implementing them one after another.

The main difficulty with counting memory usage is that some memory may be shared
using implicit sharing. We want to avoid double counting such memory. How
exactly shared memory is treated depends a bit on the use case, so no specific
assumptions are made about that in the API. The gathered memory usage is not
expected to be exact. It's expected to be a decent approximation. It's neither a
lower nor an upper bound unless specified by some specific type. Cache systems
generally build on top of heuristics to decide when to free what anyway.

There are two sides to this API:
1. Get the amount of memory used by one or more values. This side is used by
   caching systems and/or systems that want to present the used memory to the
   user.
2. Tell the caller how much memory is used. This side is used by all kinds of
   types that can report their memory usage such as meshes.

```cpp
/* Get how much memory is used by two meshes together. */
MemoryCounter memory;
mesh_a->count_memory(memory);
mesh_b->count_memory(memory);
int64_t bytes_used = memory.counted_bytes();

/* Tell the caller how much memory is used. */
void Mesh::count_memory(blender::MemoryCounter &memory) const
{
  memory.add_shared(this->runtime->face_offsets_sharing_info,
                    this->face_offsets().size_in_bytes());

  /* Forward memory counting to lower level types. This should be fairly common. */
  CustomData_count_memory(this->vert_data, this->verts_num, memory);
}

void CustomData_count_memory(const CustomData &data,
                             const int totelem,
                             blender::MemoryCounter &memory)
{
  for (const CustomDataLayer &layer : Span{data.layers, data.totlayer}) {
    memory.add_shared(layer.sharing_info, [&](blender::MemoryCounter &shared_memory) {
      /* Not quite correct for all types, but this is only a rough approximation anyway. */
      const int64_t elem_size = CustomData_get_elem_size(&layer);
      shared_memory.add(totelem * elem_size);
    });
  }
}
```

Pull Request: https://projects.blender.org/blender/blender/pulls/126295
2024-08-15 10:54:21 +02:00
Hans Goudey
c4fc19f064 Cleanup: Use reference argument for BKE_mesh_copy_for_eval 2024-05-20 13:18:24 -04:00
Campbell Barton
9918488bb1 Cleanup: use uppercase tags, following own style guide 2024-05-03 11:33:21 +10:00
Hans Goudey
ef22826a3c Cleanup: Remove non-creatable option for builtin attributes
This was necessary when attributes were stored embedded in legacy
structs like `MPoly`. Nowadays that isn't the case anymore, and there
doesn't seem to be a reason to restrict the creation of attributes.
2024-03-25 17:05:39 -04:00
Hans Goudey
04bcd17dc8 Cleanup: Remove unnecessary builtin attribute provider logic
All builtin attributes are now stored as named attributes, so the old
code path from where they were stored with non-generic types can be
removed. The stored type and attribute type don't have to be tracked
separately anymore either.
2024-03-25 16:01:36 -04:00
Hans Goudey
961783c444 Cleanup: Move BKE_deform.h to C++ 2024-01-29 19:04:13 -05:00
Hans Goudey
3e76a1a6c2 Cleanup: Move BKE_lib_id.h to C++ 2024-01-15 12:44:14 -05:00
Iliya Katushenock
37b2c12cfa Geometry Nodes: Sort Elements node
Implements the design in #109983

Pull Request: https://projects.blender.org/blender/blender/pulls/114194
2024-01-12 14:30:34 +01:00
Hans Goudey
9daa6d8115 Cleanup: Remove unnecessary namespace specification 2023-12-28 16:49:31 -05:00
Hans Goudey
b9b47088bc Cleanup: Remove unnecessary DNA_meshdata_types.h includes
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.
2023-12-20 20:58:38 -05:00
Hans Goudey
19001c9e6c Cleanup: Move attribute domain enum to C++ header, use enum class
Each value is now out of the global namespace, so they can be shorter
and easier to read. Most of this commit just adds the necessary casting
and namespace specification. `enum class` can be forward declared since
it has a specified size. We will make use of that in the next commit.
2023-12-20 13:25:28 -05:00
Hans Goudey
8dd8f932e2 Cleanup: Rename Mesh loop_data to corner_data
Related to #110434, efbee2d606, 7c69c8827b
2023-12-19 20:39:05 -05:00
Hans Goudey
efbee2d606 Mesh: Rename totvert, totedge, and totloop fields
Use the standard "elements_num" naming, and use the "corner" name rather
than the old "loop" name: `verts_num`, `edges_num`, and `corners_num`.
This matches the existing `faces_num` field which was already renamed.

Pull Request: https://projects.blender.org/blender/blender/pulls/116350
2023-12-20 02:21:48 +01:00
Hans Goudey
d093c9075d Cleanup: Check for null before copying datablocks
Avoid relying on the null check inside of `BKE_id_copy_ex`,
which shouldn't really be there.
2023-12-19 13:31:43 -05:00
Hans Goudey
1d0179adbb Cleanup: Move mesh update tags to DNA struct
This is similar to other update tags and update tags for other geometry types.
2023-12-12 18:23:59 -05:00
Hans Goudey
d8497e48e1 Cleanup: Use is_empty() instead of size() == 0 2023-12-11 15:47:11 -05:00
Jacques Lucke
cefdb67db7 Cleanup: return managed pointer when copying geometry component 2023-12-01 11:23:00 +01:00
Hans Goudey
89e3ba4e25 Mesh: Replace auto smooth with node group
Design task: #93551

This PR replaces the auto smooth option with a geometry nodes modifier
that sets the sharp edge attribute. This solves a fair number of long-
standing problems related to auto smooth, simplifies the process of
normal computation, and allows Blender to automatically choose between
face, vertex, and face corner normals based on the sharp edge and face
attributes.

Versioning adds a geometry node group to objects with meshes that had
auto-smooth enabled. The modifier can be applied, which also improves
performance.

Auto smooth is now unnecessary to get a combination of sharp and smooth
edges. In general workflows are changed a bit. Separate procedural and
destructive workflows are available. Custom normals can be used
immediately without turning on the removed auto smooth option.

**Procedural**

The node group asset "Smooth by Angle" is the main way to set sharp
normals based on the edge angle. It can be accessed directly in the add
modifier menu. Of course the modifier can be reordered, muted, or
applied like any other, or changed internally like any geometry nodes
modifier.

**Destructive**
Often the sharp edges don't need to be dynamic. This can give better
performance since edge angles don't need to be recalculated. In edit
mode the two operators "Select Sharp Edges" and "Mark Sharp" can be
used. In other modes, the "Shade Smooth by Angle" controls the edge
sharpness directly.

### Breaking API Changes
- `use_auto_smooth` is removed. Face corner normals are now used
  automatically   if there are mixed smooth vs. not smooth tags. Meshes
  now always use custom normals if they exist.
- In Cycles, the lack of the separate auto smooth state makes normals look
  triangulated when all faces are shaded smooth.
- `auto_smooth_angle` is removed. Replaced by a modifier (or operator)
  controlling the sharp edge attribute. This means the mesh itself
  (without an object) doesn't know anything about automatically smoothing
  by angle anymore.
- `create_normals_split`, `calc_normals_split`, and `free_normals_split`
  are removed, and are replaced by the simpler `Mesh.corner_normals`
  collection property. Since it gives access to the normals cache, it
  is automatically updated when relevant data changes.

Addons are updated here: https://projects.blender.org/blender/blender-addons/pulls/104609

### Tests
- `geo_node_curves_test_deform_curves_on_surface` has slightly different
   results because face corner normals are used instead of interpolated
   vertex normals.
- `bf_wavefront_obj_tests` has different export results for one file
  which mixed sharp and smooth faces without turning on auto smooth.
- `cycles_mesh_cpu` has one object which is completely flat shaded.
  Previously every edge was split before rendering, now it looks triangulated.

Pull Request: https://projects.blender.org/blender/blender/pulls/108014
2023-10-20 16:54:08 +02:00
Falk David
bc7034d9fd CurvesGeometry: Add initial vertex group support
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
2023-09-27 10:26:06 +02:00
Campbell Barton
e955c94ed3 License Headers: Set copyright to "Blender Authors", add AUTHORS
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.
2023-08-16 00:20:26 +10:00
Hans Goudey
dc7979a056 Cleanup: Make geometry set naming more consistent
Remove the "_for_read" suffix from methods to get geometry and geometry
components. That should be considered the default, so the suffix just
adds unnecessary text. This is consistent with the attribute API and
various implicit sharing data access methods.

Use "from_mesh" instead of "create_with_mesh". This is consistent with
the recently used naming for the `IndexMask` API.

Pull Request: https://projects.blender.org/blender/blender/pulls/110738
2023-08-03 17:09:18 +02:00
Hans Goudey
731d296f35 Cleanup: Move mesh related blenkernel headers to C++
See #103343

Pull Request: https://projects.blender.org/blender/blender/pulls/110730
2023-08-02 22:14:18 +02:00
Hans Goudey
95edff7495 Cleanup: Rename mesh custom data fields
Implements the rest of #101689, after 5e9ea9243b.

- `vdata` -> `vert_data`
- `edata` -> `edge_data`
- `pdata` -> `face_data`
- `ldata` -> `loop_data`

A deeper rename of `loop` to `corner` will be proposed as a next
step, and renaming `totvert` and `totedge` can be done separately.

Pull Request: https://projects.blender.org/blender/blender/pulls/110432
2023-07-25 21:15:52 +02:00
Hans Goudey
5e9ea9243b Mesh: Rename "polys" to "faces"
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
2023-07-24 22:06:55 +02:00
Hans Goudey
ec30217755 Cleanup: Simplify access to next face corner in domain interpolation 2023-07-06 13:40:42 -04:00
Hans Goudey
f4124ee02d Cleanup: Move GeometrySet and components to proper namespace
Move `GeometrySet` and `GeometryComponent` and subclasses
to the `blender::bke` namespace. This wasn't done earlier since
these were one of the first C++ classes used throughout Blender,
but now it is common.

Also remove the now-unnecessary C-header, since all users of
the geometry set header are now in C++.

Pull Request: https://projects.blender.org/blender/blender/pulls/109020
2023-06-15 22:18:28 +02:00
Hans Goudey
e5ec04d73c Mesh: Move vertex/edge crease to generic attributes
Store subdivision surface creases in two new named float attributes:
- `crease_vert`
- `crease_edge`
This is similar to 2a56403cb0.

The attributes are naming conventions, so their data type and domain
aren't enforced, and may be interpolated when necessary. Editing tools
and the subdivision surface modifier use the hard-coded name. It might
be best if these were edited as generic attributes in the future, but
in the meantime using generic attributes helps.

The attributes are visible in the list, which is how they're now meant
to be removed. They are now interchangeable with any tool that works
with the generic attribute system-- even tools like vertex paint can
affect creases now.

This is a breaking change. Forward compatibility isn't preserved for
versions before 3.6, and the `crease` property in RNA is removed in
favor of making a smaller API surface area with just the attribute API.
`Mesh.vertex_creases` and `Mesh.edge_creases` now just return the
matching attribute if possible, and are now implemented in Python.
New functions `*ensure` and `*remove` also replace the operators to
add and remove the layers for Python.

A few extrude node test files have to be updated because of different
(now generic) attribute interpolation behavior.

Pull Request: https://projects.blender.org/blender/blender/pulls/108089
2023-06-13 20:23:39 +02:00
Hans Goudey
319b68763f Cleanup: Simplify namespaces in geometry component files 2023-06-08 08:29:15 -04:00
Hans Goudey
3503f7675c Cleanup: Remove unused forward declaration 2023-06-08 08:28:57 -04:00
Sergey Sharybin
c1bc70b711 Cleanup: Add a copyright notice to files and use SPDX format
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/
2023-05-31 16:19:06 +02:00
Jacques Lucke
2cfcb8b0b8 BLI: refactor IndexMask for better performance and memory usage
Goals of this refactor:
* Reduce memory consumption of `IndexMask`. The old `IndexMask` uses an
  `int64_t` for each index which is more than necessary in pretty much all
  practical cases currently. Using `int32_t` might still become limiting
  in the future in case we use this to index e.g. byte buffers larger than
  a few gigabytes. We also don't want to template `IndexMask`, because
  that would cause a split in the "ecosystem", or everything would have to
  be implemented twice or templated.
* Allow for more multi-threading. The old `IndexMask` contains a single
  array. This is generally good but has the problem that it is hard to fill
  from multiple-threads when the final size is not known from the beginning.
  This is commonly the case when e.g. converting an array of bool to an
  index mask. Currently, this kind of code only runs on a single thread.
* Allow for efficient set operations like join, intersect and difference.
  It should be possible to multi-thread those operations.
* It should be possible to iterate over an `IndexMask` very efficiently.
  The most important part of that is to avoid all memory access when iterating
  over continuous ranges. For some core nodes (e.g. math nodes), we generate
  optimized code for the cases of irregular index masks and simple index ranges.

To achieve these goals, a few compromises had to made:
* Slicing of the mask (at specific indices) and random element access is
  `O(log #indices)` now, but with a low constant factor. It should be possible
  to split a mask into n approximately equally sized parts in `O(n)` though,
  making the time per split `O(1)`.
* Using range-based for loops does not work well when iterating over a nested
  data structure like the new `IndexMask`. Therefor, `foreach_*` functions with
  callbacks have to be used. To avoid extra code complexity at the call site,
  the `foreach_*` methods support multi-threading out of the box.

The new data structure splits an `IndexMask` into an arbitrary number of ordered
`IndexMaskSegment`. Each segment can contain at most `2^14 = 16384` indices. The
indices within a segment are stored as `int16_t`. Each segment has an additional
`int64_t` offset which allows storing arbitrary `int64_t` indices. This approach
has the main benefits that segments can be processed/constructed individually on
multiple threads without a serial bottleneck. Also it reduces the memory
requirements significantly.

For more details see comments in `BLI_index_mask.hh`.

I did a few tests to verify that the data structure generally improves
performance and does not cause regressions:
* Our field evaluation benchmarks take about as much as before. This is to be
  expected because we already made sure that e.g. add node evaluation is
  vectorized. The important thing here is to check that changes to the way we
  iterate over the indices still allows for auto-vectorization.
* Memory usage by a mask is about 1/4 of what it was before in the average case.
  That's mainly caused by the switch from `int64_t` to `int16_t` for indices.
  In the worst case, the memory requirements can be larger when there are many
  indices that are very far away. However, when they are far away from each other,
  that indicates that there aren't many indices in total. In common cases, memory
  usage can be way lower than 1/4 of before, because sub-ranges use static memory.
* For some more specific numbers I benchmarked `IndexMask::from_bools` in
  `index_mask_from_selection` on 10.000.000 elements at various probabilities for
  `true` at every index:
  ```
  Probability      Old        New
  0              4.6 ms     0.8 ms
  0.001          5.1 ms     1.3 ms
  0.2            8.4 ms     1.8 ms
  0.5           15.3 ms     3.0 ms
  0.8           20.1 ms     3.0 ms
  0.999         25.1 ms     1.7 ms
  1             13.5 ms     1.1 ms
  ```

Pull Request: https://projects.blender.org/blender/blender/pulls/104629
2023-05-24 18:11:41 +02:00
Hans Goudey
098e58ea24 Attributes: Allow attribute API to create non-deleteable attributes
This can be useful to allow creating these core attributes with shared
arrays. Otherwise CustomData has to be used directly, which is nice
to avoid. This was done in e45ed69349, but not everywhere.
2023-04-28 10:24:32 -04:00
Jacques Lucke
b4d914b676 BLI: support weak users and version in implicit sharing info
The main goal of these changes is to support checking if some data has
been changed over time. This is used by the WIP simulation nodes during
baking to detect which attributes have to be stored in every frame because
they have changed.

By using a combination of a weak user count and a version counter, it is
possible to detect that an attribute (or any data controlled by implicit
sharing) has not been changed with O(1) memory and time. It's still
possible that the data has been changed multiple times and is the same
in the end and beginning of course. That wouldn't be detected using this
mechanism.

The `ImplicitSharingInfo` struct has a new weak user count. A weak
reference is one that does not keep the referenced data alive, but makes sure
that the `ImplicitSharingInfo` itself is not deleted. If some piece of
data has one strong and multiple weak users, it is still mutable. If the
strong user count goes down to zero, the referenced data is freed.
Remaining weak users can check for this condition using `is_expired`.

This is a bit similar to `std::weak_ptr` but there is an important difference:
a weak user can not become a strong user while one can create a `shared_ptr`
from a `weak_ptr`. This restriction is necessary, because some code might
be changing the referenced data assuming that it is the only owner. If
another thread suddenly adds a new owner, the data would be shared again
and the first thread would not have been allowed to modify the data in
the first place.

There is also a new integer version counter in `ImplicitSharingInfo`.
It is incremented whenever some code wants to modify the referenced data.
Obviously, this can only be done when the data is not shared because then
it would be immutable. By comparing an old and new version number of the
same sharing info, one can check if the data has been modified. One has
to keep a weak reference to the sharing info together with the old version
number to ensure that the new sharing info is still the same as the old one.
Without this, it can happen that the sharing info was freed and a new
one was allocated at the same pointer address. Using a strong reference
for this purpose does not work, because then the data would never be
modified because it's shared.
2023-04-28 12:05:00 +02:00
Hans Goudey
8e967cfeaf Mesh: Cache loose vertices
Similar to the cache of loose edges added in 1ea169d90e,
cache the number of loose vertices and which are loose in a bit map.
This can save significant time when drawing large meshes in the
viewport, because recalculations can be avoided when the data doesn't
change, and because many geometry nodes set the loose geometry
caches eagerly when the meshes contain no loose elements.

There are two types of loose vertices:
1. Vertices not used by any edges or faces
   `Mesh.loose_verts()`
2. Vertices not used by any faces (may be used by loose edges)
   `Mesh.verts_no_face()`

Because both are used by Blender in various places, because the cost
is only a bit per vertex (or constant at best) and for design consistency,
we cache both types of loose elements. The bit maps will only be
allocated when they're actually used, but they are already accessed
in a few important places:
- Attribute domain interpolation
- Subdivision surface modifier
- Viewport drawing

Just skipping viewport drawing calculation after certain geometry
nodes setups can have a large impact. Here is the time taken by
viewport loose geometry extraction before and after the change:
- 4 million vertex grid node: 28 ms to 0 ms
- Large molecular nodes setup (curve to mesh node): 104 ms to 0 ms
- Realize instances with 1 million cubes: 131 ms to 0 ms

Pull Request: https://projects.blender.org/blender/blender/pulls/105567
2023-04-22 13:46:11 +02:00
Hans Goudey
7535ab412a Cleanup: Remove redundant "reference" argument to geometry copy
Implicit sharing means attribute ownership is shared between geometry
data-blocks, and the sharing happens automatically. So it's unnecessary
to choose whether to enable it when copying a mesh.
2023-04-19 15:52:56 -04:00
Hans Goudey
e45ed69349 Attributes: Integrate implicit sharing with the attribute API
Add the ability to retrieve implicit sharing info directly from the
C++ attribute API, which simplifies memory usage and performance
optimizations making use of it. This commit uses the additions to
the API to avoid copies in a few places:
- The "rest_position" attribute in the mesh modifier stack
- Instance on Points node
- Instances to points node
- Mesh to points node
- Points to vertices node

Many files are affected because in order to include the new information
in the API's returned data, I had to switch a bunch of types from
`VArray` to `AttributeReader`. This generally makes sense anyway, since
it allows retrieving the domain, which wasn't possible before in some
cases. I overloaded the `*` deference operator for some syntactic sugar
to avoid the (very ugly) `.varray` that would be necessary otherwise.

Pull Request: https://projects.blender.org/blender/blender/pulls/107059
2023-04-19 11:21:06 +02:00
Hans Goudey
d818d05415 Cleanup: Remove unnecessary attribute provider callbacks
We don't use the callbacks that create virtual arrays from the custom data
anymore, they just add extra indirection. The only non-obvious case was
the crease attribute which had a setter function. Replace that with an
attribute validator like the other similar attributes.

Pull Request: https://projects.blender.org/blender/blender/pulls/107088
2023-04-18 17:13:38 +02:00
Hans Goudey
2a4323c2f5 Mesh: Move edges to a generic attribute
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
2023-04-17 13:47:41 +02:00
Hans Goudey
7966cd16d6 Mesh: Replace MPoly struct with offset indices
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
2023-04-04 20:39:28 +02:00
Sergey Sharybin
d32d787f5f Clang-Format: Allow empty functions to be single-line
For example

```
OIIOOutputDriver::~OIIOOutputDriver()
{
}
```

becomes

```
OIIOOutputDriver::~OIIOOutputDriver() {}
```

Saves quite some vertical space, which is especially handy for
constructors.

Pull Request: https://projects.blender.org/blender/blender/pulls/105594
2023-03-29 16:50:54 +02:00
Hans Goudey
5c3f4195b6 Cleanup: Move poly topology lookup functions to C++ header
Standardize naming, use spans and references for input parameters,
and improve documentation. Now the functions expect the lookups to
succeed as well, they will fail and assert otherwise.

The functions are also simple enough that it likely makes sense to keep
them all inlined
2023-03-22 17:11:41 -04:00