This implements the core changes for this design: https://devtalk.blender.org/t/grease-pencil-integration-into-geometry-nodes/31220
The changes include:
* Add `CustomData` for layer attributes
* Add attribute support for the `GreasePencilComponent` to read/write layer attributes. Also introduces a `Layer` domain.
* Implement a `GreasePencilLayerFieldContext` and make `GeometryFieldContext` work with grease pencil layers.
* Implement `Set Position` node for `Grease Pencil`.
Note: These changes are only accessible/visible with the `Grease Pencil 3.0` experimental flag enabled.
Co-authored-by: Jacques Lucke <jacques@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/112535
This makes the code reusable in a few more places,
particularly by tests for a new boolean implementation
also defined in the geometry module.
It also makes the way some primitives are reused among
different nodes a bit clearer.
Pull Request: https://projects.blender.org/blender/blender/pulls/112255
Now that specific menus can be searched directly (see 7f9d51853c),
there is no need to maintain separate search functionality for adding
nodes. This PR removes the add node search. In a way this brings us
closer to the `NodeItem` situation before, but the setup is more
flexible since the menus are more standard and easier to customize.
In the few ways we customized the node search items before, this gives
us the same results as before. Overall the searching is less flexible,
but I think that is just a tradeoff we have to accept for the simplicity
of searching menus. In the future menus could be made more dynamic,
with each builtin node's menu path stored on the node type, similar to
assets. That might be a nice compromise. In the meantime this code
is just dead weight.
Pull Request: https://projects.blender.org/blender/blender/pulls/112056
Goals of the refactor:
* Internal support for baking individual simulation zones (not exposed in the UI yet).
* More well-defined access to simulation data in geometry nodes. Especially, it
should be more obvious where data is modified. A similar approach should also
work for the Bake node.
Previously, there were a bunch of simulation specific properties in `GeoNodesModifierData`
and then the simulation input and output nodes would have to figure out what to do with that
data. Now, there is a new `GeoNodesSimulationParams` which controls the behavior of
simulation zones. Contrary to before, different simulation zones can now be handled
independently, even if that is not really used yet. `GeoNodesSimulationParams` has to be
subclassed by a user of the geometry nodes API. The subclass controls what each simulation
input and output node does. This some of the logic that was part of the node before, into
the modifier.
The way we store simulation data is "transposed". Previously, we stored zone data per
frame, but now we store frame data per zone. This allows different zones to be more
independent. Consequently, the way the simulation cache is accessed changed. I kept
things simpler for now, avoiding many of the methods we had before, and directly
accessing the data more often which is often simple enough. This change also makes
it theoretically possible to store baked data for separate zones independently.
A downside of this is, that existing baked data can't be read anymore. We don't really
have compatibility guarantees for this format yet, so it's ok. Users will have to bake again.
The bake folder for the modifier now contains an extra subfolder for every zone.
Drawing the cached/baked frames in the timeline is less straight forward now. Currently,
it just draws the state of one of the zones, which usually is identical to that of all other
zones. This will change in the future though, and then the timeline drawing also needs
some new UI work.
Pull Request: https://projects.blender.org/blender/blender/pulls/111623
Include counts of some headers while making full blender build:
- BLI_color.hh 1771 -> 1718
- BLI_math_color.h 1828 -> 1783
- BLI_math_vector.hh 496 -> 405
- BLI_index_mask.hh 1341 -> 1267
- BLI_task.hh 958 -> 903
- BLI_generic_virtual_array.hh 509 -> 435
- IMB_colormanagement.h 437 -> 130
- GPU_texture.h 806 -> 780
- FN_multi_function.hh 331 -> 257
Note: DNA_node_tree_interface_types.h needs color include only
for the currently unused (but soon to be used) socket_color function.
Future step is to figure out how to include
DNA_node_tree_interface_types.h less.
Pull Request: #111113
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.
The goal here is to reduce the number of files that need to be edited when
adding a new node. To register a node, one currently has to add a line to
`node_geometry_register.cc` and `node_geometry_register.hh` (for geometry
nodes). Those files can be generated automatically.
There is a new `NOD_REGISTER_NODE` macro that nodes can use to register
themselves. The macro is then discovered by `discover_nodes.py` that generates
code that calls all the registration functions. The script also works when the
register functions are in arbitrary namespaces. This allows simplifying the node
code as well.
In the past I tried a few times to get auto-registration working without resorting to
code generation, but that never ended up working. The general idea for that would
be to use non-trivial initialization for static variables. The issue always ends up
being that the linker just discards those variables, because they are unused and it
doesn't care if there are side effects in the initialization.
Related discussion regarding using Python for code generation:
https://devtalk.blender.org/t/code-generation-with-python/30558
Pull Request: https://projects.blender.org/blender/blender/pulls/110686
Add three new nodes for operations and inputs specific to
node group operators.
- **Selection** Whether elements are selected in the viewport
- **Set Selection** Sets the edit/sculpt selection, on the point,
face, or curve domains
- **3D Cursor** Gives the location and rotation of the 3D cursor,
in the local space of the modified object.
- **Face Set** The face set value from mesh sculpt mode,
and whether the attribute exists.
- **Set Face Set** Set sculpt face set values.
In the add menu and search, the nodes are only visible in the
"Tool" context of the geometry node editor. They also give
errors when executed by a modifier.
Pull Request: https://projects.blender.org/blender/blender/pulls/109517
This adds support for running a set of nodes repeatedly. The number
of iterations can be controlled dynamically as an input of the repeat
zone. The repeat zone can be added in via the search or from the
Add > Utilities menu.
The main use case is to replace long repetitive node chains with a more
flexible alternative. Technically, repeat zones can also be used for
many other use cases. However, due to their serial nature, performance
is very sub-optimal when they are used to solve problems that could
be processed in parallel. Better solutions for such use cases will
be worked on separately.
Repeat zones are similar to simulation zones. The major difference is
that they have no concept of time and are always evaluated entirely in
the current frame, while in simulations only a single iteration is
evaluated per frame.
Stopping the repetition early using a dynamic condition is not yet
supported. "Break" functionality can be implemented manually using
Switch nodes in the loop for now. It's likely that this functionality
will be built into the repeat zone in the future.
For now, things are kept more simple.
Remaining Todos after this first version:
* Improve socket inspection and viewer node support. Currently, only
the first iteration is taken into account for socket inspection
and the viewer.
* Make loop evaluation more lazy. Currently, the evaluation is eager,
meaning that it evaluates some nodes even though their output may not
be required.
Pull Request: https://projects.blender.org/blender/blender/pulls/109164
When we don't need to preserve a persistent cache, we can use
the geometry from the last frame directly rather than copying it.
Though implicit lets us avoid copying large data arrays when they
aren't changed, this can still give a large improvement for something
like particle simulation where the majority of the data was copied
every frame.
Pull Request: https://projects.blender.org/blender/blender/pulls/109742
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/
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
See: https://projects.blender.org/blender/blender/issues/103343
Changes:
1. Added `BKE_node.hh` file. New file includes old one.
2. Functions moved to new file. Redundant `(void)`, `struct` are removed.
3. All cpp includes replaced from `.h` on `.hh`.
4. Everything in `BKE_node.hh` is on `blender::bke` namespace.
5. All implementation functions moved in namespace.
6. Function names (`BKE_node_*`) changed to `blender::bke::node_*`.
7. `eNodeSizePreset` now is a class, with renamed items.
Pull Request: https://projects.blender.org/blender/blender/pulls/107790
The "Evaluate at Index" and "Sample Index" nodes are exactly the same
once they retrieve the values to copy and the indices (apart from the
clamping option anyway). This also allows devirtualizing the index input
in the evaluate at index node like the sample index node.
This adds support for building simulations with geometry nodes. A new
`Simulation Input` and `Simulation Output` node allow maintaining a
simulation state across multiple frames. Together these two nodes form
a `simulation zone` which contains all the nodes that update the simulation
state from one frame to the next.
A new simulation zone can be added via the menu
(`Simulation > Simulation Zone`) or with the node add search.
The simulation state contains a geometry by default. However, it is possible
to add multiple geometry sockets as well as other socket types. Currently,
field inputs are evaluated and stored for the preceding geometry socket in
the order that the sockets are shown. Simulation state items can be added
by linking one of the empty sockets to something else. In the sidebar, there
is a new panel that allows adding, removing and reordering these sockets.
The simulation nodes behave as follows:
* On the first frame, the inputs of the `Simulation Input` node are evaluated
to initialize the simulation state. In later frames these sockets are not
evaluated anymore. The `Delta Time` at the first frame is zero, but the
simulation zone is still evaluated.
* On every next frame, the `Simulation Input` node outputs the simulation
state of the previous frame. Nodes in the simulation zone can edit that
data in arbitrary ways, also taking into account the `Delta Time`. The new
simulation state has to be passed to the `Simulation Output` node where it
is cached and forwarded.
* On a frame that is already cached or baked, the nodes in the simulation
zone are not evaluated, because the `Simulation Output` node can return
the previously cached data directly.
It is not allowed to connect sockets from inside the simulation zone to the
outside without going through the `Simulation Output` node. This is a necessary
restriction to make caching and sub-frame interpolation work. Links can go into
the simulation zone without problems though.
Anonymous attributes are not propagated by the simulation nodes unless they
are explicitly stored in the simulation state. This is unfortunate, but
currently there is no practical and reliable alternative. The core problem
is detecting which anonymous attributes will be required for the simulation
and afterwards. While we can detect this for the current evaluation, we can't
look into the future in time to see what data will be necessary. We intend to
make it easier to explicitly pass data through a simulation in the future,
even if the simulation is in a nested node group.
There is a new `Simulation Nodes` panel in the physics tab in the properties
editor. It allows baking all simulation zones on the selected objects. The
baking options are intentially kept at a minimum for this MVP. More features
for simulation baking as well as baking in general can be expected to be added
separately.
All baked data is stored on disk in a folder next to the .blend file. #106937
describes how baking is implemented in more detail. Volumes can not be baked
yet and materials are lost during baking for now. Packing the baked data into
the .blend file is not yet supported.
The timeline indicates which frames are currently cached, baked or cached but
invalidated by user-changes.
Simulation input and output nodes are internally linked together by their
`bNode.identifier` which stays the same even if the node name changes. They
are generally added and removed together. However, there are still cases where
"dangling" simulation nodes can be created currently. Those generally don't
cause harm, but would be nice to avoid this in more cases in the future.
Co-authored-by: Hans Goudey <h.goudey@me.com>
Co-authored-by: Lukas Tönne <lukas@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/104924
Eager bounds calculation for cylindrical and spherical primitive nodes,
implemented in constant time rather than as a loop over all positions.
Takes into account the segments count of the circle from which they
are constructed. Solution of the task #105551.
Pull Request: https://projects.blender.org/blender/blender/pulls/105743
Geometry Nodes: SDF Volume nodes milestone 1
Adds initial support for SDF volume creation and manipulation.
`SDF volume` is Blender's name of an OpenVDB grid of type Level Set.
See the discussion about naming in #91668.
The new nodes are:
- Mesh to SDF Volume: Converts a mesh to an SDF Volume
- Points to SDF Volume: Converts points to an SDF Volume
- Mean Filter SDF Volume: Applies a Mean Filter to an SDF
- Offset SDF Volume: Applies an offset to an SDF
- SDF Volume Sphere: Creates an SDF Volume in the shape of a sphere
For now an experimental option `New Volume Nodes` needs to be
enabled in Blender preferences for the nodes to be visible.
See the current work plan for Volume Nodes in #103248.
Pull Request: https://projects.blender.org/blender/blender/pulls/105090
Straightforward port. I took the oportunity to remove some C vector
functions (ex: copy_v2_v2).
This makes some changes to DRWView to accomodate the alignement
requirements of the float4x4 type.
Straightforward port. I took the oportunity to remove some C vector
functions (ex: `copy_v2_v2`).
This makes some changes to DRWView to accomodate the alignement
requirements of the float4x4 type.
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
This is essentially a left-over from the initial transition to fields where this was
forgotten. The mesh primitive nodes used to create a named uv map attribute
with a hard-coded name. The standard way to deal with that in geometry nodes
now is to output the attribute as a socket instead. The user can then decide
to store it as a named attribute or not.
The benefits of not always storing the named attribute in the node are:
* Improved performance and lower memory usage when the uv map is not
used.
* It's more obvious that there actually is a uv map.
* The hard-coded name was inconsistent.
The versioning code inserts a new Store Named Attribute node that
stores the uv map immediatly. In many cases, users can probably just
remove this node without affecting their final result, but we can't
detect that.
There is one behavior change which is that the stored uv map will be
a 3d vector instead of a 2d vector which is what the nodes originally created.
We could store the uv map as 2d vector inthe Store Named Attribute node,
but that has the problem that older Blender versions don't support this
and would crash immediately. Users can just change this to 2d vector
manually if they don't care about forward compatibility.
There is a plan to support 2d vectors more natively in geometry nodes: T92765.
This change breaks forward compatibility in the case when the uv map
was used.
Differential Revision: https://developer.blender.org/D16637
The main goal here is to move towards more self contained node
definitions. Previously, one would have to change `blenkernel` to
add a new node which is not necessary anymore. There is no need
for all these register functions to "leak out" of the nodes module.
Differential Revision: https://developer.blender.org/D16612
This patch contains an initial set of nodes to access basic
mesh topology information, as explored in T100020.
The nodes allow six direct topology mappings for meshes:
- **Corner -> Face** The face a corner is in, the index in the face
- **Vertex -> Edge** Choose an edge attached to the vertex
- **Vertex -> Corner** Choose a corner attached to the vertex
- **Corner -> Edge** The next and previous edge at each face corner
- **Corner -> Vertex** The vertex associated with a corner
- **Corner -> Corner** Offset a corner index within a face
And two new topology mappings for curves:
- **Curve -> Points** Choose a point within a curve
- **Point -> Curve** The curve a point is in, the index in the curve
The idea is that some of the 16 possible mesh mappings are more
important, and that this is a useful set of nodes to start exploring
this area. For mappings with an arbitrary number of connections, we
must sort them and use an index to choose a single element, because
geometry nodes does not support list fields. Note that the sort
index has repeating behavior as it goes over the "Total" number of
connections, and negative sort indices choose from the end.
Currently which of the "start" elements is used is determined by the
field context, so the "Field at Index" and "Interpolate Domain" nodes
will be quite important. Also, currently the "Sort Index" inputs are
clamped to the number of connections.
One important feature that isn't implemented here is using the winding
order for the output elements. This can be a separate mode for some
of these nodes. It will be optional because of the performance impact.
There are several todos for separate commits after this:
- Rename "Control Point Neighbors" to be consistent with this naming
- Version away the "Vertex Neighbors" node which is fully redundant now
- Implement a special case for when no weights are used for performance
- De-duplicating some of the sorting logic between the nodes
- Improve performance and memory use of topology mappings
- Look into caching some of the mappings on meshes
Differential Revision: https://developer.blender.org/D16029
This patch replaces the existing transfer attribute node with three
nodes, "Sample Nearest Surface", "Sample Index", and "Sample Nearest".
This follows the design in T100010, allowing for new nodes like UV
sampling in the future. There is versioning so the new nodes replace
the old ones and are relinked as necessary.
The "Sample Nearest Surface" node is meant for the more complex
sampling algorithms that only work on meshes and interpolate
values inside of faces.
The new "Sample Index" just retrieves attributes from a geometry at
specific indices. It doesn't have implicit behavior like the old
transfer mode, which should make it more predictable. In order to not
change the behavior from existing files, the node has a has a "Clamp",
which is off by default for consistency with the "Field at Index" node.
The "Sample Nearest" node returns the index of the nearest element
on a geometry. It can be combined with the "Sample Index" node for
the same functionality as the old transfer node. This node can support
curves in the future.
Backwards compatibility is handled by versioning, but old versions can
not understand these nodes. The warning from 680fa8a523 should make
this explicit in 3.3 and earlier.
Differential Revision: https://developer.blender.org/D15909
The purpose of `NodeTreeRef` was to speed up various queries on a read-only
`bNodeTree`. Not that we have runtime data in nodes and sockets, we can also
store the result of some queries there. This has some benefits:
* No need for a read-only separate node tree data structure which increased
complexity.
* Makes it easier to reuse cached queries in more parts of Blender that can
benefit from it.
A downside is that we loose some type safety that we got by having different
types for input and output sockets, as well as internal and non-internal links.
This patch also refactors `DerivedNodeTree` so that it does not use
`NodeTreeRef` anymore, but uses `bNodeTree` directly instead.
To provide a convenient API (that is also close to what `NodeTreeRef` has), a
new approach is implemented: `bNodeTree`, `bNode`, `bNodeSocket` and `bNodeLink`
now have C++ methods declared in `DNA_node_types.h` which are implemented in
`BKE_node_runtime.hh`. To make this work, `makesdna` now skips c++ sections when
parsing dna header files.
No user visible changes are expected.
Differential Revision: https://developer.blender.org/D15491
OpenVDB crashes when the determinant of the grid transformation is
too small. The solution is too detect when the determinant is too small
and to replace the grid with an empty one. If possible the translation
and rotation of the grid remains unchanged.
Differential Revision: https://developer.blender.org/D15806
The separate geometry and delete geometry nodes often invert the
selection so that deleting elements from a geometry can be implemented
as copying the opposite selection of elements. This should make the two
nodes faster in some cases, since the generic versions of selection
creation functions (i.e. from d3a1e9cbb9) are used instead
of the single threaded code that was used for this node.
The change also makes the deletion/separation code easier to
understand because it doesn't have to pass around the inversion.
This commit re-implements the resample curve node to use the new curves
type instead of CurveEval. The largest changes come from the need to
keep track of offsets into the point attribute arrays, and the fact
that the attributes for all curves are stored in a flat array.
Another difference is that a bit more of the logic is handled by
building of the field network inputs. The idea is to let the field
evaluator handle potential optimizations while making the rest of the
code simpler.
When resampling 1 million small poly curves,the node is about 6
times faster compared to 3.1 on my hardware (500ms to 80ms).
This also adds support for Catmull Rom curve inputs.
Differential Revision: https://developer.blender.org/D14435