19#include <Eigen/Geometry>
20#include <Eigen/IterativeLinearSolvers>
22#include <Eigen/SparseCholesky>
46template<
typename DerivedV,
typename DerivedF>
47static inline void grad(
const Eigen::PlainObjectBase<DerivedV> &
V,
48 const Eigen::PlainObjectBase<DerivedF> &
F,
49 Eigen::SparseMatrix<typename DerivedV::Scalar> &
G,
52 Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> eperp21(
F.rows(), 3),
55 for (
int i = 0; i <
F.rows(); ++i) {
62 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v32 =
V.row(i3) -
V.row(i2);
63 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v13 =
V.row(i1) -
V.row(i3);
64 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v21 =
V.row(i2) -
V.row(i1);
65 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> n = v32.cross(v13);
70 double dblA = std::sqrt(n.dot(n));
71 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> u;
80 double h =
sqrt((dblA) /
83 Eigen::VectorXd v1,
v2, v3;
86 v3 << h / 2., (
sqrt(3) / 2.) * h, 0;
96 double norm21 = std::sqrt(v21.dot(v21));
97 double norm13 = std::sqrt(v13.dot(v13));
98 eperp21.row(i) = u.cross(v21);
99 eperp21.row(i) = eperp21.row(i) / std::sqrt(eperp21.row(i).dot(eperp21.row(i)));
100 eperp21.row(i) *= norm21 / dblA;
101 eperp13.row(i) = u.cross(v13);
102 eperp13.row(i) = eperp13.row(i) / std::sqrt(eperp13.row(i).dot(eperp13.row(i)));
103 eperp13.row(i) *= norm13 / dblA;
107 rs.reserve(
F.rows() * 4 * 3);
109 cs.reserve(
F.rows() * 4 * 3);
110 std::vector<double> vs;
111 vs.reserve(
F.rows() * 4 * 3);
114 for (
int r = 0; r < 3; r++) {
115 for (
int j = 0; j < 4; j++) {
116 for (
int i = r *
F.rows(); i < (r + 1) *
F.rows(); i++)
122 for (
int r = 0; r < 3; r++) {
123 for (
int i = 0; i <
F.rows(); i++)
124 cs.push_back(
F(i, 1));
125 for (
int i = 0; i <
F.rows(); i++)
126 cs.push_back(
F(i, 0));
127 for (
int i = 0; i <
F.rows(); i++)
128 cs.push_back(
F(i, 2));
129 for (
int i = 0; i <
F.rows(); i++)
130 cs.push_back(
F(i, 0));
134 for (
int i = 0; i <
F.rows(); i++)
135 vs.push_back(eperp13(i, 0));
136 for (
int i = 0; i <
F.rows(); i++)
137 vs.push_back(-eperp13(i, 0));
138 for (
int i = 0; i <
F.rows(); i++)
139 vs.push_back(eperp21(i, 0));
140 for (
int i = 0; i <
F.rows(); i++)
141 vs.push_back(-eperp21(i, 0));
142 for (
int i = 0; i <
F.rows(); i++)
143 vs.push_back(eperp13(i, 1));
144 for (
int i = 0; i <
F.rows(); i++)
145 vs.push_back(-eperp13(i, 1));
146 for (
int i = 0; i <
F.rows(); i++)
147 vs.push_back(eperp21(i, 1));
148 for (
int i = 0; i <
F.rows(); i++)
149 vs.push_back(-eperp21(i, 1));
150 for (
int i = 0; i <
F.rows(); i++)
151 vs.push_back(eperp13(i, 2));
152 for (
int i = 0; i <
F.rows(); i++)
153 vs.push_back(-eperp13(i, 2));
154 for (
int i = 0; i <
F.rows(); i++)
155 vs.push_back(eperp21(i, 2));
156 for (
int i = 0; i <
F.rows(); i++)
157 vs.push_back(-eperp21(i, 2));
160 G.resize(3 *
F.rows(),
V.rows());
161 std::vector<Eigen::Triplet<typename DerivedV::Scalar>> triplets;
162 for (
int i = 0; i < (
int)vs.size(); ++i) {
163 triplets.push_back(Eigen::Triplet<typename DerivedV::Scalar>(rs[i], cs[i], vs[i]));
165 G.setFromTriplets(triplets.begin(), triplets.end());
180template<
typename DerivedA,
186static inline void polar_svd(
const Eigen::PlainObjectBase<DerivedA> &
A,
187 Eigen::PlainObjectBase<DerivedR> &
R,
188 Eigen::PlainObjectBase<DerivedT> &
T,
189 Eigen::PlainObjectBase<DerivedU> &
U,
190 Eigen::PlainObjectBase<DerivedS> &S,
191 Eigen::PlainObjectBase<DerivedV> &
V)
194 Eigen::JacobiSVD<DerivedA> svd;
195 svd.compute(
A, Eigen::ComputeFullU | Eigen::ComputeFullV);
198 S = svd.singularValues();
199 R =
U *
V.transpose();
200 const auto &SVT = S.asDiagonal() *
V.adjoint();
202 if (
R.determinant() < 0) {
205 W.col(
V.cols() - 1) *= -1.;
206 R =
U *
W.transpose();
215 const Eigen::MatrixXi &
F,
216 const Eigen::MatrixXd &F1,
217 const Eigen::MatrixXd &F2,
218 Eigen::SparseMatrix<double> &D1,
219 Eigen::SparseMatrix<double> &D2)
221 Eigen::SparseMatrix<double>
G;
223 Eigen::SparseMatrix<double> Dx =
G.block(0, 0,
F.rows(),
V.rows());
224 Eigen::SparseMatrix<double> Dy =
G.block(
F.rows(), 0,
F.rows(),
V.rows());
225 Eigen::SparseMatrix<double> Dz =
G.block(2 *
F.rows(), 0,
F.rows(),
V.rows());
227 D1 = F1.col(0).asDiagonal() * Dx + F1.col(1).asDiagonal() * Dy + F1.col(2).asDiagonal() * Dz;
228 D2 = F2.col(0).asDiagonal() * Dx + F2.col(1).asDiagonal() * Dy + F2.col(2).asDiagonal() * Dz;
236 s.
Ji.col(0) = s.
Dx * uv.col(0);
237 s.
Ji.col(1) = s.
Dy * uv.col(0);
238 s.
Ji.col(2) = s.
Dx * uv.col(1);
239 s.
Ji.col(3) = s.
Dy * uv.col(1);
243 s.
Ji.col(0) = weights.cwiseProduct(s.
Ji.col(0));
244 s.
Ji.col(1) = weights.cwiseProduct(s.
Ji.col(1));
245 s.
Ji.col(2) = weights.cwiseProduct(s.
Ji.col(2));
246 s.
Ji.col(3) = weights.cwiseProduct(s.
Ji.col(3));
254 s.
Ji.col(0) = s.
Dx * uv.col(0);
255 s.
Ji.col(1) = s.
Dy * uv.col(0);
256 s.
Ji.col(2) = s.
Dx * uv.col(1);
257 s.
Ji.col(3) = s.
Dy * uv.col(1);
277 const double eps = 1
e-8;
280 for (
int i = 0; i < s.
Ji.rows(); ++i) {
281 typedef Eigen::Matrix<double, 2, 2> Mat2;
282 typedef Eigen::Matrix<double, 2, 1>
Vec2;
283 Mat2 ji, ri, ti, ui, vi;
285 Vec2 closest_sing_vec;
290 ji(0, 0) = s.
Ji(i, 0);
291 ji(0, 1) = s.
Ji(i, 1);
292 ji(1, 0) = s.
Ji(i, 2);
293 ji(1, 1) = s.
Ji(i, 3);
307 double s1_g = 2 * (s1 -
pow(s1, -3));
308 double s2_g = 2 * (s2 -
pow(s2, -3));
309 m_sing_new <<
sqrt(s1_g / (2 * (s1 - 1))),
sqrt(s2_g / (2 * (s2 - 1)));
313 double s1_g = 2 * (
log(s1) / s1);
314 double s2_g = 2 * (
log(s2) / s2);
315 m_sing_new <<
sqrt(s1_g / (2 * (s1 - 1))),
sqrt(s2_g / (2 * (s2 - 1)));
319 double s1_g = 1 / (2 * s2) - s2 / (2 *
pow(s1, 2));
320 double s2_g = 1 / (2 * s1) - s1 / (2 *
pow(s2, 2));
322 double geo_avg =
sqrt(s1 * s2);
323 double s1_min = geo_avg;
324 double s2_min = geo_avg;
326 m_sing_new <<
sqrt(s1_g / (2 * (s1 - s1_min))),
sqrt(s2_g / (2 * (s2 - s2_min)));
329 closest_sing_vec << s1_min, s2_min;
330 ri = ui * closest_sing_vec.asDiagonal() * vi.transpose();
334 double s1_g = 2 * (s1 -
pow(s1, -3));
335 double s2_g = 2 * (s2 -
pow(s2, -3));
337 double in_exp = exp_f * ((
pow(s1, 2) +
pow(s2, 2)) / (2 * s1 * s2));
338 double exp_thing =
exp(in_exp);
340 s1_g *= exp_thing * exp_f;
341 s2_g *= exp_thing * exp_f;
343 m_sing_new <<
sqrt(s1_g / (2 * (s1 - 1))),
sqrt(s2_g / (2 * (s2 - 1)));
347 double s1_g = 2 * (s1 -
pow(s1, -3));
348 double s2_g = 2 * (s2 -
pow(s2, -3));
350 double in_exp = exp_f * (
pow(s1, 2) +
pow(s1, -2) +
pow(s2, 2) +
pow(s2, -2));
351 double exp_thing =
exp(in_exp);
353 s1_g *= exp_thing * exp_f;
354 s2_g *= exp_thing * exp_f;
356 m_sing_new <<
sqrt(s1_g / (2 * (s1 - 1))),
sqrt(s2_g / (2 * (s2 - 1)));
361 if (std::abs(s1 - 1) <
eps)
363 if (std::abs(s2 - 1) <
eps)
365 mat_W = ui * m_sing_new.asDiagonal() * ui.transpose();
367 s.
W_11(i) = mat_W(0, 0);
368 s.
W_12(i) = mat_W(0, 1);
369 s.
W_21(i) = mat_W(1, 0);
370 s.
W_22(i) = mat_W(1, 1);
374 s.
Ri(i, 0) = ri(0, 0);
375 s.
Ri(i, 1) = ri(1, 0);
376 s.
Ri(i, 2) = ri(0, 1);
377 s.
Ri(i, 3) = ri(1, 1);
381template<
typename DerivedV,
typename DerivedF>
382static inline void local_basis(
const Eigen::PlainObjectBase<DerivedV> &
V,
383 const Eigen::PlainObjectBase<DerivedF> &
F,
384 Eigen::PlainObjectBase<DerivedV> &B1,
385 Eigen::PlainObjectBase<DerivedV> &B2,
386 Eigen::PlainObjectBase<DerivedV> &B3)
388 using namespace Eigen;
390 B1.resize(
F.rows(), 3);
391 B2.resize(
F.rows(), 3);
392 B3.resize(
F.rows(), 3);
394 for (
unsigned i = 0; i <
F.rows(); ++i) {
395 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v1 =
396 (
V.row(
F(i, 1)) -
V.row(
F(i, 0))).normalized();
397 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> t =
V.row(
F(i, 2)) -
V.row(
F(i, 0));
398 Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v3 = v1.cross(t).normalized();
399 Eigen::Matrix<typename DerivedV::Scalar, 1, 3>
v2 = v1.cross(v3).normalized();
415 Eigen::MatrixXd F1, F2, F3;
424 s.
Dx.makeCompressed();
425 s.
Dy.makeCompressed();
426 s.
Dz.makeCompressed();
433 for (
int i = 0; i < s.
dim * s.
dim; i++)
434 for (
int j = 0; j < s.
f_n; j++)
446 std::vector<Eigen::Triplet<double>> IJV;
448 IJV.reserve(4 * (s.
Dx.outerSize() + s.
Dy.outerSize()));
454 for (
int k = 0; k < s.
Dx.outerSize(); ++k) {
455 for (Eigen::SparseMatrix<double>::InnerIterator it(s.
Dx, k); it; ++it) {
458 double val = it.value();
461 IJV.push_back(Eigen::Triplet<double>(dx_r, dx_c, weight * val * s.
W_11(dx_r)));
462 IJV.push_back(Eigen::Triplet<double>(dx_r, s.
v_n + dx_c, weight * val * s.
W_12(dx_r)));
464 IJV.push_back(Eigen::Triplet<double>(2 * s.
f_n + dx_r, dx_c, weight * val * s.
W_21(dx_r)));
466 Eigen::Triplet<double>(2 * s.
f_n + dx_r, s.
v_n + dx_c, weight * val * s.
W_22(dx_r)));
470 for (
int k = 0; k < s.
Dy.outerSize(); ++k) {
471 for (Eigen::SparseMatrix<double>::InnerIterator it(s.
Dy, k); it; ++it) {
474 double val = it.value();
477 IJV.push_back(Eigen::Triplet<double>(s.
f_n + dy_r, dy_c, weight * val * s.
W_11(dy_r)));
479 Eigen::Triplet<double>(s.
f_n + dy_r, s.
v_n + dy_c, weight * val * s.
W_12(dy_r)));
481 IJV.push_back(Eigen::Triplet<double>(3 * s.
f_n + dy_r, dy_c, weight * val * s.
W_21(dy_r)));
483 Eigen::Triplet<double>(3 * s.
f_n + dy_r, s.
v_n + dy_c, weight * val * s.
W_22(dy_r)));
487 A.setFromTriplets(IJV.begin(), IJV.end());
494 Eigen::VectorXd f_rhs(s.
dim * s.
dim * s.
f_n);
501 for (
int i = 0; i < s.
f_n; i++) {
502 f_rhs(i + 0 * s.
f_n) = s.
W_11(i) * s.
Ri(i, 0) + s.
W_12(i) * s.
Ri(i, 1);
503 f_rhs(i + 1 * s.
f_n) = s.
W_11(i) * s.
Ri(i, 2) + s.
W_12(i) * s.
Ri(i, 3);
504 f_rhs(i + 2 * s.
f_n) = s.
W_21(i) * s.
Ri(i, 0) + s.
W_22(i) * s.
Ri(i, 1);
505 f_rhs(i + 3 * s.
f_n) = s.
W_21(i) * s.
Ri(i, 2) + s.
W_22(i) * s.
Ri(i, 3);
508 Eigen::VectorXd uv_flat(s.
dim * s.
v_n);
509 for (
int i = 0; i < s.
dim; i++)
510 for (
int j = 0; j < s.
v_n; j++)
511 uv_flat(s.
v_n * i + j) = s.
V_o(j, i);
520 for (
int d = 0; d < s.
dim; d++) {
521 for (
int i = 0; i < s.
b.rows(); i++) {
524 L.coeffRef(d * v_n + v_idx, d * v_n + v_idx) += s.
soft_const_p;
536 Eigen::SparseMatrix<double> At =
A.transpose();
539 Eigen::SparseMatrix<double> id_m(At.rows(), At.rows());
547 Eigen::SparseMatrix<double> OldL =
L;
553 const Eigen::MatrixXd &Ji,
554 Eigen::VectorXd &areas,
555 Eigen::VectorXd &singularValues,
556 bool gatherSingularValues)
561 Eigen::Matrix<double, 2, 2> ji;
562 for (
int i = 0; i < s.
f_n; i++) {
568 typedef Eigen::Matrix<double, 2, 2> Mat2;
569 typedef Eigen::Matrix<double, 2, 1>
Vec2;
578 energy += areas(i) * (
pow(s1 - 1, 2) +
pow(s2 - 1, 2));
582 energy += areas(i) * (
pow(s1, 2) +
pow(s1, -2) +
pow(s2, 2) +
pow(s2, -2));
584 if (gatherSingularValues) {
585 singularValues(i) = s1;
586 singularValues(i + s.
F.rows()) = s2;
596 energy += areas(i) * (
pow(
log(s1), 2) +
pow(
log(s2), 2));
600 energy += areas(i) * ((
pow(s1, 2) +
pow(s2, 2)) / (2 * s1 * s2));
617 for (
int i = 0; i < s.
b.rows(); i++) {
624 Eigen::MatrixXd &V_new,
625 Eigen::VectorXd &singularValues,
626 bool gatherSingularValues)
637 Eigen::VectorXd temp;
642 Eigen::MatrixXd &V_new,
643 Eigen::VectorXd &singularValues)
651 Eigen::MatrixXd &V_init,
663 data.v_num =
V.rows();
664 data.f_num =
F.rows();
666 data.slim_energy = slim_energy;
670 data.soft_const_p = soft_p;
672 data.proximal_p = 0.0001;
678 data.mesh_improvement_3d =
false;
683 assert(
F.cols() == 3);
691 Eigen::VectorXd &areas)
693 int nFaces = singularValues.rows() / 2;
695 Eigen::VectorXd areasChained(2 * nFaces);
696 areasChained << areas, areas;
721 Eigen::VectorXd squaredSingularValues = singularValues.cwiseProduct(singularValues);
722 Eigen::VectorXd inverseSquaredSingularValues =
723 singularValues.cwiseProduct(singularValues).cwiseInverse();
725 Eigen::VectorXd weightedSquaredSingularValues = squaredSingularValues.cwiseProduct(areasChained);
726 Eigen::VectorXd weightedInverseSquaredSingularValues = inverseSquaredSingularValues.cwiseProduct(
729 double s1 = weightedSquaredSingularValues.head(nFaces).sum();
730 double s2 = weightedSquaredSingularValues.tail(nFaces).sum();
732 double t1 = weightedInverseSquaredSingularValues.head(nFaces).sum();
733 double t2 = weightedInverseSquaredSingularValues.tail(nFaces).sum();
746 using namespace Eigen;
748 Eigen::SparseMatrix<double>
L;
753 SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
754 Uc = solver.compute(
L).solve(s.
rhs);
756 for (
int i = 0; i < Uc.size(); i++)
757 if (!std::isfinite(Uc(i)))
760 for (
int i = 0; i < s.
dim; i++)
761 uv.col(i) = Uc.block(i * s.
v_n, 0, s.
v_n, 1);
767 Eigen::VectorXd singularValues;
768 bool are_pins_present =
data.b.rows() > 0;
770 if (are_pins_present) {
771 singularValues.resize(
data.F.rows() * 2);
775 for (
int i = 0; i < iter_num; i++) {
776 Eigen::MatrixXd dest_res;
783 std::function<
double(Eigen::MatrixXd &)> compute_energy_func = [&](Eigen::MatrixXd &aaa) {
795 if (are_pins_present) {
798 data.Dx /=
data.globalScaleInvarianceFactor;
799 data.Dy /=
data.globalScaleInvarianceFactor;
typedef double(DMatrix)[4][4]
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
local_group_size(16, 16) .push_constant(Type b
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
ccl_device_inline float3 exp(float3 v)
ccl_device_inline float3 log(float3 v)
static double compute_soft_const_energy(SLIMData &s, Eigen::MatrixXd &V_o)
void slim_precompute(Eigen::MatrixXd &V, Eigen::MatrixXi &F, Eigen::MatrixXd &V_init, SLIMData &data, SLIMData::SLIM_ENERGY slim_energy, Eigen::VectorXi &b, Eigen::MatrixXd &bc, double soft_p)
static void compute_jacobians(SLIMData &s, const Eigen::MatrixXd &uv)
static void update_weights_and_closest_rotations(SLIMData &s, Eigen::MatrixXd &uv)
static void polar_svd(const Eigen::PlainObjectBase< DerivedA > &A, Eigen::PlainObjectBase< DerivedR > &R, Eigen::PlainObjectBase< DerivedT > &T, Eigen::PlainObjectBase< DerivedU > &U, Eigen::PlainObjectBase< DerivedS > &S, Eigen::PlainObjectBase< DerivedV > &V)
void doublearea(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DeriveddblA > &dblA)
static void buildRhs(SLIMData &s, const Eigen::SparseMatrix< double > &At)
static void compute_surface_gradient_matrix(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::MatrixXd &F1, const Eigen::MatrixXd &F2, Eigen::SparseMatrix< double > &D1, Eigen::SparseMatrix< double > &D2)
static double compute_energy_with_jacobians(SLIMData &s, const Eigen::MatrixXd &Ji, Eigen::VectorXd &areas, Eigen::VectorXd &singularValues, bool gatherSingularValues)
static void build_linear_system(SLIMData &s, Eigen::SparseMatrix< double > &L)
static void buildA(SLIMData &s, Eigen::SparseMatrix< double > &A)
static void pre_calc(SLIMData &s)
double computeGlobalScaleInvarianceFactor(Eigen::VectorXd &singularValues, Eigen::VectorXd &areas)
static void solve_weighted_arap(SLIMData &s, Eigen::MatrixXd &uv)
static void local_basis(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedV > &B1, Eigen::PlainObjectBase< DerivedV > &B2, Eigen::PlainObjectBase< DerivedV > &B3)
static void compute_weighted_jacobians(SLIMData &s, const Eigen::MatrixXd &uv)
static void add_soft_constraints(SLIMData &s, Eigen::SparseMatrix< double > &L)
Eigen::MatrixXd slim_solve(SLIMData &data, int iter_num)
double flip_avoiding_line_search(const Eigen::MatrixXi F, Eigen::MatrixXd &cur_v, Eigen::MatrixXd &dst_v, std::function< double(Eigen::MatrixXd &)> energy, double cur_energy)
static double compute_energy(SLIMData &s, Eigen::MatrixXd &V_new, Eigen::VectorXd &singularValues, bool gatherSingularValues)
static void compute_unweighted_jacobians(SLIMData &s, const Eigen::MatrixXd &uv)
static void grad(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::SparseMatrix< typename DerivedV::Scalar > &G, bool uniform=false)
bool withWeightedParameterization
Eigen::VectorXf weightPerFaceMap
Eigen::SparseMatrix< double > Dy
@ EXP_SYMMETRIC_DIRICHLET
Eigen::SparseMatrix< double > Dx
Eigen::SparseMatrix< double > Dz
CCL_NAMESPACE_BEGIN struct Window V