[Bf-blender-cvs] [845d525099c] bevelv2: Add slope parameter to mesh_inset and use that in face bevel.

Howard Trickey noreply at git.blender.org
Thu Sep 15 00:05:28 CEST 2022


Commit: 845d525099cc1c16ee3ea0a3cad7289781d0cf75
Author: Howard Trickey
Date:   Wed Sep 14 18:04:46 2022 -0400
Branches: bevelv2
https://developer.blender.org/rB845d525099cc1c16ee3ea0a3cad7289781d0cf75

Add slope parameter to mesh_inset and use that in face bevel.

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

M	source/blender/blenlib/BLI_mesh_inset.hh
M	source/blender/blenlib/intern/mesh_inset.cc
M	source/blender/nodes/geometry/nodes/node_geo_bevel_mesh.cc

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

diff --git a/source/blender/blenlib/BLI_mesh_inset.hh b/source/blender/blenlib/BLI_mesh_inset.hh
index cd7dfcb57df..599ea061b2e 100644
--- a/source/blender/blenlib/BLI_mesh_inset.hh
+++ b/source/blender/blenlib/BLI_mesh_inset.hh
@@ -26,6 +26,7 @@ public:
   /** The contours to inset; ints are vert indices; contour is on left side of implied edges. */
   Span<Vector<int>> contour;
   float inset_amount;
+  float slope;
   bool need_ids;
 };
 
diff --git a/source/blender/blenlib/intern/mesh_inset.cc b/source/blender/blenlib/intern/mesh_inset.cc
index 0a862b106bb..58513280a69 100644
--- a/source/blender/blenlib/intern/mesh_inset.cc
+++ b/source/blender/blenlib/intern/mesh_inset.cc
@@ -462,6 +462,28 @@ static float3 vertex_normal(const Vert *vert)
   return ans;
 }
 
+/** Analog of BM_vert_calc_shell_factor. */
+static float vertex_shell_factor(Vert *vert)
+{
+  float accum_shell = 0.0f;
+  float accum_angle = 0.0f;
+  Edge e = vert->e;
+  float3 vnorm = vertex_normal(vert);
+  do {
+    if (!e.tri()->is_ghost()) {
+      Edge eprev = e.triangle_pred();
+      float face_angle = angle_v3v3v3(v_src(eprev)->co, v_src(e)->co, v_dst(e)->co);
+      accum_shell += shell_v3v3_normalized_to_dist(vnorm, e.tri()->normal()) * face_angle;
+      accum_angle += face_angle;
+    }
+    e = rot_ccw(e);
+  } while (e != vert->e);
+  if (accum_angle != 0.0f) {
+    return accum_shell / accum_angle;
+  }
+  return 1.0f;
+}
+
 class TriangleMesh {
   Vector<Triangle *> triangles_;
   Vector<Vert *> verts_;
@@ -3186,10 +3208,27 @@ MeshInset_Result mesh_inset_calc(const MeshInset_Input &input)
   TriangleMesh trimesh = triangulate_input(input);
   StraightSkeleton ss(trimesh, input.contour, input.inset_amount);
   ss.compute();
-  Array<Triangle *> remaining_triangles = triangle_set_to_sorted_array(ss.remaining_triangles_set);
-  /* TODO: take in slope and offset arguments and use to adjust position of results in the normal
-   * direction, using ss.vertex_height_map
-   */
+  if (input.slope != 0.0f) {
+    /* Gather all the deltas before applying, as changing height changes the vertex normals. */
+    Array<float3> vco_delta(trimesh.all_verts().size(), float3(0.0f, 0.0f, 0.0f));
+    trimesh.calculate_all_tri_normals();
+    for (int v_index : trimesh.all_verts().index_range()) {
+      Vert *v = trimesh.get_vert_by_index(v_index);
+      if (!v->is_deleted()) {
+        if (ss.vertex_height_map.contains(v->id)) {
+          float h = ss.vertex_height_map.lookup(v->id);
+          if (h != 0.0f) {
+            float shell_factor = vertex_shell_factor(v);
+            vco_delta[v_index] = vertex_normal(v) * shell_factor * h * input.slope;
+          }
+        }
+      }
+    }
+    for (int v_index : trimesh.all_verts().index_range()) {
+      Vert *v = trimesh.get_vert_by_index(v_index);
+      v->co += vco_delta[v->id];
+    }
+  }
   if (dbg_level > 0) {
     trimesh_draw("after ss " + std::to_string(input.inset_amount), trimesh);
     std::cout << trimesh << "\n";
diff --git a/source/blender/nodes/geometry/nodes/node_geo_bevel_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_bevel_mesh.cc
index dcbada546fb..088b2d06ece 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_bevel_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_bevel_mesh.cc
@@ -34,6 +34,16 @@ static void node_declare(NodeDeclarationBuilder &b)
   b.add_input<decl::Geometry>("Mesh").supported_type(GEO_COMPONENT_TYPE_MESH);
   b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value();
   b.add_input<decl::Float>(N_("Amount")).default_value(1.0f).supports_field();
+  b.add_input<decl::Float>(N_("Slope")).default_value(0.0f).supports_field()
+    .description(N_("Face inset will raise up with this slope"))
+    .make_available([](bNode &node) {
+      node_storage(node).mode = GEO_NODE_BEVEL_MESH_FACES;
+    });
+  b.add_input<decl::Bool>(N_("Use Regions")).default_value(false)
+    .description(N_("Combine adjacent faces into regions and inset regions as a whole"))
+    .make_available([](bNode &node) {
+      node_storage(node).mode = GEO_NODE_BEVEL_MESH_FACES;
+    });
   b.add_output<decl::Geometry>("Mesh");
 }
 
@@ -51,8 +61,13 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node)
   node->storage = data;
 }
 
-static void node_update(bNodeTree *UNUSED(ntree), bNode *UNUSED(node))
+static void node_update(bNodeTree *ntree, bNode *node)
 {
+  const NodeGeometryBevelMesh &storage = node_storage(*node);
+  bNodeSocket *slope_socket = nodeFindSocket(node, SOCK_IN, "Slope");
+  nodeSetSocketAvailability(ntree, slope_socket, storage.mode == GEO_NODE_BEVEL_MESH_FACES);
+  bNodeSocket *use_regions_socket = nodeFindSocket(node, SOCK_IN, "Use Regions");
+  nodeSetSocketAvailability(ntree, use_regions_socket, storage.mode == GEO_NODE_BEVEL_MESH_FACES);
 }
 
 /** MeshTopology encapsulates data needed to answer topological queries about a mesh,
@@ -1591,8 +1606,13 @@ static Mesh *calculate_face_bevel(BevelData &bd,
                                   GeometrySet geometry_set,
                                   const MeshComponent &component,
                                   const IndexMask &to_bevel,
-                                  const VArray<float> amounts)
+                                  const VArray<float> amounts,
+                                  const VArray<float> slopes,
+                                  bool use_regions)
 {
+  if (use_regions) {
+    std::cout << "TODO: Implement use_regions";
+  }
   Span<MPoly> faces = mesh.polys();
   Span<MVert> verts = mesh.verts();
   Span<MLoop> loops = mesh.loops();
@@ -1618,6 +1638,7 @@ static Mesh *calculate_face_bevel(BevelData &bd,
     mi_input.face = mi_faces.as_span();
     mi_input.contour = mi_faces.as_span();
     mi_input.inset_amount = amounts[face_index];
+    mi_input.slope = slopes[face_index];
     meshinset::MeshInset_Result mi_result = meshinset::mesh_inset_calc(mi_input);
     /* Mapping from the result output vert indices to mesh indices. */
     Array<int> mr_vert_to_mesh_vert(mi_result.vert.size());
@@ -1689,19 +1710,23 @@ static Mesh *bevel_mesh_edges(GeometrySet geometry_set,
 static Mesh *bevel_mesh_faces(GeometrySet geometry_set,
                              const MeshComponent &component,
                              const Field<bool> &selection_field,
-                             const Field<float> &amount_field)
+                             const Field<float> &amount_field,
+                             const Field<float> &slope_field,
+                             bool use_regions)
 {
   const Mesh &mesh = *component.get_for_read();
   bke::MeshFieldContext context{mesh, ATTR_DOMAIN_FACE};
   FieldEvaluator evaluator{context, mesh.totpoly};
   evaluator.set_selection(selection_field);
   evaluator.add(amount_field);
+  evaluator.add(slope_field);
   evaluator.evaluate();
   VArray<float> amounts = evaluator.get_evaluated<float>(0);
+  VArray<float> slopes = evaluator.get_evaluated<float>(1);
   const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
 
   BevelData bdata(mesh);
-  return calculate_face_bevel(bdata, mesh, geometry_set, component, selection, amounts);
+  return calculate_face_bevel(bdata, mesh, geometry_set, component, selection, amounts, slopes, use_regions);
 }
 
 static void node_geo_exec(GeoNodeExecParams params)
@@ -1721,10 +1746,16 @@ static void node_geo_exec(GeoNodeExecParams params)
           mesh_out = bevel_mesh_vertices(geometry_set, component, selection_field, amount_field);
           break;
         case GEO_NODE_BEVEL_MESH_EDGES:
-          mesh_out = bevel_mesh_edges(geometry_set, component, selection_field, amount_field);
+          {
+            mesh_out = bevel_mesh_edges(geometry_set, component, selection_field, amount_field);
+          }
           break;
         case GEO_NODE_BEVEL_MESH_FACES:
-          mesh_out = bevel_mesh_faces(geometry_set, component, selection_field, amount_field);
+        {
+          Field<float> slope_field = params.extract_input<Field<float>>("Slope");
+          bool use_regions = params.get_input<bool>("Use Regions");
+          mesh_out = bevel_mesh_faces(geometry_set, component, selection_field, amount_field, slope_field, use_regions);
+        }
           break;
       }
       BLI_assert(BKE_mesh_is_valid(mesh_out));



More information about the Bf-blender-cvs mailing list