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>2021-10-19 16:39:10 +0300
committerHans Goudey <h.goudey@me.com>2021-10-19 16:39:10 +0300
commit219058c213d5c9efce3f44216f6513edc93b5536 (patch)
tree26b76ae133b36d41c9a90d43eaa29ebf2b943c5a
parentcd36f59027042ff0f2ad53e98088428a4c0c5e38 (diff)
Geometry Nodes: Remove implicit realizing and conversion
This commit removes the implicit conversion from points to a mesh that used to happen before the next modifier. It also removes the implicit realizing of instances that happened before another modifier. Now we have specific nodes for both of these operations, the implicit conversions make less sense, and implicit instance realizing has already been removed in other nodes. This adds another geometry nodes modifier before modifiers that would have realized instances implicitly before. Currently adding another data-block during versioning after linking means that an assert needs to be changed. That should be made unnecessary by T92333. Differential Revision: https://developer.blender.org/D12722
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_geometry_set_instances.hh1
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc44
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc66
-rw-r--r--source/blender/blenkernel/intern/lib_id.c5
-rw-r--r--source/blender/blenloader/intern/versioning_300.c81
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc6
7 files changed, 95 insertions, 110 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index d8112de760d..5ee86f9446e 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 34
+#define BLENDER_FILE_SUBVERSION 35
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_geometry_set_instances.hh b/source/blender/blenkernel/BKE_geometry_set_instances.hh
index d7a60162e81..e5b28e4fbab 100644
--- a/source/blender/blenkernel/BKE_geometry_set_instances.hh
+++ b/source/blender/blenkernel/BKE_geometry_set_instances.hh
@@ -44,7 +44,6 @@ struct GeometryInstanceGroup {
void geometry_set_gather_instances(const GeometrySet &geometry_set,
Vector<GeometryInstanceGroup> &r_instance_groups);
-GeometrySet geometry_set_realize_mesh_for_modifier(const GeometrySet &geometry_set);
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set);
/**
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index 59e81938e79..3ec0ab9c512 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -886,33 +886,6 @@ void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval,
}
/**
- * Some modifiers don't work on geometry sets directly, but expect a single mesh as input.
- * Therefore, we convert data from the geometry set into a single mesh, so that those
- * modifiers can work on it as well.
- */
-static Mesh *prepare_geometry_set_for_mesh_modifier(Mesh *mesh, GeometrySet &r_geometry_set)
-{
- if (!r_geometry_set.has_instances() && !r_geometry_set.has_pointcloud()) {
- return mesh;
- }
-
- {
- /* Add the mesh to the geometry set. */
- MeshComponent &mesh_component = r_geometry_set.get_component_for_write<MeshComponent>();
- mesh_component.replace(mesh, GeometryOwnershipType::Editable);
- }
- {
- /* Combine mesh and all instances into a single mesh that can be passed to the modifier. */
- GeometrySet new_geometry_set = blender::bke::geometry_set_realize_mesh_for_modifier(
- r_geometry_set);
- MeshComponent &mesh_component = new_geometry_set.get_component_for_write<MeshComponent>();
- Mesh *new_mesh = mesh_component.release();
- r_geometry_set = new_geometry_set;
- return new_mesh;
- }
-}
-
-/**
* Modifies the given mesh and geometry set. The mesh is not passed as part of the mesh component
* in the \a geometry_set input, it is only passed in \a input_mesh and returned in the return
* value.
@@ -928,14 +901,7 @@ static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md,
Mesh *mesh_output = nullptr;
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
if (mti->modifyGeometrySet == nullptr) {
- Mesh *new_input_mesh = prepare_geometry_set_for_mesh_modifier(input_mesh, geometry_set);
- mesh_output = BKE_modifier_modify_mesh(md, &mectx, new_input_mesh);
-
- /* The caller is responsible for freeing `input_mesh` and `mesh_output`. The intermediate
- * `new_input_mesh` has to be freed here. */
- if (!ELEM(new_input_mesh, input_mesh, mesh_output)) {
- BKE_id_free(nullptr, new_input_mesh);
- }
+ mesh_output = BKE_modifier_modify_mesh(md, &mectx, input_mesh);
}
else {
/* For performance reasons, this should be called by the modifier and/or nodes themselves at
@@ -1177,14 +1143,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
/* No existing verts to deform, need to build them. */
if (!deformed_verts) {
if (mesh_final) {
- Mesh *mesh_final_new = prepare_geometry_set_for_mesh_modifier(mesh_final,
- geometry_set_final);
- if (mesh_final_new != mesh_final) {
- BLI_assert(mesh_final != mesh_input);
- BKE_id_free(nullptr, mesh_final);
- mesh_final = mesh_final_new;
- }
-
/* Deforming a mesh, read the vertex locations
* out of the mesh and deform them. Once done with this
* run of deformers verts will be written back. */
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index d92df386575..35c6a7df2c7 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -224,8 +224,7 @@ void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> se
}
}
-static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGroup> set_groups,
- const bool convert_points_to_vertices)
+static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGroup> set_groups)
{
int totverts = 0;
int totloops = 0;
@@ -255,10 +254,6 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGrou
materials.add(material);
}
}
- if (convert_points_to_vertices && set.has_pointcloud()) {
- const PointCloud &pointcloud = *set.get_pointcloud_for_read();
- totverts += pointcloud.totpoint * tot_transforms;
- }
}
/* Don't create an empty mesh. */
@@ -345,24 +340,6 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGrou
poly_offset += mesh.totpoly;
}
}
-
- const float3 point_normal{0.0f, 0.0f, 1.0f};
- short point_normal_short[3];
- normal_float_to_short_v3(point_normal_short, point_normal);
-
- if (convert_points_to_vertices && set.has_pointcloud()) {
- const PointCloud &pointcloud = *set.get_pointcloud_for_read();
- for (const float4x4 &transform : set_group.transforms) {
- for (const int i : IndexRange(pointcloud.totpoint)) {
- MVert &new_vert = new_mesh->mvert[vert_offset + i];
- const float3 old_position = pointcloud.co[i];
- const float3 new_position = transform * old_position;
- copy_v3_v3(new_vert.co, new_position);
- memcpy(&new_vert.no, point_normal_short, sizeof(point_normal_short));
- }
- vert_offset += pointcloud.totpoint;
- }
- }
}
/* A possible optimization is to only tag the normals dirty when there are transforms that change
@@ -495,12 +472,9 @@ static CurveEval *join_curve_splines_and_builtin_attributes(Span<GeometryInstanc
return new_curve;
}
-static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups,
- bool convert_points_to_vertices,
- GeometrySet &result)
+static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups, GeometrySet &result)
{
- Mesh *new_mesh = join_mesh_topology_and_builtin_attributes(set_groups,
- convert_points_to_vertices);
+ Mesh *new_mesh = join_mesh_topology_and_builtin_attributes(set_groups);
if (new_mesh == nullptr) {
return;
}
@@ -508,21 +482,17 @@ static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups,
MeshComponent &dst_component = result.get_component_for_write<MeshComponent>();
dst_component.replace(new_mesh);
- Vector<GeometryComponentType> component_types;
- component_types.append(GEO_COMPONENT_TYPE_MESH);
- if (convert_points_to_vertices) {
- component_types.append(GEO_COMPONENT_TYPE_POINT_CLOUD);
- }
-
/* Don't copy attributes that are stored directly in the mesh data structs. */
Map<AttributeIDRef, AttributeKind> attributes;
geometry_set_gather_instances_attribute_info(
set_groups,
- component_types,
+ {GEO_COMPONENT_TYPE_MESH},
{"position", "material_index", "normal", "shade_smooth", "crease"},
attributes);
- join_attributes(
- set_groups, component_types, attributes, static_cast<GeometryComponent &>(dst_component));
+ join_attributes(set_groups,
+ {GEO_COMPONENT_TYPE_MESH},
+ attributes,
+ static_cast<GeometryComponent &>(dst_component));
}
static void join_instance_groups_pointcloud(Span<GeometryInstanceGroup> set_groups,
@@ -582,24 +552,6 @@ static void join_instance_groups_curve(Span<GeometryInstanceGroup> set_groups, G
static_cast<GeometryComponent &>(dst_component));
}
-GeometrySet geometry_set_realize_mesh_for_modifier(const GeometrySet &geometry_set)
-{
- if (!geometry_set.has_instances() && !geometry_set.has_pointcloud()) {
- return geometry_set;
- }
-
- GeometrySet new_geometry_set = geometry_set;
- Vector<GeometryInstanceGroup> set_groups;
- geometry_set_gather_instances(geometry_set, set_groups);
- join_instance_groups_mesh(set_groups, true, new_geometry_set);
- /* Remove all instances, even though some might contain other non-mesh data. We can't really
- * keep only non-mesh instances in general. */
- new_geometry_set.remove<InstancesComponent>();
- /* If there was a point cloud, it is now part of the mesh. */
- new_geometry_set.remove<PointCloudComponent>();
- return new_geometry_set;
-}
-
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
{
if (!geometry_set.has_instances()) {
@@ -610,7 +562,7 @@ GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
Vector<GeometryInstanceGroup> set_groups;
geometry_set_gather_instances(geometry_set, set_groups);
- join_instance_groups_mesh(set_groups, false, new_geometry_set);
+ join_instance_groups_mesh(set_groups, new_geometry_set);
join_instance_groups_pointcloud(set_groups, new_geometry_set);
join_instance_groups_volume(set_groups, new_geometry_set);
join_instance_groups_curve(set_groups, new_geometry_set);
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 3b2d2c5d2c3..3c85ba62d07 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1121,8 +1121,9 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
id->us = 1;
}
if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
- /* Note that 2.8x versioning has tested not to cause conflicts. */
- BLI_assert(bmain->is_locked_for_linking == false || ELEM(type, ID_WS, ID_GR));
+ /* Note that 2.8x versioning has tested not to cause conflicts. Node trees are
+ * skipped in this check to allow adding a geometry node tree for versioning. */
+ BLI_assert(bmain->is_locked_for_linking == false || ELEM(type, ID_WS, ID_GR, ID_NT));
ListBase *lb = which_libbase(bmain, type);
BKE_main_lock(bmain);
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 035642a561a..4c6b70982a4 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -55,6 +55,7 @@
#include "BKE_idprop.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
+#include "BKE_modifier.h"
#include "BKE_node.h"
#include "RNA_access.h"
@@ -539,6 +540,54 @@ static void version_geometry_nodes_add_realize_instance_nodes(bNodeTree *ntree)
}
}
+/**
+ * The geometry nodes modifier used to realize instances for the next modifier implicitly. Now it
+ * is done with the realize instances node. It also used to convert meshes to point clouds
+ * automatically, which is also now done with a specific node.
+ */
+static bNodeTree *add_realize_node_tree(Main *bmain)
+{
+ bNodeTree *node_tree = ntreeAddTree(bmain, "Realize Instances 2.93 Legacy", "GeometryNodeTree");
+
+ ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketGeometry", "Geometry");
+ ntreeAddSocketInterface(node_tree, SOCK_OUT, "NodeSocketGeometry", "Geometry");
+
+ bNode *group_input = nodeAddStaticNode(NULL, node_tree, NODE_GROUP_INPUT);
+ group_input->locx = -400.0f;
+ bNode *group_output = nodeAddStaticNode(NULL, node_tree, NODE_GROUP_OUTPUT);
+ group_output->locx = 500.0f;
+ group_output->flag |= NODE_DO_OUTPUT;
+
+ bNode *join = nodeAddStaticNode(NULL, node_tree, GEO_NODE_JOIN_GEOMETRY);
+ join->locx = group_output->locx - 175.0f;
+ join->locy = group_output->locy;
+ bNode *conv = nodeAddStaticNode(NULL, node_tree, GEO_NODE_POINTS_TO_VERTICES);
+ conv->locx = join->locx - 175.0f;
+ conv->locy = join->locy - 70.0;
+ bNode *separate = nodeAddStaticNode(NULL, node_tree, GEO_NODE_SEPARATE_COMPONENTS);
+ separate->locx = join->locx - 350.0f;
+ separate->locy = join->locy + 50.0f;
+ bNode *realize = nodeAddStaticNode(NULL, node_tree, GEO_NODE_REALIZE_INSTANCES);
+ realize->locx = separate->locx - 200.0f;
+ realize->locy = join->locy;
+
+ nodeAddLink(node_tree, group_input, group_input->outputs.first, realize, realize->inputs.first);
+ nodeAddLink(node_tree, realize, realize->outputs.first, separate, separate->inputs.first);
+ nodeAddLink(node_tree, conv, conv->outputs.first, join, join->inputs.first);
+ nodeAddLink(node_tree, separate, BLI_findlink(&separate->outputs, 3), join, join->inputs.first);
+ nodeAddLink(node_tree, separate, BLI_findlink(&separate->outputs, 1), conv, conv->inputs.first);
+ nodeAddLink(node_tree, separate, BLI_findlink(&separate->outputs, 2), join, join->inputs.first);
+ nodeAddLink(node_tree, separate, separate->outputs.first, join, join->inputs.first);
+ nodeAddLink(node_tree, join, join->outputs.first, group_output, group_output->inputs.first);
+
+ LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) {
+ nodeSetSelected(node, false);
+ }
+
+ ntreeUpdateTree(bmain, node_tree);
+ return node_tree;
+}
+
void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports))
{
if (MAIN_VERSION_ATLEAST(bmain, 300, 0) && !MAIN_VERSION_ATLEAST(bmain, 300, 1)) {
@@ -672,6 +721,38 @@ void do_versions_after_linking_300(Main *bmain, ReportList *UNUSED(reports))
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 300, 35)) {
+ /* Add a new modifier to realize instances from previous modifiers.
+ * Previously that was done automatically by geometry nodes. */
+ bNodeTree *realize_instances_node_tree = NULL;
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ LISTBASE_FOREACH_MUTABLE (ModifierData *, md, &ob->modifiers) {
+ if (md->type != eModifierType_Nodes) {
+ continue;
+ }
+ if (md->next == NULL) {
+ break;
+ }
+ if (md->next->type == eModifierType_Nodes) {
+ continue;
+ }
+ NodesModifierData *nmd = (NodesModifierData *)md;
+ if (nmd->node_group == NULL) {
+ continue;
+ }
+
+ NodesModifierData *new_nmd = (NodesModifierData *)BKE_modifier_new(eModifierType_Nodes);
+ STRNCPY(new_nmd->modifier.name, "Realize Instances 2.93 Legacy");
+ BKE_modifier_unique_name(&ob->modifiers, &new_nmd->modifier);
+ BLI_insertlinkafter(&ob->modifiers, md, new_nmd);
+ if (realize_instances_node_tree == NULL) {
+ realize_instances_node_tree = add_realize_node_tree(bmain);
+ }
+ new_nmd->node_group = realize_instances_node_tree;
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index b28fead299d..b5ca5f3545f 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -1093,12 +1093,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
modifyGeometry(md, ctx, geometry_set);
- if (ctx->flag & MOD_APPLY_TO_BASE_MESH) {
- /* In this case it makes sense to realize instances, otherwise in some cases there might be no
- * results when applying the modifier. */
- geometry_set = blender::bke::geometry_set_realize_mesh_for_modifier(geometry_set);
- }
-
Mesh *new_mesh = geometry_set.get_component_for_write<MeshComponent>().release();
if (new_mesh == nullptr) {
return BKE_mesh_new_nomain(0, 0, 0, 0, 0);