[Bf-blender-cvs] [df280824e41] temp-new-hair: Curves: Deform curves based on surface node. (WIP)

Jacques Lucke noreply at git.blender.org
Mon Jul 4 16:14:32 CEST 2022


Commit: df280824e419936a1c514aafd71de38adeb8f5dd
Author: Jacques Lucke
Date:   Mon Jul 4 16:14:18 2022 +0200
Branches: temp-new-hair
https://developer.blender.org/rBdf280824e419936a1c514aafd71de38adeb8f5dd

Curves: Deform curves based on surface node. (WIP)

{F13245862}

Notes:
* The reverse uv lookup implementation is still fairly trivial (and can have quadratic behavior for some uv maps).
* There is still a discontinuity between faces when faces are rotated (although that seems to exist in the old hair system as well). See todo comment in code.

Todo:
* Decide on the inputs of the deform node? (original/deformed mesh, rest position, uv map, attachment uv coords)
* Is using parenting to deal with object transforms fine?
* Where/when/how to store the rest position?

Maniphest Tasks: T96436, T95776

Differential Revision: https://developer.blender.org/D14864

===================================================================

M	release/scripts/startup/bl_ui/properties_data_mesh.py
M	release/scripts/startup/nodeitems_builtins.py
M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/DerivedMesh.cc
M	source/blender/blenkernel/intern/node.cc
M	source/blender/blenkernel/intern/node_tree_update.cc
M	source/blender/blenlib/BLI_float3x3.hh
M	source/blender/editors/curves/intern/curves_add.cc
M	source/blender/editors/curves/intern/curves_ops.cc
M	source/blender/editors/include/ED_curves.h
M	source/blender/editors/object/object_add.cc
M	source/blender/editors/object/object_relations.c
M	source/blender/geometry/GEO_reverse_uv_sampler.hh
M	source/blender/geometry/intern/reverse_uv_sampler.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesdna/DNA_object_types.h
M	source/blender/makesrna/intern/rna_object.c
M	source/blender/modifiers/intern/MOD_nodes.cc
M	source/blender/nodes/NOD_geometry.h
M	source/blender/nodes/NOD_static_types.h
M	source/blender/nodes/geometry/CMakeLists.txt
A	source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc

===================================================================

diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 0b043905713..2fc949f4aae 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -411,6 +411,8 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
                 row.active = enable_edit_value
                 row.prop(key, "eval_time")
 
+        layout.prop(ob, "add_rest_position_attribute")
+
 
 class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
     bl_label = "UV Maps"
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 21bb3d01616..14032937af0 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -73,6 +73,7 @@ def curve_node_items(context):
     yield NodeItem("GeometryNodeCurveLength")
     yield NodeItem("GeometryNodeCurveToMesh")
     yield NodeItem("GeometryNodeCurveToPoints")
+    yield NodeItem("GeometryNodeDeformCurvesWithSurface")
     yield NodeItem("GeometryNodeFillCurve")
     yield NodeItem("GeometryNodeFilletCurve")
     yield NodeItem("GeometryNodeResampleCurve")
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index e13ac3180ec..71eb3f6664f 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1501,6 +1501,7 @@ struct TexResult;
 #define GEO_NODE_MESH_TO_VOLUME 1164
 #define GEO_NODE_UV_UNWRAP 1165
 #define GEO_NODE_UV_PACK_ISLANDS 1166
+#define GEO_NODE_DEFORM_CURVES_WITH_SURFACE 1167
 
 /** \} */
 
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index ffac89c15e6..c2ea01bcadf 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -66,6 +66,9 @@
 #  include "DNA_userdef_types.h"
 #endif
 
+using blender::float3;
+using blender::IndexRange;
+
 /* very slow! enable for testing only! */
 //#define USE_MODIFIER_VALIDATE
 
@@ -814,6 +817,25 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
   /* Clear errors before evaluation. */
   BKE_modifiers_clear_errors(ob);
 
+  if (ob->modifier_flag & OB_MODIFIER_FLAG_ADD_REST_POSITION) {
+    if (mesh_final == nullptr) {
+      mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
+      ASSERT_IS_VALID_MESH(mesh_final);
+    }
+    float3 *rest_positions = static_cast<float3 *>(CustomData_add_layer_named(&mesh_final->vdata,
+                                                                              CD_PROP_FLOAT3,
+                                                                              CD_DEFAULT,
+                                                                              nullptr,
+                                                                              mesh_final->totvert,
+                                                                              "rest_position"));
+    blender::threading::parallel_for(
+        IndexRange(mesh_final->totvert), 1024, [&](const IndexRange range) {
+          for (const int i : range) {
+            rest_positions[i] = mesh_final->mvert[i].co;
+          }
+        });
+  }
+
   /* Apply all leading deform modifiers. */
   if (use_deform) {
     for (; md; md = md->next, md_datamask = md_datamask->next) {
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 5be912ffb2b..1c797f29ce1 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -4749,6 +4749,7 @@ static void registerGeometryNodes()
   register_node_type_geo_curve_to_mesh();
   register_node_type_geo_curve_to_points();
   register_node_type_geo_curve_trim();
+  register_node_type_geo_deform_curves_with_surface();
   register_node_type_geo_delete_geometry();
   register_node_type_geo_duplicate_elements();
   register_node_type_geo_distribute_points_on_faces();
diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc
index 019ab114b83..9a0e669b966 100644
--- a/source/blender/blenkernel/intern/node_tree_update.cc
+++ b/source/blender/blenkernel/intern/node_tree_update.cc
@@ -1294,6 +1294,12 @@ class NodeTreeMainUpdater {
         break;
       }
     }
+
+    if (!(ntree.runtime->runtime_flag & NTREE_RUNTIME_FLAG_HAS_SURFACE_DEFORMATION)) {
+      if (!tree_ref.nodes_by_type("GeometryNodeDeformCurvesWithSurface").is_empty()) {
+        ntree.runtime->runtime_flag |= NTREE_RUNTIME_FLAG_HAS_SURFACE_DEFORMATION;
+      }
+    }
   }
 
   void update_node_levels(bNodeTree &ntree)
diff --git a/source/blender/blenlib/BLI_float3x3.hh b/source/blender/blenlib/BLI_float3x3.hh
index 62478556d9b..6a9e7dd04f0 100644
--- a/source/blender/blenlib/BLI_float3x3.hh
+++ b/source/blender/blenlib/BLI_float3x3.hh
@@ -152,6 +152,13 @@ struct float3x3 {
     return result;
   }
 
+  friend float3 operator*(const float3x3 &a, const float3 &b)
+  {
+    float3 result;
+    mul_v3_m3v3(result, a.values, b);
+    return result;
+  }
+
   void operator*=(const float3x3 &other)
   {
     mul_m3_m3_post(values, other.values);
diff --git a/source/blender/editors/curves/intern/curves_add.cc b/source/blender/editors/curves/intern/curves_add.cc
index 552ef1d96c8..95f54d963c2 100644
--- a/source/blender/editors/curves/intern/curves_add.cc
+++ b/source/blender/editors/curves/intern/curves_add.cc
@@ -6,12 +6,79 @@
 
 #include "BLI_rand.hh"
 
+#include "BKE_context.h"
 #include "BKE_curves.hh"
+#include "BKE_node.h"
+#include "BKE_node_runtime.hh"
 
 #include "ED_curves.h"
+#include "ED_node.h"
+#include "ED_object.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
 
 namespace blender::ed::curves {
 
+static bool has_surface_deformation_node(const Object &curves_ob)
+{
+  LISTBASE_FOREACH (const ModifierData *, md, &curves_ob.modifiers) {
+    if (md->type != eModifierType_Nodes) {
+      continue;
+    }
+    const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md);
+    if (nmd->node_group == nullptr) {
+      continue;
+    }
+    if (nmd->node_group->runtime->runtime_flag & NTREE_RUNTIME_FLAG_HAS_SURFACE_DEFORMATION) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void ensure_surface_deformation_node_exists(bContext &C, Object &curves_ob)
+{
+  if (has_surface_deformation_node(curves_ob)) {
+    return;
+  }
+
+  Main *bmain = CTX_data_main(&C);
+  Scene *scene = CTX_data_scene(&C);
+
+  ModifierData *md = ED_object_modifier_add(
+      nullptr, bmain, scene, &curves_ob, "Hair Deform", eModifierType_Nodes);
+  NodesModifierData &nmd = *reinterpret_cast<NodesModifierData *>(md);
+  nmd.node_group = ntreeAddTree(bmain, "Hair Deform", "GeometryNodeTree");
+
+  bNodeTree *ntree = nmd.node_group;
+  ntreeAddSocketInterface(ntree, SOCK_IN, "NodeSocketGeometry", "Geometry");
+  ntreeAddSocketInterface(ntree, SOCK_OUT, "NodeSocketGeometry", "Geometry");
+  bNode *group_input = nodeAddStaticNode(&C, ntree, NODE_GROUP_INPUT);
+  bNode *group_output = nodeAddStaticNode(&C, ntree, NODE_GROUP_OUTPUT);
+  bNode *deform_node = nodeAddStaticNode(&C, ntree, GEO_NODE_DEFORM_CURVES_WITH_SURFACE);
+
+  ED_node_tree_propagate_change(&C, bmain, nmd.node_group);
+
+  nodeAddLink(ntree,
+              group_input,
+              static_cast<bNodeSocket *>(group_input->outputs.first),
+              deform_node,
+              nodeFindSocket(deform_node, SOCK_IN, "Curves"));
+  nodeAddLink(ntree,
+              deform_node,
+              nodeFindSocket(deform_node, SOCK_OUT, "Curves"),
+              group_output,
+              static_cast<bNodeSocket *>(group_output->inputs.first));
+
+  group_input->locx = -200;
+  group_output->locx = 200;
+  deform_node->locx = 0;
+
+  ED_node_tree_propagate_change(&C, bmain, nmd.node_group);
+}
+
 bke::CurvesGeometry primitive_random_sphere(const int curves_size, const int points_per_curve)
 {
   bke::CurvesGeometry curves(points_per_curve * curves_size, curves_size);
diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc
index 1575912deb1..bd0505c65ee 100644
--- a/source/blender/editors/curves/intern/curves_ops.cc
+++ b/source/blender/editors/curves/intern/curves_ops.cc
@@ -520,154 +520,169 @@ static bool snap_curves_to_surface_poll(bContext *C)
   return true;
 }
 
+static void snap_curves_to_surface_exec_object(Object &curves_ob,
+                                               const Object &surface_ob,
+                                               const AttachMode attach_mode,
+                                               bool *r_invalid_uvs,
+                                               bool *r_missing_uvs)
+{
+  Curves &curves_id = *static_cast<Curves *>(curves_ob.data);
+  CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
+
+  Mesh &surface_mesh = *static_cast<Mesh *>(surface_ob.data);
+
+  MeshComponent surface_mesh_component;
+  surface_mesh_component.replace(&surface_mesh, GeometryOwnershipType::ReadOnly);
+
+  VArraySpan<float2> surface_uv_map;
+  if (curves_id.surface_uv_map != nullptr) {
+    surface_uv_map = surface_mesh_component
+                         .attribute_try_get_for_read(
+                             curves_id.surface_uv_map, ATTR_DOMAIN_CORNER, CD_PROP_FLOAT2)
+                         .typed<float2>();
+  }
+
+  MutableSpan<float3> positions_cu = curves.positions_for_write();
+  MutableSpan<float2> surface_uv_coords = curves.surface_uv_coords_for_write();
+
+  const Span<MLoopTri> surface_looptris = {BKE_mesh_runtime_looptri_ensure(&surface_mesh),
+                                           BKE_mesh_runtime_looptri_len(&surface_mesh)};
+
+  const float4x4 curves_to_world_mat = curves_ob.obmat;
+  const float4x4 world_to_curves_mat = curves_to_world_mat.inverted();
+  const float4x4 surface_to_world_mat = surface_ob.obmat;
+  const float4x4 world_to_surface_mat = surface_to_world_mat.inverted();
+  const float4x4 curves_to_surface_mat = world_to_surface_mat * curves_to_world_mat;
+  const float4x4 surface

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list