[Bf-blender-cvs] [779aeb72aba] sculpt-dev: Sculpt: integrate instant meshes

Joseph Eagar noreply at git.blender.org
Mon Oct 25 19:06:10 CEST 2021


Commit: 779aeb72aba0c2f9711f62aea1a976f41cef5a0e
Author: Joseph Eagar
Date:   Mon Oct 25 10:05:12 2021 -0700
Branches: sculpt-dev
https://developer.blender.org/rB779aeb72aba0c2f9711f62aea1a976f41cef5a0e

Sculpt: integrate instant meshes

Still not particularly usable, but
much faster then Quadriflow.

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

M	intern/instant-meshes/CMakeLists.txt
A	intern/instant-meshes/Readme.Blender.MD
A	intern/instant-meshes/instant_meshes_c_api.h
A	intern/instant-meshes/src/c_api.cpp
M	intern/instant-meshes/src/field.cpp
M	intern/instant-meshes/src/field.h
M	intern/instant-meshes/src/hierarchy.h
M	intern/instant-meshes/src/viewer.cpp
M	source/blender/blenkernel/BKE_mesh_remesh_voxel.h
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/blenkernel/intern/brush.c
M	source/blender/blenkernel/intern/brush_engine_presets.c
M	source/blender/blenkernel/intern/mesh_remesh_voxel.cc
M	source/blender/editors/object/object_intern.h
M	source/blender/editors/object/object_ops.c
M	source/blender/editors/object/object_remesh.cc
M	source/blender/editors/sculpt_paint/sculpt.c

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

diff --git a/intern/instant-meshes/CMakeLists.txt b/intern/instant-meshes/CMakeLists.txt
index b89e0b01acc..ed484821a35 100644
--- a/intern/instant-meshes/CMakeLists.txt
+++ b/intern/instant-meshes/CMakeLists.txt
@@ -22,6 +22,7 @@ set(INC
   .
   ../atomic
   ../eigen
+  ../guardedalloc
   ../../extern/Eigen3
   ext/half
   ext/dset
@@ -53,6 +54,10 @@ set(SRC
   src/extract.h
   src/field.cpp
   src/field.h
+  src/meshstats.cpp
+  src/meshstats.h
+  src/normal.cpp
+  src/normal.h
   src/hierarchy.cpp
   src/hierarchy.h
   src/reorder.cpp
@@ -61,6 +66,8 @@ set(SRC
   src/subdivide.h
   src/smoothcurve.cpp
   src/smoothcurve.h
+  src/c_api.cpp
+  instant_meshes_c_api.h
 )
 
 set(LIB
diff --git a/intern/instant-meshes/Readme.Blender.MD b/intern/instant-meshes/Readme.Blender.MD
new file mode 100644
index 00000000000..5b1ed23d5eb
--- /dev/null
+++ b/intern/instant-meshes/Readme.Blender.MD
@@ -0,0 +1 @@
+This is a fork of instant-meshes, an alternative to QuadriFlow.
diff --git a/intern/instant-meshes/instant_meshes_c_api.h b/intern/instant-meshes/instant_meshes_c_api.h
new file mode 100644
index 00000000000..038a8769eb8
--- /dev/null
+++ b/intern/instant-meshes/instant_meshes_c_api.h
@@ -0,0 +1,56 @@
+#pragma once
+
+/* clang-format off */
+//remeshedge->flag
+enum {
+  REMESH_EDGE_BOUNDARY = (1<<0),
+  REMESH_EDGE_USE_DIR = (1<<1)
+};
+/* clang-format on */
+
+typedef struct RemeshVertex {
+  float co[3], no[3];
+} RemeshVertex;
+
+// edge constraint
+typedef struct RemeshEdge {
+  int v1, v2, flag;
+  float dir[3];
+} RemeshEdge;
+
+typedef struct RemeshTri {
+  int v1, v2, v3;
+  int eflags[3];
+} RemeshTri;
+
+typedef struct RemeshOutFace {
+  int *verts;
+  int totvert;
+} RemeshOutFace;
+
+typedef struct RemeshMesh {
+  RemeshTri *tris;
+  RemeshVertex *verts;
+  RemeshEdge *edges;  // list of constrained edges, need not be all edges in the mesh
+
+  int tottri, totvert, totedge;
+
+  RemeshOutFace *outfaces;
+  RemeshVertex *outverts;
+  int *out_scracth;
+
+  int totoutface;
+  int totoutvert;
+} RemeshMesh;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void instant_meshes_run(RemeshMesh *mesh);
+void instant_meshes_finish(RemeshMesh *mesh);
+void instant_meshes_set_number_of_threads(int n);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/intern/instant-meshes/src/c_api.cpp b/intern/instant-meshes/src/c_api.cpp
new file mode 100644
index 00000000000..5bfc47c6c66
--- /dev/null
+++ b/intern/instant-meshes/src/c_api.cpp
@@ -0,0 +1,347 @@
+#include "MEM_guardedalloc.h"
+
+#include "adjacency.h"
+#include "cleanup.h"
+#include "common.h"
+#include "dedge.h"
+#include "extract.h"
+#include "field.h"
+#include "hierarchy.h"
+#include "normal.h"
+#include "smoothcurve.h"
+#include "subdivide.h"
+
+#include "meshstats.h"
+
+#include "../instant_meshes_c_api.h"
+
+#include <set>
+
+int instant_meshes_nprocs = 1;
+
+const float len_v3v3(const float *a, const float *b)
+{
+  float dx = a[0] - b[0];
+  float dy = a[1] - b[1];
+  float dz = a[2] - b[2];
+
+  float len = dx * dx + dy * dy + dz * dz;
+
+  return len > 0.0f ? sqrtf(len) : 0.0f;
+}
+
+extern "C" {
+void instant_meshes_run(RemeshMesh *mesh)
+{
+  MatrixXu F;
+  MatrixXf V;
+  MatrixXf N;
+
+  float elen = 0.0f;
+  int totlen = 0;
+  float scale = 0.1f;
+
+  std::set<uint32_t> creaseSet;
+
+  F.resize(3, mesh->tottri);
+  V.resize(3, mesh->totvert);
+  N.resize(3, mesh->totvert);
+
+  // F.resize(mesh->tottri * 3);
+  // V.resize(mesh->totvert * 3);
+  // N.resize(mesh->totvert * 3);
+
+  for (int i = 0; i < mesh->tottri; i++) {
+    RemeshTri *tri = mesh->tris + i;
+
+    elen += len_v3v3(mesh->verts[tri->v1].co, mesh->verts[tri->v2].co);
+    elen += len_v3v3(mesh->verts[tri->v2].co, mesh->verts[tri->v3].co);
+    elen += len_v3v3(mesh->verts[tri->v3].co, mesh->verts[tri->v1].co);
+    totlen += 3;
+
+    F(0, i) = tri->v1;
+    F(1, i) = tri->v2;
+    F(2, i) = tri->v3;
+  }
+
+  for (int i = 0; i < mesh->totvert; i++) {
+    RemeshVertex *v = mesh->verts + i;
+
+    for (int j = 0; j < 3; j++) {
+      V(j, i) = v->co[j];
+      N(j, i) = v->no[j];
+    }
+  }
+
+  if (totlen > 0) {
+    elen /= totlen;
+    scale = elen * 4.0f;
+  }
+
+  const bool extrinsic = true;
+  const bool deterministic = false;
+  const int rosy = 4, posy = 4;
+
+  printf("scale: %.5f\n", scale);
+
+  VectorXu V2E, E2E;
+  VectorXb boundary;
+  VectorXb nonManifold;
+
+  nonManifold.resize(V.cols());
+
+  build_dedge(F, V, V2E, E2E, boundary, nonManifold);
+  // AdjacencyMatrix adj = generate_adjacency_matrix_cotan(F, V, V2E, E2E, nonManifold);
+  AdjacencyMatrix adj = generate_adjacency_matrix_uniform(F, V2E, E2E, nonManifold);
+
+  VectorXf A;
+
+  generate_smooth_normals(F, V, V2E, E2E, nonManifold, N);
+  compute_dual_vertex_areas(F, V, V2E, E2E, nonManifold, A);
+
+  MultiResolutionHierarchy mRes;
+
+  mRes.setF(std::move(F));
+  mRes.setV(std::move(V));
+  mRes.setN(std::move(N));
+  mRes.setE2E(std::move(E2E));
+  mRes.setAdj(std::move(adj));
+  mRes.setA(std::move(A));
+  mRes.setScale(scale);
+
+  printf("building multiresolution hierarchy\n");
+  mRes.build(deterministic);
+  mRes.resetSolution();
+
+  /* set up edge constraints */
+  mRes.clearConstraints();
+
+  for (int i = 0; i < mesh->totedge; i++) {
+    RemeshEdge *e = mesh->edges + i;
+
+    const MatrixXu &F = mRes.F();
+    const MatrixXf &N = mRes.N(), &V = mRes.V();
+    const VectorXu &E2E = mRes.E2E();
+
+    uint32_t i0 = (uint32_t)e->v1;
+    uint32_t i1 = (uint32_t)e->v2;
+    Vector3f p0 = V.col(i0), p1 = V.col(i1);
+
+    if (0 && (e->flag & REMESH_EDGE_USE_DIR)) {
+      Vector3f dir(e->dir);
+
+      if (dir.squaredNorm() > 0) {
+        mRes.CO().col(i0) = p0;
+        mRes.CO().col(i1) = p1;
+        mRes.CQ().col(i0) = mRes.CQ().col(i1) = dir;
+        mRes.CQw()[i0] = mRes.CQw()[i1] = mRes.COw()[i0] = mRes.COw()[i1] = 0.05f;
+      }
+    }
+    else if (e->flag & REMESH_EDGE_BOUNDARY) {
+      Vector3f edge = p1 - p0;
+
+      creaseSet.insert((uint32_t)e->v1);
+      creaseSet.insert((uint32_t)e->v2);
+
+      if (edge.squaredNorm() > 0) {
+        edge.normalize();
+        mRes.CO().col(i0) = p0;
+        mRes.CO().col(i1) = p1;
+        mRes.CQ().col(i0) = mRes.CQ().col(i1) = edge;
+        mRes.CQw()[i0] = mRes.CQw()[i1] = mRes.COw()[i0] = mRes.COw()[i1] = 1.0f;
+      }
+    }
+  }
+
+  mRes.propagateConstraints(rosy, posy);
+
+  Optimizer opt(mRes, false);
+
+  opt.setExtrinsic(extrinsic);
+  opt.setRoSy(rosy);
+  opt.setPoSy(posy);
+
+  printf("optimizing orientation field\n");
+  for (int step = 0; step < 1; step++) {
+    opt.optimizeOrientations(-1);
+    opt.notify();
+    opt.wait();
+  }
+
+  std::map<uint32_t, uint32_t> sing;
+  compute_orientation_singularities(mRes, sing, extrinsic, rosy);
+  cout << "Orientation field has " << sing.size() << " singularities." << endl;
+
+  printf("optimizing position field\n");
+  for (int step = 0; step < 1; step++) {
+    opt.optimizePositions(-1);
+    opt.notify();
+    opt.wait();
+  }
+
+  std::map<uint32_t, Vector2i> pos_sing;
+  compute_position_singularities(mRes, sing, pos_sing, extrinsic, rosy, posy);
+  cout << "Position field has " << pos_sing.size() << " singularities." << endl;
+
+  opt.shutdown();
+
+  std::vector<std::vector<TaggedLink>> adj_extracted;
+
+  MatrixXu F_extracted;
+  MatrixXf V_extracted;
+  MatrixXf N_extracted;
+  MatrixXf Nf_extracted;
+
+  std::set<uint32_t> creaseOut;
+
+  printf("extracting mesh\n");
+
+  extract_graph(mRes,
+                extrinsic,
+                rosy,
+                posy,
+                adj_extracted,
+                V_extracted,
+                N_extracted,
+                creaseSet,
+                creaseOut,
+                deterministic,
+                true,
+                true,
+                true);
+
+  extract_faces(adj_extracted,
+                V_extracted,
+                N_extracted,
+                Nf_extracted,
+                F_extracted,
+                posy,
+                mRes.scale(),
+                creaseOut,
+                true,
+                false,
+                nullptr,
+                0);
+
+  // F_extracted = mRes.F();
+  // V_extracted = mRes.V();
+
+  mesh->totoutface = F_extracted.cols();
+  mesh->totoutvert = V_extracted.cols();
+
+  int sides = F_extracted.rows();
+
+  mesh->outfaces = (RemeshOutFace *)MEM_malloc_arrayN(
+      mesh->totoutface, sizeof(RemeshOutFace), "RemeshOutFaces");
+  mesh->outverts = (RemeshVertex *)MEM_malloc_arrayN(
+      mesh->totoutvert, sizeof(RemeshVertex), "RemeshOutVerts");
+  mesh->out_scracth = (int *)MEM_malloc_arrayN(
+      mesh->totoutface * sides, sizeof(int), "out_scratch");
+
+  printf(
+      "sides:%d\ntotal faces: %d\ntotal verts: %d\n", sides, mesh->totoutface, mesh->totoutvert);
+
+  RemeshOutFace *f = mesh->outfaces;
+  int totface = mesh->totoutface;
+  int i = 0, fi = 0, li = 0;
+
+  /* Check for irregular faces */
+  std::map<uint32_t, std::pair<uint32_t, std::map<uint32_t, uint32_t>>> irregular;
+  size_t nIrregular = 0;
+
+  for (; fi < totface; fi++) {
+    if (F_extracted(2, fi) == F_extracted(3, fi)) {
+      nIrregular++;
+      auto &value = irregular[F_extracted(2, fi)];
+      value.first = fi;
+      value.second[F_extracted(0, fi)] = F_extracted(1, fi);
+      continue;
+    }
+
+    f->verts = mesh->out_scracth + li;
+    li += sides;
+
+    int j = 0;
+
+    for (j = 0; j < sides; j++) {
+      f->verts[j] = F_extracted(j, fi);
+    }
+
+    //  if (j != sides) {
+    //      i--;
+    //}
+
+    f->totvert = sides;
+    i++;
+    f++;
+  }
+
+  for (auto item : irregular) {
+    auto face = item.second;
+    uint32_t v = face.second.begin()->first, first = v, k = 0;
+
+    int j = 0;
+    f->verts = mesh->out_scracth + li;
+
+    while (true) {
+      v = face.second[v];
+      f->verts[j] = (int)v;
+
+      li++;
+      j++;
+
+      if (v == first || ++k == face.second.size())
+        break;
+    }
+
+    f->totvert = j;
+
+    f++;
+    i++;
+  }
+
+  printf("final totface: %d, alloc totface: %d\n", i, mesh->totoutface);
+  printf("final totloop: %d, alloc totloop: %d\n", li, mesh->totoutface * sides);
+
+  mesh->totoutface = i;
+
+  RemeshVertex *v = mesh->outverts;
+  for (int i = 0; i < m

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list