[Bf-blender-cvs] [38fadd7fc42] bevelv2: Added data structures to hold construction of bevel around a vert.

Howard Trickey noreply at git.blender.org
Mon Jul 4 19:39:06 CEST 2022


Commit: 38fadd7fc42d7916e99d52e0763cfc009074c7f2
Author: Howard Trickey
Date:   Mon Jul 4 12:06:12 2022 -0400
Branches: bevelv2
https://developer.blender.org/rB38fadd7fc42d7916e99d52e0763cfc009074c7f2

Added data structures to hold construction of bevel around a vert.

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

M	source/blender/nodes/geometry/nodes/node_geo_bevel_mesh.cc

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

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 dcc307034d1..f2a846c2094 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_bevel_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_bevel_mesh.cc
@@ -8,6 +8,8 @@
 #include "BKE_mesh_runtime.h"
 
 #include "BLI_array.hh"
+#include "BLI_math_vec_types.hh"
+#include "BLI_math_vector.hh"
 #include "BLI_set.hh"
 #include "BLI_sort.hh"
 #include "BLI_task.hh"
@@ -51,8 +53,13 @@ static void node_update(bNodeTree *UNUSED(ntree), bNode *UNUSED(node))
 {
 }
 
-/* While Mesh uses the term 'poly' for polygon, most of Blender uses the term 'face',
+/* MeshTopology encapsulates data needed to answer topological queries about a mesh,
+ * such as "which edges are adjacent to a given vertex?".
+ * While Mesh uses the term 'poly' for polygon, most of Blender uses the term 'face',
  * so we'll go with 'face' in this code except in the final to/from mesh routines.
+ * This structure will also give some basic access to information about the Mesh elements
+ * themselves, in order to keep open the possibility that this code could be adapted
+ * for use with BMesh at some point in the future.
  */
 class MeshTopology {
   MeshElemMap *vert_edge_map_;
@@ -108,6 +115,24 @@ class MeshTopology {
   {
     return mesh_.totpoly;
   }
+
+  float3 vert_co(int v) const
+  {
+    return float3(mesh_.mvert[v].co);
+  }
+
+  int edge_v1(int e) const
+  {
+    return mesh_.medge[e].v1;
+  }
+
+  int edge_v2(int e) const
+  {
+    return mesh_.medge[e].v2;
+  }
+
+  float3 edge_dir_from_vert(int e, int v) const;
+  float3 edge_dir_from_vert_normalized(int e, int v) const;
 };
 
 MeshTopology::MeshTopology(const Mesh &mesh) : mesh_(mesh)
@@ -185,6 +210,23 @@ bool MeshTopology::edge_is_successor_in_face(const int e0, const int e1, const i
   return false;
 }
 
+float3 MeshTopology::edge_dir_from_vert(int e, int v) const
+{
+  const MEdge &medge = mesh_.medge[e];
+  if (medge.v1 == v) {
+    return vert_co(medge.v2) - vert_co(medge.v1);
+  }
+  else {
+    BLI_assert(medge.v2 == v);
+    return vert_co(medge.v1) - vert_co(medge.v2);
+  }
+}
+
+float3 MeshTopology::edge_dir_from_vert_normalized(int e, int v) const
+{
+  return math::normalize(edge_dir_from_vert(e, v));
+}
+
 /* A Vertex Cap consists of a vertex in a mesh and an CCW ordering of
  * alternating edges and faces around it, as viewed from the face's
  * normal side. Some faces may be missing (i.e., gaps).
@@ -207,6 +249,9 @@ class VertexCap {
   {
   }
 
+  /* Initialize for vertex v, given a mesh topo. */
+  void init_from_topo(const int vert, const MeshTopology &topo);
+
   /* The number of edges around the cap. */
   int size() const
   {
@@ -257,34 +302,16 @@ class VertexCap {
   {
     return face(i) == -1;
   }
-
-  /* Debug printing on std::cout. */
-  void print() const;
-};
-
-class BevelData {
-  Array<VertexCap> bevel_vert_caps_;
-
- public:
-  MeshTopology topo;
-
-  BevelData(const Mesh &mesh) : topo(mesh)
-  {
-  }
-  ~BevelData()
-  {
-  }
-
-  void init_caps_from_vertex_selection(const IndexMask selection);
 };
 
 /* Construct and return the VertexCap for vertex vert. */
-static VertexCap construct_cap(const int vert, const MeshTopology &topo)
+void VertexCap::init_from_topo(const int vert, const MeshTopology &topo)
 {
+  this->vert = vert;
   Span<int> incident_edges = topo.vert_edges(vert);
   const int num_edges = incident_edges.size();
   if (num_edges == 0) {
-    return VertexCap(vert, Span<int>(), Span<int>());
+    return;
   }
 
   /* First check for the most common case: a complete manifold cap:
@@ -350,35 +377,254 @@ static VertexCap construct_cap(const int vert, const MeshTopology &topo)
           std::reverse(ordered_faces.begin(), ordered_faces.end());
         }
       }
-      return VertexCap(vert, ordered_edges.as_span(), ordered_faces.as_span());
+      this->edges_ = ordered_edges;
+      this->faces_ = ordered_faces;
+      return;
     }
   }
   std::cout << "to implement: VertexCap for non-manifold edges\n";
-  BLI_assert(false);
-  return VertexCap();
 }
 
-void VertexCap::print() const
+static std::ostream &operator<<(std::ostream &os, const VertexCap &cap)
 {
-  std::cout << "cap at v" << vert << ": ";
-  for (const int i : edges_.index_range()) {
-    std::cout << "e" << edges_[i] << " ";
-    if (faces_[i] == -1) {
-      std::cout << "<gap> ";
+  os << "cap at v" << cap.vert << ": ";
+  for (const int i : cap.edges().index_range()) {
+    os << "e" << cap.edge(i) << " ";
+    if (cap.face(i) == -1) {
+      os << "<gap> ";
     }
     else {
-      std::cout << "f" << faces_[i] << " ";
+      os << "f" << cap.face(i) << " ";
     }
   }
-  std::cout << "\n";
+  os << "\n";
+  return os;
 }
 
-void BevelData::init_caps_from_vertex_selection(const IndexMask selection)
+/* The different types of BoundaryVerts (see below). */
+typedef enum eBoundaryVertType {
+  BV_ON_EDGE = 0,
+  BV_ON_FACE = 1,
+  BV_ABOVE_FACE = 2,
+  BV_OTHER = 3,
+} eBoundaryVertType;
+
+static const char *bv_type_name[4] = {"on_edge", "on_face", "above_face", "other"};
+
+/* A BoundaryVert is a vertex placed somewhere around a vertex involved
+ * in a bevel. BoundaryVerts will be joined with line or arcs (depending on the
+ * number of segments in the bevel).
+ */
+class BoundaryVert {
+ public:
+  /* The position of the Boundary Vertex. */
+  float3 co;
+  /* If the type references an edge or a face.
+   * the index of the corresponding edge or face in the VertexCap. */
+  int vc_index;
+  /* Mesh index of this vertex in the output mesh. */
+  int mesh_index;
+  /* The type of this Boundary Vertex. */
+  eBoundaryVertType type;
+
+  BoundaryVert() : co(0.0, 0.0, 0.0), vc_index(-1), mesh_index(-1), type(BV_OTHER)
+  {
+  }
+};
+
+static std::ostream &operator<<(std::ostream &os, const BoundaryVert &bv)
 {
-  bevel_vert_caps_.reinitialize(selection.size());
-  threading::parallel_for(selection.index_range(), 1024, [&](const IndexRange range) {
+  os << "bv{" << bv_type_name[bv.type] << " "
+     << "vc#=" << bv.vc_index << " "
+     << "mesh#" << bv.mesh_index << " "
+     << "co=" << bv.co << "}";
+  return os;
+}
+
+/* The different types of BoundaryEdges (see below). */
+typedef enum eBoundaryEdgeType {
+  BE_UNBEVELED = 0,
+  BE_BEVELED = 1,
+  BE_FACE_BEVEL_BOTH = 2,
+  BE_FACE_BEVEL_LEFT = 3,
+  BE_FACE_BEVEL_RIGHT = 4,
+  BE_OTHER = 5,
+} eBoundaryEdgeType;
+
+static const char *be_type_name[6] = {
+    "unbev", "bev", "facebev_both", "facebev_l", "facebev_r", "other"};
+
+/* A BoundaryEdge is one end of an edge, attached to a vertex in a VertexCap.
+ * This data describes how it is involved in beveling, and how it is attached
+ * to BoundaryVerts.
+ * Note: when the descriptors "left" and "right" are used to refer to sides of
+ * edges, these are to be taken as left and right when looking down the edge
+ * towards the VertexCap's vertex.
+ */
+class BoundaryEdge {
+ public:
+  /* The mesh index of the edge. */
+  int edge;
+  /* Where it is found in the list of edges in the VertexCap. */
+  int vc_index;
+  /* The boundary vertex index where the edge is attached,
+   * only used for BE_UNBEVELED and BE_FACE_BEVEL_* types. */
+  int bv_index;
+  /* The boundary vertex index where the left half of a BE_BEVELED,
+   * BE_FACE_BEVEL_BOTH, or BE_FACE_BEVEL_LEFT attached. */
+  int bv_left_index;
+  /* The boundary vertex index where the left half of a BE_BEVELED,
+   * BE_FACE_BEVEL_BOTH, or BE_FACE_BEVEL_RIGHT attached. */
+  int bv_right_index;
+  /* The type of this BoundaryEdge. */
+  eBoundaryEdgeType type;
+
+  BoundaryEdge()
+      : edge(-1), vc_index(-1), bv_index(-1), bv_left_index(-1), bv_right_index(-1), type(BE_OTHER)
+  {
+  }
+};
+
+static std::ostream &operator<<(std::ostream &os, const BoundaryEdge &be)
+{
+  os << "be{" << be_type_name[be.type] << " "
+     << "edge=" << be.edge << " "
+     << "vc#=" << be.vc_index << " "
+     << "bv#=" << be.bv_index << " "
+     << "bvl#=" << be.bv_left_index << " "
+     << "bvr#=" << be.bv_right_index << "}";
+  return os;
+}
+
+class BevelVertexData {
+  VertexCap vertex_cap_;
+  Array<BoundaryVert> boundary_vert_;
+  Array<BoundaryEdge> boundary_edge_;
+
+ public:
+  BevelVertexData()
+  {
+  }
+  ~BevelVertexData()
+  {
+  }
+
+  void construct_vertex_cap(int vert, const MeshTopology &topo)
+  {
+    vertex_cap_.init_from_topo(vert, topo);
+  }
+
+  void construct_vertex_bevel(int vert, float amount, const MeshTopology &topo);
+
+  const VertexCap &vertex_cap() const
+  {
+    return vertex_cap_;
+  }
+
+  Span<BoundaryVert> boundary_verts() const
+  {
+    return boundary_vert_.as_span();
+  }
+
+  Span<BoundaryEdge> boundary_edges() const
+  {
+    return boundary_edge_.as_span();
+  }
+};
+
+static std::ostream &operator<<(std::ostream &os, const BevelVertexData &bvd)
+{
+  const VertexCap &vc = bvd.vertex_cap();
+  os << "bevel vertex data for vertex " << vc.vert << "\n";
+  os << vc;
+  Span<BoundaryVert> bvs = bvd.boundary_verts();
+  os << "boundary verts:\n";
+  for (const int i : bvs.index_range()) {
+    os << "[" << i << "] " << bvs[i] << "\n";
+  }
+  Span<BoundaryEdge> bes = bvd.boundary_edges();
+  os << "boundary edges:\n";
+  for (const int i : bes.index_range()) {
+    os << "[" << i << "] " << bes[i] << "\n";
+  }
+  return os;
+}
+
+/* Calculate the BevelVertexData for one vertex, `vert`, by the given `amount`.
+ * This doesn't calculate limits to the bevel caused by collisions with vertex bevels
+ * at adjacent vertices; that needs to done after all of these are calculated,
+ * so that this operation can be done in parallel with all other vertex constructions.
+ */
+void BevelVertexData::construct_vertex_bevel(int vert, float amount, const MeshTopology &topo)
+{
+  construct_vertex_cap(vert, topo);
+
+  const int num_edges = vertex_cap().size();
+
+  /* There will be one boundary vertex on each edge attached to `vert`. */
+  boundary_edge_.reinitialize(num_edges);
+  boundary_vert_.reinitialize(num_edges);
+
+  const float3 vert_co = topo.vert_co(vertex_cap().vert);
+  for (const int i : IndexRange(num_edges)) {
+    BoundaryVert &bv = boundary_vert_[i];
+    bv.type = BV_ON_E

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list