Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-09-23 21:56:35 +0300
committerHans Goudey <h.goudey@me.com>2022-09-23 21:56:35 +0300
commitdedc679ecabb43e79b0160a7c64bbd616adfa829 (patch)
treec91dd88b31fb20cfeed77c65b6afff6de1977d18 /source/blender/blenloader
parentd5554cdc7c900880571c4265c9f3f7a7cfec6071 (diff)
Geometry Nodes: Split transfer attribute node
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 680fa8a523e0 should make this explicit in 3.3 and earlier. Differential Revision: https://developer.blender.org/D15909
Diffstat (limited to 'source/blender/blenloader')
-rw-r--r--source/blender/blenloader/intern/versioning_300.cc160
-rw-r--r--source/blender/blenloader/intern/versioning_common.cc29
-rw-r--r--source/blender/blenloader/intern/versioning_common.h11
3 files changed, 194 insertions, 6 deletions
diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc
index 8f1f2fa2c17..9ea662ac000 100644
--- a/source/blender/blenloader/intern/versioning_300.cc
+++ b/source/blender/blenloader/intern/versioning_300.cc
@@ -1791,6 +1791,147 @@ static void version_fix_image_format_copy(Main *bmain, ImageFormatData *format)
}
}
+static void version_geometry_nodes_replace_transfer_attribute_node(bNodeTree *ntree)
+{
+ using namespace blender;
+ /* Otherwise `ntree->typeInfo` is null. */
+ ntreeSetTypes(NULL, ntree);
+ LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
+ if (node->type != GEO_NODE_TRANSFER_ATTRIBUTE_DEPRECATED) {
+ continue;
+ }
+ bNodeSocket *old_geometry_socket = nodeFindSocket(node, SOCK_IN, "Source");
+ const NodeGeometryTransferAttribute *storage = (const NodeGeometryTransferAttribute *)
+ node->storage;
+ switch (storage->mode) {
+ case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED: {
+ bNode *sample_nearest_surface = nodeAddStaticNode(
+ NULL, ntree, GEO_NODE_SAMPLE_NEAREST_SURFACE);
+ sample_nearest_surface->parent = node->parent;
+ sample_nearest_surface->custom1 = storage->data_type;
+ sample_nearest_surface->locx = node->locx;
+ sample_nearest_surface->locy = node->locy;
+ static auto socket_remap = []() {
+ Map<std::string, std::string> map;
+ map.add_new("Attribute", "Value_Vector");
+ map.add_new("Attribute_001", "Value_Float");
+ map.add_new("Attribute_002", "Value_Color");
+ map.add_new("Attribute_003", "Value_Bool");
+ map.add_new("Attribute_004", "Value_Int");
+ map.add_new("Source", "Mesh");
+ map.add_new("Source Position", "Sample Position");
+ return map;
+ }();
+ node_tree_relink_with_socket_id_map(*ntree, *node, *sample_nearest_surface, socket_remap);
+ break;
+ }
+ case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST: {
+ /* These domains weren't supported by the index transfer mode, but were selectable. */
+ const eAttrDomain domain = ELEM(storage->domain, ATTR_DOMAIN_INSTANCE, ATTR_DOMAIN_CURVE) ?
+ ATTR_DOMAIN_POINT :
+ eAttrDomain(storage->domain);
+
+ /* Use a sample index node to retrieve the data with this node's index output. */
+ bNode *sample_index = nodeAddStaticNode(NULL, ntree, GEO_NODE_SAMPLE_INDEX);
+ NodeGeometrySampleIndex *sample_storage = static_cast<NodeGeometrySampleIndex *>(
+ sample_index->storage);
+ sample_storage->data_type = storage->data_type;
+ sample_storage->domain = domain;
+ sample_index->parent = node->parent;
+ sample_index->locx = node->locx + 25.0f;
+ sample_index->locy = node->locy;
+ if (old_geometry_socket->link) {
+ nodeAddLink(ntree,
+ old_geometry_socket->link->fromnode,
+ old_geometry_socket->link->fromsock,
+ sample_index,
+ nodeFindSocket(sample_index, SOCK_IN, "Geometry"));
+ }
+
+ bNode *sample_nearest = nodeAddStaticNode(NULL, ntree, GEO_NODE_SAMPLE_NEAREST);
+ sample_nearest->parent = node->parent;
+ sample_nearest->custom1 = storage->data_type;
+ sample_nearest->custom2 = domain;
+ sample_nearest->locx = node->locx - 25.0f;
+ sample_nearest->locy = node->locy;
+ if (old_geometry_socket->link) {
+ nodeAddLink(ntree,
+ old_geometry_socket->link->fromnode,
+ old_geometry_socket->link->fromsock,
+ sample_nearest,
+ nodeFindSocket(sample_nearest, SOCK_IN, "Geometry"));
+ }
+ static auto sample_nearest_remap = []() {
+ Map<std::string, std::string> map;
+ map.add_new("Source Position", "Sample Position");
+ return map;
+ }();
+ node_tree_relink_with_socket_id_map(*ntree, *node, *sample_nearest, sample_nearest_remap);
+
+ static auto sample_index_remap = []() {
+ Map<std::string, std::string> map;
+ map.add_new("Attribute", "Value_Vector");
+ map.add_new("Attribute_001", "Value_Float");
+ map.add_new("Attribute_002", "Value_Color");
+ map.add_new("Attribute_003", "Value_Bool");
+ map.add_new("Attribute_004", "Value_Int");
+ map.add_new("Source Position", "Sample Position");
+ return map;
+ }();
+ node_tree_relink_with_socket_id_map(*ntree, *node, *sample_index, sample_index_remap);
+
+ nodeAddLink(ntree,
+ sample_nearest,
+ nodeFindSocket(sample_nearest, SOCK_OUT, "Index"),
+ sample_index,
+ nodeFindSocket(sample_index, SOCK_IN, "Index"));
+ break;
+ }
+ case GEO_NODE_ATTRIBUTE_TRANSFER_INDEX: {
+ bNode *sample_index = nodeAddStaticNode(NULL, ntree, GEO_NODE_SAMPLE_INDEX);
+ NodeGeometrySampleIndex *sample_storage = static_cast<NodeGeometrySampleIndex *>(
+ sample_index->storage);
+ sample_storage->data_type = storage->data_type;
+ sample_storage->domain = storage->domain;
+ sample_storage->clamp = 1;
+ sample_index->parent = node->parent;
+ sample_index->locx = node->locx;
+ sample_index->locy = node->locy;
+ const bool index_was_linked = nodeFindSocket(node, SOCK_IN, "Index")->link != nullptr;
+ static auto socket_remap = []() {
+ Map<std::string, std::string> map;
+ map.add_new("Attribute", "Value_Vector");
+ map.add_new("Attribute_001", "Value_Float");
+ map.add_new("Attribute_002", "Value_Color");
+ map.add_new("Attribute_003", "Value_Bool");
+ map.add_new("Attribute_004", "Value_Int");
+ map.add_new("Source", "Geometry");
+ map.add_new("Index", "Index");
+ return map;
+ }();
+ node_tree_relink_with_socket_id_map(*ntree, *node, *sample_index, socket_remap);
+
+ if (!index_was_linked) {
+ /* Add an index input node, since the new node doesn't use an implicit input. */
+ bNode *index = nodeAddStaticNode(NULL, ntree, GEO_NODE_INPUT_INDEX);
+ index->parent = node->parent;
+ index->locx = node->locx - 25.0f;
+ index->locy = node->locy - 25.0f;
+ nodeAddLink(ntree,
+ index,
+ nodeFindSocket(index, SOCK_OUT, "Index"),
+ sample_index,
+ nodeFindSocket(sample_index, SOCK_IN, "Index"));
+ }
+ break;
+ }
+ }
+ /* The storage must be feeed manually because the node type isn't defined anymore. */
+ MEM_freeN(node->storage);
+ nodeRemoveNode(NULL, ntree, node, false);
+ }
+}
+
/* NOLINTNEXTLINE: readability-function-size */
void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
@@ -2803,7 +2944,8 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
ntree, GEO_NODE_INPUT_MESH_EDGE_ANGLE, "Angle", "Unsigned Angle");
version_node_output_socket_name(
ntree, GEO_NODE_INPUT_MESH_ISLAND, "Index", "Island Index");
- version_node_input_socket_name(ntree, GEO_NODE_TRANSFER_ATTRIBUTE, "Target", "Source");
+ version_node_input_socket_name(
+ ntree, GEO_NODE_TRANSFER_ATTRIBUTE_DEPRECATED, "Target", "Source");
}
}
}
@@ -3405,12 +3547,10 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
/* Convert mix rgb node to new mix node and add storage. */
- {
- FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
- versioning_replace_legacy_mix_rgb_node(ntree);
- }
- FOREACH_NODETREE_END;
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ versioning_replace_legacy_mix_rgb_node(ntree);
}
+ FOREACH_NODETREE_END;
/* Face sets no longer store whether the corresponding face is hidden. */
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
@@ -3437,5 +3577,13 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+
+ /* Split the transfer attribute node into multiple smaller nodes. */
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_GEOMETRY) {
+ version_geometry_nodes_replace_transfer_attribute_node(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
}
}
diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc
index 823385727e1..c87983f1287 100644
--- a/source/blender/blenloader/intern/versioning_common.cc
+++ b/source/blender/blenloader/intern/versioning_common.cc
@@ -12,6 +12,7 @@
#include "DNA_screen_types.h"
#include "BLI_listbase.h"
+#include "BLI_map.hh"
#include "BLI_string.h"
#include "BLI_string_ref.hh"
@@ -25,6 +26,7 @@
#include "versioning_common.h"
+using blender::Map;
using blender::StringRef;
ARegion *do_versions_add_region_if_not_found(ListBase *regionbase,
@@ -234,3 +236,30 @@ ARegion *do_versions_add_region(int regiontype, const char *name)
region->regiontype = regiontype;
return region;
}
+
+void node_tree_relink_with_socket_id_map(bNodeTree &ntree,
+ bNode &old_node,
+ bNode &new_node,
+ const Map<std::string, std::string> &map)
+{
+ LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) {
+ if (link->tonode == &old_node) {
+ bNodeSocket *old_socket = link->tosock;
+ if (const std::string *new_identifier = map.lookup_ptr_as(old_socket->identifier)) {
+ bNodeSocket *new_socket = nodeFindSocket(&new_node, SOCK_IN, new_identifier->c_str());
+ link->tonode = &new_node;
+ link->tosock = new_socket;
+ old_socket->link = NULL;
+ }
+ }
+ if (link->fromnode == &old_node) {
+ bNodeSocket *old_socket = link->fromsock;
+ if (const std::string *new_identifier = map.lookup_ptr_as(old_socket->identifier)) {
+ bNodeSocket *new_socket = nodeFindSocket(&new_node, SOCK_OUT, new_identifier->c_str());
+ link->fromnode = &new_node;
+ link->fromsock = new_socket;
+ old_socket->link = NULL;
+ }
+ }
+ }
+}
diff --git a/source/blender/blenloader/intern/versioning_common.h b/source/blender/blenloader/intern/versioning_common.h
index c8c7dcc7cff..a8844d076b3 100644
--- a/source/blender/blenloader/intern/versioning_common.h
+++ b/source/blender/blenloader/intern/versioning_common.h
@@ -6,6 +6,10 @@
#pragma once
+#ifdef __cplusplus
+# include "BLI_map.hh"
+#endif
+
struct ARegion;
struct ListBase;
struct Main;
@@ -93,3 +97,10 @@ ARegion *do_versions_add_region(int regiontype, const char *name);
#ifdef __cplusplus
}
#endif
+
+#ifdef __cplusplus
+void node_tree_relink_with_socket_id_map(bNodeTree &ntree,
+ bNode &old_node,
+ bNode &new_node,
+ const blender::Map<std::string, std::string> &map);
+#endif