[Bf-blender-cvs] [956a61be719] quadriflow: Initial quadriflow border preservation
Sebastian Parborg
noreply at git.blender.org
Tue Sep 10 18:36:05 CEST 2019
Commit: 956a61be719395656c84dcc42f281f72352d6748
Author: Sebastian Parborg
Date: Fri Aug 30 14:57:01 2019 +0200
Branches: quadriflow
https://developer.blender.org/rB956a61be719395656c84dcc42f281f72352d6748
Initial quadriflow border preservation
===================================================================
M extern/quadriflow/blender_config.cmake
M extern/quadriflow/src/hierarchy.cpp
M extern/quadriflow/src/hierarchy.hpp
M extern/quadriflow/src/main.cpp
M extern/quadriflow/src/optimizer.cpp
M extern/quadriflow/src/parametrizer-mesh.cpp
M extern/quadriflow/src/parametrizer.hpp
M intern/quadriflow/quadriflow_capi.cpp
M intern/quadriflow/quadriflow_capi.hpp
M source/blender/blenkernel/BKE_mesh_remesh_voxel.h
M source/blender/blenkernel/intern/mesh_remesh_voxel.c
M source/blender/editors/object/object_remesh.c
===================================================================
diff --git a/extern/quadriflow/blender_config.cmake b/extern/quadriflow/blender_config.cmake
index b0e4c947952..19500d67774 100644
--- a/extern/quadriflow/blender_config.cmake
+++ b/extern/quadriflow/blender_config.cmake
@@ -3,7 +3,7 @@
set(QUADRIFLOW_STANDALONE FALSE)
set(BUILD_PERFORMANCE_TEST FALSE)
-set(BUILD_LOG FALSE)
+set(BUILD_LOG TRUE)
set(BUILD_GUROBI FALSE)
set(BUILD_OPENMP ${WITH_OPENMP})
set(BUILD_TBB FALSE)
diff --git a/extern/quadriflow/src/hierarchy.cpp b/extern/quadriflow/src/hierarchy.cpp
index 3806089a4d8..c333256a139 100644
--- a/extern/quadriflow/src/hierarchy.cpp
+++ b/extern/quadriflow/src/hierarchy.cpp
@@ -23,6 +23,11 @@ Hierarchy::Hierarchy() {
mToLower.resize(MAX_DEPTH);
mToUpper.resize(MAX_DEPTH);
rng_seed = 0;
+
+ mCQ.reserve(MAX_DEPTH + 1);
+ mCQw.reserve(MAX_DEPTH + 1);
+ mCO.reserve(MAX_DEPTH + 1);
+ mCOw.reserve(MAX_DEPTH + 1);
}
#undef max
@@ -30,6 +35,7 @@ Hierarchy::Hierarchy() {
void Hierarchy::Initialize(double scale, int with_scale) {
this->with_scale = with_scale;
generate_graph_coloring_deterministic(mAdj[0], mV[0].cols(), mPhases[0]);
+
for (int i = 0; i < MAX_DEPTH; ++i) {
DownsampleGraph(mAdj[i], mV[i], mN[i], mA[i], mV[i + 1], mN[i + 1], mA[i + 1], mToUpper[i],
mToLower[i], mAdj[i + 1]);
@@ -49,6 +55,11 @@ void Hierarchy::Initialize(double scale, int with_scale) {
mS.resize(mV.size());
mK.resize(mV.size());
+ mCO.resize(mV.size());
+ mCOw.resize(mV.size());
+ mCQ.resize(mV.size());
+ mCQw.resize(mV.size());
+
//Set random seed
srand(rng_seed);
@@ -1090,6 +1101,124 @@ void Hierarchy::PropagateEdge() {
}
}
+void Hierarchy::clearConstraints() {
+ int levels = mV.size();
+ if (levels == 0) return;
+ for (int i = 0; i < levels; ++i) {
+ int size = mV[i].cols();
+ mCQ[i].resize(3, size);
+ mCO[i].resize(3, size);
+ mCQw[i].resize(size);
+ mCOw[i].resize(size);
+ mCQw[i].setZero();
+ mCOw[i].setZero();
+ }
+}
+
+void Hierarchy::propagateConstraints() {
+ int levels = mV.size();
+ if (levels == 0) return;
+
+ for (int l = 0; l < levels - 1; ++l) {
+ auto& N = mN[l];
+ auto& N_next = mN[l + 1];
+ auto& V = mV[l];
+ auto& V_next = mV[l + 1];
+ auto& CQ = mCQ[l];
+ auto& CQ_next = mCQ[l + 1];
+ auto& CQw = mCQw[l];
+ auto& CQw_next = mCQw[l + 1];
+ auto& CO = mCO[l];
+ auto& CO_next = mCO[l + 1];
+ auto& COw = mCOw[l];
+ auto& COw_next = mCOw[l + 1];
+ auto& toUpper = mToUpper[l];
+ MatrixXd& S = mS[l];
+
+ for (uint32_t i = 0; i != mV[l + 1].cols(); ++i) {
+ Vector2i upper = toUpper.col(i);
+ Vector3d cq = Vector3d::Zero(), co = Vector3d::Zero();
+ float cqw = 0.0f, cow = 0.0f;
+
+ bool has_cq0 = CQw[upper[0]] != 0;
+ bool has_cq1 = upper[1] != -1 && CQw[upper[1]] != 0;
+ bool has_co0 = COw[upper[0]] != 0;
+ bool has_co1 = upper[1] != -1 && COw[upper[1]] != 0;
+
+ if (has_cq0 && !has_cq1) {
+ cq = CQ.col(upper[0]);
+ cqw = CQw[upper[0]];
+ } else if (has_cq1 && !has_cq0) {
+ cq = CQ.col(upper[1]);
+ cqw = CQw[upper[1]];
+ } else if (has_cq1 && has_cq0) {
+ Vector3d q_i = CQ.col(upper[0]);
+ Vector3d n_i = CQ.col(upper[0]);
+ Vector3d q_j = CQ.col(upper[1]);
+ Vector3d n_j = CQ.col(upper[1]);
+ auto result = compat_orientation_extrinsic_4(q_i, n_i, q_j, n_j);
+ cq = result.first * CQw[upper[0]] + result.second * CQw[upper[1]];
+ cqw = (CQw[upper[0]] + CQw[upper[1]]);
+ }
+ if (cq != Vector3d::Zero()) {
+ Vector3d n = N_next.col(i);
+ cq -= n.dot(cq) * n;
+ if (cq.squaredNorm() > RCPOVERFLOW) cq.normalize();
+ }
+
+ if (has_co0 && !has_co1) {
+ co = CO.col(upper[0]);
+ cow = COw[upper[0]];
+ } else if (has_co1 && !has_co0) {
+ co = CO.col(upper[1]);
+ cow = COw[upper[1]];
+ } else if (has_co1 && has_co0) {
+ double scale_x = mScale;
+ double scale_y = mScale;
+ if (with_scale) {
+ // FIXME
+ // scale_x *= S(0, i);
+ // scale_y *= S(1, i);
+ }
+ double inv_scale_x = 1.0f / scale_x;
+ double inv_scale_y = 1.0f / scale_y;
+
+ double scale_x_1 = mScale;
+ double scale_y_1 = mScale;
+ if (with_scale) {
+ // FIXME
+ // scale_x_1 *= S(0, j);
+ // scale_y_1 *= S(1, j);
+ }
+ double inv_scale_x_1 = 1.0f / scale_x_1;
+ double inv_scale_y_1 = 1.0f / scale_y_1;
+ auto result = compat_position_extrinsic_4(
+ V.col(upper[0]), N.col(upper[0]), CQ.col(upper[0]), CO.col(upper[0]),
+ V.col(upper[1]), N.col(upper[1]), CQ.col(upper[1]), CO.col(upper[1]), scale_x,
+ scale_y, inv_scale_x, inv_scale_y, scale_x_1, scale_y_1, inv_scale_x_1,
+ inv_scale_y_1);
+ cow = COw[upper[0]] + COw[upper[1]];
+ co = (result.first * COw[upper[0]] + result.second * COw[upper[1]]) / cow;
+ }
+ if (co != Vector3d::Zero()) {
+ Vector3d n = N_next.col(i), v = V_next.col(i);
+ co -= n.dot(cq - v) * n;
+ }
+#if 0
+ cqw *= 0.5f;
+ cow *= 0.5f;
+#else
+ if (cqw > 0) cqw = 1;
+ if (cow > 0) cow = 1;
+#endif
+
+ CQw_next[i] = cqw;
+ COw_next[i] = cow;
+ CQ_next.col(i) = cq;
+ CO_next.col(i) = co;
+ }
+ }
+}
#ifdef WITH_CUDA
#include <cuda_runtime.h>
diff --git a/extern/quadriflow/src/hierarchy.hpp b/extern/quadriflow/src/hierarchy.hpp
index 58132f6d7cb..8403038de4f 100644
--- a/extern/quadriflow/src/hierarchy.hpp
+++ b/extern/quadriflow/src/hierarchy.hpp
@@ -40,6 +40,9 @@ class Hierarchy {
void SaveToFile(FILE* fp);
void LoadFromFile(FILE* fp);
+ void clearConstraints();
+ void propagateConstraints();
+
double mScale;
int rng_seed;
@@ -58,6 +61,12 @@ class Hierarchy {
std::vector<MatrixXd> mS;
std::vector<MatrixXd> mK;
+ // constraints
+ std::vector<MatrixXd> mCQ;
+ std::vector<MatrixXd> mCO;
+ std::vector<VectorXd> mCQw;
+ std::vector<VectorXd> mCOw;
+
int with_scale;
// upper: fine to coarse
diff --git a/extern/quadriflow/src/main.cpp b/extern/quadriflow/src/main.cpp
index e4a6ec6ccb6..41ba1ab82d0 100644
--- a/extern/quadriflow/src/main.cpp
+++ b/extern/quadriflow/src/main.cpp
@@ -30,6 +30,8 @@ int main(int argc, char** argv) {
output_obj = argv[i + 1];
} else if (strcmp(argv[i], "-sharp") == 0) {
field.flag_preserve_sharp = 1;
+ } else if (strcmp(argv[i], "-border") == 0) {
+ field.flag_preserve_border = 1;
} else if (strcmp(argv[i], "-adaptive") == 0) {
field.flag_adaptive_scale = 1;
} else if (strcmp(argv[i], "-mcf") == 0) {
@@ -54,6 +56,29 @@ int main(int argc, char** argv) {
t2 = GetCurrentTime64();
printf("Use %lf seconds\n", (t2 - t1) * 1e-3);
+ if (field.flag_preserve_border) {
+ printf("Add border constrains...\n");
+ Hierarchy& mRes = field.hierarchy;
+ mRes.clearConstraints();
+ for (uint32_t i = 0; i < 3 * mRes.mF.cols(); ++i) {
+ if (mRes.mE2E[i] == -1) {
+ uint32_t i0 = mRes.mF(i % 3, i / 3);
+ uint32_t i1 = mRes.mF((i + 1) % 3, i / 3);
+ Vector3d p0 = mRes.mV[0].col(i0), p1 = mRes.mV[0].col(i1);
+ Vector3d edge = p1 - p0;
+ if (edge.squaredNorm() > 0) {
+ edge.normalize();
+ mRes.mCO[0].col(i0) = p0;
+ mRes.mCO[0].col(i1) = p1;
+ mRes.mCQ[0].col(i0) = mRes.mCQ[0].col(i1) = edge;
+ mRes.mCQw[0][i0] = mRes.mCQw[0][i1] = mRes.mCOw[0][i0] = mRes.mCOw[0][i1] =
+ 1.0;
+ }
+ }
+ }
+ mRes.propagateConstraints();
+ }
+
printf("Solve Orientation Field...\n");
t1 = GetCurrentTime64();
diff --git a/extern/quadriflow/src/optimizer.cpp b/extern/quadriflow/src/optimizer.cpp
index 24d6f7f9b73..47004f01126 100644
--- a/extern/quadriflow/src/optimizer.cpp
+++ b/extern/quadriflow/src/optimizer.cpp
@@ -42,6 +42,8 @@ void Optimizer::optimize_orientations(Hierarchy& mRes) {
for (int level = mRes.mN.size() - 1; level >= 0; --level) {
AdjacentMatrix& adj = mRes.mAdj[level];
const MatrixXd& N = mRes.mN[level];
+ const MatrixXd& CQ = mRes.mCQ[level];
+ const VectorXd& CQw = mRes.mCQw[level];
MatrixXd& Q = mRes.mQ[level];
auto& phases = mRes.mPhases[level];
for (int iter = 0; iter < levelIterations; ++iter) {
@@ -69,6 +71,20 @@ void Optimizer::optimize_orientations(Hierarchy& mRes) {
double norm = sum.norm();
if (norm > RCPOVERFLOW) sum /= norm;
}
+
+ if (CQw.size() > 0) {
+ float cw = CQw[i];
+ if (cw != 0) {
+ std::pair<Vector3d, Vector3d> value =
+ compat_orientation_extrinsic_4(sum, n_i, CQ.col(i), n_i);
+ sum = value.first * (1 - cw) + value.second * cw;
+ sum -= n_i * n_i.dot(sum);
+
+ float norm = sum.norm();
+ if (norm > RCPOVERFLOW) sum /= norm;
+ }
+ }
+
if (weight_sum
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list