// Choose an initial solution, and lock two vertices void MeshPara::init_slover() { // Get bbox Vec3f bAxis = bbMax - bbMin; // Get the Projection dirction int d1 ,d2, d3, i; d1 = d2 = d3 = 0; for (i = 1; i < 3; i++) { if (bAxis[i] > bAxis[d1]) d1 = i; if (bAxis[i] < bAxis[d3]) d3 = i; } for (d2 = 0; d2 < 3; d2++) { if (d2 != d1 && d2 != d3) break; } // Project vertices auto v_end(mesh_.vertices_end()); float u1 = -1.0e30, u2 = 1.0e30; int lock1 = 0, lock2 = 0; for (auto v_it = mesh_.vertices_begin(); v_it != v_end; ++v_it) { float u = mesh_.point(*v_it)[d1]; float v = mesh_.point(*v_it)[d2]; int idx = (*v_it).idx(); mesh_.set_texcoord2D(*v_it, Vec2f(u, v)); // set initial solution nlSetVariable(2 * idx, u); nlSetVariable(2 * idx + 1, v); if (u > u1) { lock1 = idx; u1 = u; } if (u < u2) { lock2 = idx; u2 = u; } } // set locked variables nlLockVariable(2 * lock1); nlLockVariable(2 * lock1 + 1); nlLockVariable(2 * lock2); nlLockVariable(2 * lock2 + 1); }
void leastSquaresSystem::solve(double *vs) { int i; Node *n; coeffIndexPair *f; nlNewContext(); nlSolverParameteri(NL_SOLVER, NL_PERM_SUPERLU_EXT); nlSolverParameteri(NL_NB_VARIABLES, num_variables); nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE) ; nlSolverParameteri(NL_MAX_ITERATIONS, 1000) ; nlSolverParameterd(NL_THRESHOLD, 1e-10) ; nlBegin(NL_SYSTEM); for (i=0; i<num_variables; i++) { nlSetVariable(i, vs[i]); if (locks[i]) nlLockVariable(i); } nlBegin(NL_MATRIX); for (i=0; i<num_equations; i++) { nlRowParameterd(NL_RIGHT_HAND_SIDE, known_term[0][i]); nlBegin(NL_ROW); for (n=rows[i].cips.head(); n!=NULL; n=n->next()) { f = (coeffIndexPair *)n->data; nlCoefficient(f->index, f->coeff); } nlEnd(NL_ROW); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); nlSolve(); for (i=0; i<num_variables; i++) vs[i] = nlGetVariable(i); nlDeleteContext(nlGetCurrent()); }
void sparse3System::solve(double *vs) { int i, j; Node *n; coeffIndexPair *f; for (j=0; j<3; j++) { nlNewContext(); nlSolverParameteri(NL_SOLVER, NL_PERM_SUPERLU_EXT); nlSolverParameteri(NL_NB_VARIABLES, num_variables); nlBegin(NL_SYSTEM); for (i=0; i<num_variables; i++) { nlSetVariable(i, vs[i*3 + j]); if (locks[i]) nlLockVariable(i); } nlBegin(NL_MATRIX); for (i=0; i<num_equations; i++) { nlRowParameterd(NL_RIGHT_HAND_SIDE, known_term[j][i]); nlBegin(NL_ROW); for (n=rows[i].cips.head(); n!=NULL; n=n->next()) { f = (coeffIndexPair *)n->data; nlCoefficient(f->index, f->coeff); } nlEnd(NL_ROW); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); nlSolve(); for (i=0; i<num_variables; i++) vs[i*3 + j] = nlGetVariable(i); nlDeleteContext(nlGetCurrent()); } }
void laplacian_begin_solve(LaplacianSystem *sys, int index) { int a; if (!sys->nlbegun) { nlBegin(NL_SYSTEM); if(index >= 0) { for(a=0; a<sys->totvert; a++) { if(sys->vpinned[a]) { nlSetVariable(0, a, sys->verts[a][index]); nlLockVariable(a); } } } nlBegin(NL_MATRIX); sys->nlbegun = 1; } }
// Solves the system for j'th component of B bool sparseSystem::solve(double *x, int j) { int i; Node *n; coeffIndexPair *f; nlNewContext(); nlSolverParameteri(NL_SOLVER, NL_PERM_SUPERLU_EXT); nlSolverParameteri(NL_NB_VARIABLES, num_variables); nlBegin(NL_SYSTEM); for (i=0; i<num_variables; i++) nlSetVariable(i, x[i]); nlBegin(NL_MATRIX); for (i=0; i<num_equations; i++) { nlRowParameterd(NL_RIGHT_HAND_SIDE, known_term[j][i]); nlBegin(NL_ROW); for (n=rows[i].cips.head(); n!=NULL; n=n->next()) { f = (coeffIndexPair *)n->data; nlCoefficient(f->index, f->coeff); } nlEnd(NL_ROW); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); bool success = (bool)nlSolve(); if (success) for (i=0; i<num_variables; i++) x[i] = nlGetVariable(i); nlDeleteContext(nlGetCurrent()); return success; }
static void laplaciansmoothModifier_do( LaplacianSmoothModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { LaplacianSystem *sys; MDeformVert *dvert = NULL; MDeformVert *dv = NULL; float w, wpaint; int i, iter; int defgrp_index; DM_ensure_tessface(dm); sys = init_laplacian_system(dm->getNumEdges(dm), dm->getNumTessFaces(dm), numVerts); if (!sys) { return; } sys->mfaces = dm->getTessFaceArray(dm); sys->medges = dm->getEdgeArray(dm); sys->vertexCos = vertexCos; sys->min_area = 0.00001f; modifier_get_vgroup(ob, dm, smd->defgrp_name, &dvert, &defgrp_index); sys->vert_centroid[0] = 0.0f; sys->vert_centroid[1] = 0.0f; sys->vert_centroid[2] = 0.0f; memset_laplacian_system(sys, 0); #ifdef OPENNL_THREADING_HACK modifier_opennl_lock(); #endif nlNewContext(); sys->context = nlGetCurrent(); nlSolverParameteri(NL_NB_VARIABLES, numVerts); nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); nlSolverParameteri(NL_NB_ROWS, numVerts); nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3); init_laplacian_matrix(sys); for (iter = 0; iter < smd->repeat; iter++) { nlBegin(NL_SYSTEM); for (i = 0; i < numVerts; i++) { nlSetVariable(0, i, vertexCos[i][0]); nlSetVariable(1, i, vertexCos[i][1]); nlSetVariable(2, i, vertexCos[i][2]); if (iter == 0) { add_v3_v3(sys->vert_centroid, vertexCos[i]); } } if (iter == 0 && numVerts > 0) { mul_v3_fl(sys->vert_centroid, 1.0f / (float)numVerts); } nlBegin(NL_MATRIX); dv = dvert; for (i = 0; i < numVerts; i++) { nlRightHandSideSet(0, i, vertexCos[i][0]); nlRightHandSideSet(1, i, vertexCos[i][1]); nlRightHandSideSet(2, i, vertexCos[i][2]); if (iter == 0) { if (dv) { wpaint = defvert_find_weight(dv, defgrp_index); dv++; } else { wpaint = 1.0f; } if (sys->zerola[i] == 0) { if (smd->flag & MOD_LAPLACIANSMOOTH_NORMALIZED) { w = sys->vweights[i]; sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / w; w = sys->vlengths[i]; sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w; if (sys->numNeEd[i] == sys->numNeFa[i]) { nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda) * wpaint); } else { nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f); } } else { w = sys->vweights[i] * sys->ring_areas[i]; sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / (4.0f * w); w = sys->vlengths[i]; sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w; if (sys->numNeEd[i] == sys->numNeFa[i]) { nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda) * wpaint / (4.0f * sys->ring_areas[i])); } else { nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f); } } } else { nlMatrixAdd(i, i, 1.0f); } } } if (iter == 0) { fill_laplacian_matrix(sys); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_TRUE)) { validate_solution(sys, smd->flag, smd->lambda, smd->lambda_border); } } nlDeleteContext(sys->context); sys->context = NULL; #ifdef OPENNL_THREADING_HACK modifier_opennl_unlock(); #endif delete_laplacian_system(sys); }
static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3]) { int vid, i, j, n, na; n = sys->total_verts; na = sys->total_anchors; #ifdef OPENNL_THREADING_HACK modifier_opennl_lock(); #endif if (!sys->is_matrix_computed) { nlNewContext(); sys->context = nlGetCurrent(); nlSolverParameteri(NL_NB_VARIABLES, n); nlSolverParameteri(NL_SYMMETRIC, NL_FALSE); nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); nlSolverParameteri(NL_NB_ROWS, n + na); nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3); nlBegin(NL_SYSTEM); for (i = 0; i < n; i++) { nlSetVariable(0, i, sys->co[i][0]); nlSetVariable(1, i, sys->co[i][1]); nlSetVariable(2, i, sys->co[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlSetVariable(0, vid, vertexCos[vid][0]); nlSetVariable(1, vid, vertexCos[vid][1]); nlSetVariable(2, vid, vertexCos[vid][2]); } nlBegin(NL_MATRIX); initLaplacianMatrix(sys); computeImplictRotations(sys); for (i = 0; i < n; i++) { nlRightHandSideSet(0, i, sys->delta[i][0]); nlRightHandSideSet(1, i, sys->delta[i][1]); nlRightHandSideSet(2, i, sys->delta[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); nlMatrixAdd(n + i, vid, 1.0f); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_TRUE)) { sys->has_solution = true; for (j = 1; j <= sys->repeat; j++) { nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); rotateDifferentialCoordinates(sys); for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (!nlSolveAdvanced(NULL, NL_FALSE)) { sys->has_solution = false; break; } } if (sys->has_solution) { for (vid = 0; vid < sys->total_verts; vid++) { vertexCos[vid][0] = nlGetVariable(0, vid); vertexCos[vid][1] = nlGetVariable(1, vid); vertexCos[vid][2] = nlGetVariable(2, vid); } } else { sys->has_solution = false; } } else { sys->has_solution = false; } sys->is_matrix_computed = true; } else if (sys->has_solution) { nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); for (i = 0; i < n; i++) { nlRightHandSideSet(0, i, sys->delta[i][0]); nlRightHandSideSet(1, i, sys->delta[i][1]); nlRightHandSideSet(2, i, sys->delta[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); nlMatrixAdd(n + i, vid, 1.0f); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_FALSE)) { sys->has_solution = true; for (j = 1; j <= sys->repeat; j++) { nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); rotateDifferentialCoordinates(sys); for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (!nlSolveAdvanced(NULL, NL_FALSE)) { sys->has_solution = false; break; } } if (sys->has_solution) { for (vid = 0; vid < sys->total_verts; vid++) { vertexCos[vid][0] = nlGetVariable(0, vid); vertexCos[vid][1] = nlGetVariable(1, vid); vertexCos[vid][2] = nlGetVariable(2, vid); } } else { sys->has_solution = false; } } else { sys->has_solution = false; } } #ifdef OPENNL_THREADING_HACK modifier_opennl_unlock(); #endif }