[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