void MeshPara::get_result() { Vec2f tc1, tc2; tc1[0] = tc2[0] = nlGetVariable(0); tc1[1] = tc2[1] = nlGetVariable(1); auto v_it(mesh_.vertices_begin()); auto v_end(mesh_.vertices_end()); for (; v_it != v_end; v_it++) { int idx = (*v_it).idx(); float u = nlGetVariable(2 * idx); float v = nlGetVariable(2 * idx + 1); mesh_.set_texcoord2D(*v_it, Vec2f(u, v)); if (u < tc1[0])tc1[0] = u; if (u > tc2[0])tc2[0] = u; if (v < tc1[1])tc1[1] = v; if (v > tc2[1])tc2[1] = v; } // Normalize double dx = tc2[0] - tc1[0]; double dy = tc2[1] - tc1[1]; if (dy > dx) dx = dy; for (v_it = mesh_.vertices_begin(); v_it != v_end; v_it++) { Vec2f tc = mesh_.texcoord2D(*v_it); tc[0] = (tc[0] - tc1[0]) / dx; tc[1] = (tc[1] - tc1[1]) / dx; mesh_.set_texcoord2D(*v_it, tc); } }
static void validate_solution(LaplacianSystem *sys, short flag, float lambda, float lambda_border) { int i; float lam; float vini, vend; if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { vini = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces); } for (i = 0; i < sys->numVerts; i++) { if (sys->zerola[i] == 0) { lam = sys->numNeEd[i] == sys->numNeFa[i] ? (lambda >= 0.0f ? 1.0f : -1.0f) : (lambda_border >= 0.0f ? 1.0f : -1.0f); if (flag & MOD_LAPLACIANSMOOTH_X) { sys->vertexCos[i][0] += lam * (nlGetVariable(0, i) - sys->vertexCos[i][0]); } if (flag & MOD_LAPLACIANSMOOTH_Y) { sys->vertexCos[i][1] += lam * (nlGetVariable(1, i) - sys->vertexCos[i][1]); } if (flag & MOD_LAPLACIANSMOOTH_Z) { sys->vertexCos[i][2] += lam * (nlGetVariable(2, i) - sys->vertexCos[i][2]); } } } if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { vend = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces); volume_preservation(sys, vini, vend, flag); } }
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()); } }
// 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; }
float laplacian_system_get_solution(int v) { return nlGetVariable(0, v); }
static void meshdeform_matrix_solve(MeshDeformBind *mdb) { NLContext *context; float vec[3], gridvec[3]; int a, b, x, y, z, totvar; char message[1024]; /* setup variable indices */ mdb->varidx= MEM_callocN(sizeof(int)*mdb->size3, "MeshDeformDSvaridx"); for(a=0, totvar=0; a<mdb->size3; a++) mdb->varidx[a]= (mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR)? -1: totvar++; if(totvar == 0) { MEM_freeN(mdb->varidx); return; } progress_bar(0, "Starting mesh deform solve"); /* setup opennl solver */ nlNewContext(); context= nlGetCurrent(); nlSolverParameteri(NL_NB_VARIABLES, totvar); nlSolverParameteri(NL_NB_ROWS, totvar); nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 1); nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); /* build matrix */ for(z=0; z<mdb->size; z++) for(y=0; y<mdb->size; y++) for(x=0; x<mdb->size; x++) meshdeform_matrix_add_cell(mdb, x, y, z); /* solve for each cage vert */ for(a=0; a<mdb->totcagevert; a++) { if(a != 0) { nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); } /* fill in right hand side and solve */ for(z=0; z<mdb->size; z++) for(y=0; y<mdb->size; y++) for(x=0; x<mdb->size; x++) meshdeform_matrix_add_rhs(mdb, x, y, z, a); nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); #if 0 nlPrintMatrix(); #endif if(nlSolveAdvanced(NULL, NL_TRUE)) { for(z=0; z<mdb->size; z++) for(y=0; y<mdb->size; y++) for(x=0; x<mdb->size; x++) meshdeform_matrix_add_semibound_phi(mdb, x, y, z, a); for(z=0; z<mdb->size; z++) for(y=0; y<mdb->size; y++) for(x=0; x<mdb->size; x++) meshdeform_matrix_add_exterior_phi(mdb, x, y, z, a); for(b=0; b<mdb->size3; b++) { if(mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR) mdb->phi[b]= nlGetVariable(0, mdb->varidx[b]); mdb->totalphi[b] += mdb->phi[b]; } if(mdb->weights) { /* static bind : compute weights for each vertex */ for(b=0; b<mdb->totvert; b++) { if(mdb->inside[b]) { copy_v3_v3(vec, mdb->vertexcos[b]); gridvec[0]= (vec[0] - mdb->min[0] - mdb->halfwidth[0])/mdb->width[0]; gridvec[1]= (vec[1] - mdb->min[1] - mdb->halfwidth[1])/mdb->width[1]; gridvec[2]= (vec[2] - mdb->min[2] - mdb->halfwidth[2])/mdb->width[2]; mdb->weights[b*mdb->totcagevert + a]= meshdeform_interp_w(mdb, gridvec, vec, a); } } } else { MDefBindInfluence *inf; /* dynamic bind */ for(b=0; b<mdb->size3; b++) { if(mdb->phi[b] >= MESHDEFORM_MIN_INFLUENCE) { inf= BLI_memarena_alloc(mdb->memarena, sizeof(*inf)); inf->vertex= a; inf->weight= mdb->phi[b]; inf->next= mdb->dyngrid[b]; mdb->dyngrid[b]= inf; } } } } else { error("Mesh Deform: failed to find solution."); break; } sprintf(message, "Mesh deform solve %d / %d |||", a+1, mdb->totcagevert); progress_bar((float)(a+1)/(float)(mdb->totcagevert), message); } #if 0 /* sanity check */ for(b=0; b<mdb->size3; b++) if(mdb->tag[b] != MESHDEFORM_TAG_EXTERIOR) if(fabs(mdb->totalphi[b] - 1.0f) > 1e-4) printf("totalphi deficiency [%s|%d] %d: %.10f\n", (mdb->tag[b] == MESHDEFORM_TAG_INTERIOR)? "interior": "boundary", mdb->semibound[b], mdb->varidx[b], mdb->totalphi[b]); #endif /* free */ MEM_freeN(mdb->varidx); nlDeleteContext(context); }
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 }
static void rotateDifferentialCoordinates(LaplacianSystem *sys) { float alpha, beta, gamma; float pj[3], ni[3], di[3]; float uij[3], dun[3], e2[3], pi[3], fni[3], vn[4][3]; int i, j, lvin, num_fni, k, fi; int *fidn; for (i = 0; i < sys->total_verts; i++) { copy_v3_v3(pi, sys->co[i]); copy_v3_v3(ni, sys->no[i]); k = sys->unit_verts[i]; copy_v3_v3(pj, sys->co[k]); sub_v3_v3v3(uij, pj, pi); mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni)); sub_v3_v3(uij, dun); normalize_v3(uij); cross_v3_v3v3(e2, ni, uij); copy_v3_v3(di, sys->delta[i]); alpha = dot_v3v3(ni, di); beta = dot_v3v3(uij, di); gamma = dot_v3v3(e2, di); pi[0] = nlGetVariable(0, i); pi[1] = nlGetVariable(1, i); pi[2] = nlGetVariable(2, i); zero_v3(ni); num_fni = 0; num_fni = sys->ringf_map[i].count; for (fi = 0; fi < num_fni; fi++) { const unsigned int *vin; fidn = sys->ringf_map[i].indices; vin = sys->faces[fidn[fi]]; lvin = vin[3] ? 4 : 3; for (j = 0; j < lvin; j++) { vn[j][0] = nlGetVariable(0, vin[j]); vn[j][1] = nlGetVariable(1, vin[j]); vn[j][2] = nlGetVariable(2, vin[j]); if (vin[j] == sys->unit_verts[i]) { copy_v3_v3(pj, vn[j]); } } if (lvin == 3) { normal_tri_v3(fni, vn[0], vn[1], vn[2]); } else if (lvin == 4) { normal_quad_v3(fni, vn[0], vn[1], vn[2], vn[3]); } add_v3_v3(ni, fni); } normalize_v3(ni); sub_v3_v3v3(uij, pj, pi); mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni)); sub_v3_v3(uij, dun); normalize_v3(uij); cross_v3_v3v3(e2, ni, uij); fni[0] = alpha * ni[0] + beta * uij[0] + gamma * e2[0]; fni[1] = alpha * ni[1] + beta * uij[1] + gamma * e2[1]; fni[2] = alpha * ni[2] + beta * uij[2] + gamma * e2[2]; if (len_squared_v3(fni) > FLT_EPSILON) { nlRightHandSideSet(0, i, fni[0]); nlRightHandSideSet(1, i, fni[1]); nlRightHandSideSet(2, i, fni[2]); } else { nlRightHandSideSet(0, i, sys->delta[i][0]); nlRightHandSideSet(1, i, sys->delta[i][1]); nlRightHandSideSet(2, i, sys->delta[i][2]); } } }