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
The fact that blenlib doesn't know about the set of attribute types is
actually an important detail right now that can influence how things
are designed. Longer term it would be good to consolidate many of
these attribute propagation algorithms anyway.
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.
Change the implementation of the raycast and sample nearest surface
node to split separate loops into separate multi-functions. This
clarifies the task of each function, gives more information to the
field evaluator, and gives more opportunity for memory reuse.
Sampling mesh attributes with triangle barycentric weights is now
implemented in a single place. Two other new multi-functions
handle conversion of sampled positions into barycentric weights.
Normalizing the ray directions for the raycast node is split out
too, so it can be skipped in some cases in the future.
The mesh attribute interpolator helper class is also removed,
since it didn't give much benefit over a more functional approach.
I didn't notice a performance improvement from this change.
Pull Request: https://projects.blender.org/blender/blender/pulls/107563
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
This patch implements the Mask node for the realtime compositor. The
evaluation of the mask is not GPU accelerated, but is cached as a form
of temporary implementation until we implement a GPU evaluator for
masks.
One limitation currently is that we do not redraw the viewport while the
mask is getting edited by the user, because always doing that will be
redundant in most situations, and conditioning the redraw requires a lot
of work that should be handled outside of this patch.
This is similar to the Texture node implementation in 151a53110c.
Pull Request: https://projects.blender.org/blender/blender/pulls/107464
Node socket tooltips suffered from several issues.
- Some could not be translated because they were not properly
extracted, so extraction macros were added.
- Some were extracted but included newlines at the end which did not
get translated, such as `ss << TIP_("Geometry:\n")`, changed to
`ss << TIP_("Geometry:") << "\n"`.
- Some translations were not functional, such as:
`TIP_(attributes_num == 1 ? " Named Attribute" : " Named Attributes");`
because `TIP_()` needs to be around a single string.
- Some extraction macros had no effect and were removed, such as:
`.description(N_(leading_out_description));`
This is a no-op macro which can be used only around a string literal.
Pull Request: https://projects.blender.org/blender/blender/pulls/107257
It arguably reads easier if simple operations like reading from indices
of an array don't each get their own line. Also the same corner
attribute sampling was repeated in a few places. And add a new
function to sample normals from the corner domain, and use
lower level arguments to the lower level functions (i.e. not just
a mesh pointer, but the necessary data arrays).
Usually anonymous attributes are removed earlier, but otherwise
the extrude node can end up doing extra work.We need to retrieve the
propagation set and remove not-propagated attributes. And also fix
a case where in vertex mode, the offsets array could be freed when
the mesh is resized.
A `BitGroupVector` is a compact data structure that allows storing multiple
bits per element, for example 5 bits per vertex. The implementation is
mostly just a wrapper around `BitVector`. There is some additional logic
to make sure that the bit span of every element is bounded (according
to the `is_bounded_span` function). This makes it more efficient to operate
on groups as a whole (e.g. `or` one group into another). In some sense,
this data structure can also be interpreted as a 2D bit array. Functions
like `append` can be added when they become necessary.
The new data structure is used to replace some `MultiValueMap` in
geometry nodes. This simplifies the code.
This patch implements the Corner Pin node for the realtime compositor.
This is different from the existing compositor in that single value
inputs produce single value outputs, instead of assuming the size of the
render.
Pull Request: https://projects.blender.org/blender/blender/pulls/107363
Use a grain size for the final tree creation/balancing/lookup that
depends on the average size of each tree. When the trees are larger,
fewer trees are processed on each thread and vice versa. I didn't notice
a difference when there are hundreds of thousands of groups, but
when there are few (i.e. around the number of cores), I noticed a 6x
performance improvement, from over 1 second to around 0.2 s.
Note that generally the performance is better with many small groups,
because the creation and balancing of trees is single threaded.
If the Group ID input isn't a single value, it's likely to be a span,
so making sure that's true should generally be free, at least in
most cases. This brought a test with 1 million points from 37
to 34 ms, roughtly an 8% improvement.
Needed for the simulation zone addition to the add menu search.
Link-drag search isn't supported yet, but a similar change should be
possible there.
Now the search item exposed through the public nodes namespace returns
several items directly, and the "after add function" is just handled as
a sub-case of that for convenience.
This triggered an assert during evaluation, because the group inputs
were first requested and later the set unused, which is not allowed.
The issue was likely introduced in 258678916f.
Currently `Mesh to Volume` creates a volume using
`openvdb::tools::meshToVolume` which is then filled with the specified
density and the class set to Fog Volume. This is wrong because
`meshToVolume` creates a signed distance field by default that needs
to be converted to a Fog Volume with `openvdb::tools::sdfToFogVolume`
to get a proper Fog volume.
Here is the description of what that function does (from OpenVDB):
"The active and negative-valued interior half of the narrow band
becomes a linear ramp from 0 to 1; the inactive interior becomes
active with a constant value of 1; and the exterior, including the
background and the active exterior half of the narrow band, becomes
inactive with a constant value of 0. The interior, though active,
remains sparse."
This means with this commit old files will not look the same.
There is no way to version this as the options for external band width
and not filling the volume is removed (they don't make any sense for a
proper fog volume).
Pull Request: https://projects.blender.org/blender/blender/pulls/107279
This patch refactors the static cache manager to be split into multiple
smaller Cached Resources Containers. This is a non factional change, and
was done to simplify future implementations of cached resources as they
become more elaborate.
This patch implements the Texture node for the realtime compositor. The
evaluation of the texture is not GPU accelerated, but is cached as a
form of temporary implementation since the Texture node is deprecated
and will be removed in the future. Furthermore, texture node evaluation
is not supported for now.
This patch also introduces the concept of an ID static cache, which
uses the DrawDataList mechanism to invalidate the cache as needed,
consequently, a DrawDataList was added to the Tex ID structure.
An improvement that should be implemented outside of this patch is to
implement support for proxy textures in results to avoid redundant
copies in the execute method of the texture node. This should be
straightforward bit will be implemented in a separate patch.
Pull Request: https://projects.blender.org/blender/blender/pulls/107291
The String to Curves node allows selecting various metrics for the
characters. Size is the absolute height between two lines, and is
correctly marked as a distance. Character, Word and Line Spacing, on
the other hand, do not represent any distance, but are proportional to
the base size and should not have distance units.
This commit simply removes the properties' `PROP_DISTANCE` subtype.
Pull Request: https://projects.blender.org/blender/blender/pulls/106660
This patch adds missing domain priority specifications for the Box and
Ellipse mask. This is a non-functional change because the inputs
happened to be properly ordered anyways.
Many nodes output anonymous attributes (e.g. the top selection in the
Cylinder node). The actual data is only contained in the geometry output
though. The field output just contains a reference to this data (essentially
just the generated name of an attribute). This data can be output even
without computing the geometry itself.
As of right now, this only simplifies the code a bit, but does not have a
bigger impact, because to use the anonymous attribute, you always need
the geometry anyway. However, with the upcoming simulation nodes,
it's possible to create the anonymous attribute in one frame and to access
it in another frame. In the other frame we only need the anonymous
attribute reference and don't have to create the actual geometry again.
Skipping creating the actual attribute on the geometry can have a
significant performance benefit.
- Implement mesh creation in GeometrySet agnostic way, with less context
- Remove useless comments
- Use a field to clamp crease values instead of clamping when copying
- Small variable name tweaks
- Use `BKE_subdiv_new_from_mesh` instead of "update"
- Remove crease layers before writing, avoiding potential copy
The socket indices in `bNode` and their corresponding `lf::Node`
don't match exactly, because `lf::Node` does not contain the
unavailable sockets. A simple mapping from `bNodeSocket` index
to `lf::Socket` index is required for future work. For now it
only removes the need for various tempory vectors.
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
The node outputs the index of the closest element to itself. See #102387
for the original design.
This is different from the Sample Nearest node in two important ways:
* It does not have a geometry input, instead the geometry is taken from the
field evaluation context.
* The node can exclude the "current" element from the search.
* The group id input can be used to build subsets of elements that only
consider each other as neighbors and ignore elements with other ids.
Pull Request: https://projects.blender.org/blender/blender/pulls/104619