static void meshdeform_matrix_add_rhs(MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z, int cagevert) { MDefBoundIsect *isect; float rhs, weight, totweight; int i, a, acenter; acenter = meshdeform_index(mdb, x, y, z, 0); if (mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR) return; totweight = meshdeform_boundary_total_weight(mdb, x, y, z); for (i = 1; i <= 6; i++) { a = meshdeform_index(mdb, x, y, z, i); if (a == -1) continue; isect = mdb->boundisect[acenter][i - 1]; if (isect) { weight = (1.0f / isect->len) / totweight; rhs = weight * meshdeform_boundary_phi(mdb, isect, cagevert); EIG_linear_solver_right_hand_side_add(context, 0, mdb->varidx[acenter], rhs); } } }
void laplacian_add_right_hand_side(LaplacianSystem *sys, int v, float value) { EIG_linear_solver_right_hand_side_add(sys->context, 0, v, value); }
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[3][3]; int i, j, 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] = EIG_linear_solver_variable_get(sys->context, 0, i); pi[1] = EIG_linear_solver_variable_get(sys->context, 1, i); pi[2] = EIG_linear_solver_variable_get(sys->context, 2, i); zero_v3(ni); 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->tris[fidn[fi]]; for (j = 0; j < 3; j++) { vn[j][0] = EIG_linear_solver_variable_get(sys->context, 0, vin[j]); vn[j][1] = EIG_linear_solver_variable_get(sys->context, 1, vin[j]); vn[j][2] = EIG_linear_solver_variable_get(sys->context, 2, vin[j]); if (vin[j] == sys->unit_verts[i]) { copy_v3_v3(pj, vn[j]); } } normal_tri_v3(fni, UNPACK3(vn)); 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) { EIG_linear_solver_right_hand_side_add(sys->context, 0, i, fni[0]); EIG_linear_solver_right_hand_side_add(sys->context, 1, i, fni[1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, i, fni[2]); } else { EIG_linear_solver_right_hand_side_add(sys->context, 0, i, sys->delta[i][0]); EIG_linear_solver_right_hand_side_add(sys->context, 1, i, sys->delta[i][1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, i, sys->delta[i][2]); } } }
static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3]) { int vid, i, j, n, na; n = sys->total_verts; na = sys->total_anchors; if (!sys->is_matrix_computed) { sys->context = EIG_linear_least_squares_solver_new(n + na, n, 3); for (i = 0; i < n; i++) { EIG_linear_solver_variable_set(sys->context, 0, i, sys->co[i][0]); EIG_linear_solver_variable_set(sys->context, 1, i, sys->co[i][1]); EIG_linear_solver_variable_set(sys->context, 2, i, sys->co[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; EIG_linear_solver_variable_set(sys->context, 0, vid, vertexCos[vid][0]); EIG_linear_solver_variable_set(sys->context, 1, vid, vertexCos[vid][1]); EIG_linear_solver_variable_set(sys->context, 2, vid, vertexCos[vid][2]); } initLaplacianMatrix(sys); computeImplictRotations(sys); for (i = 0; i < n; i++) { EIG_linear_solver_right_hand_side_add(sys->context, 0, i, sys->delta[i][0]); EIG_linear_solver_right_hand_side_add(sys->context, 1, i, sys->delta[i][1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, i, sys->delta[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]); EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]); EIG_linear_solver_matrix_add(sys->context, n + i, vid, 1.0f); } if (EIG_linear_solver_solve(sys->context)) { sys->has_solution = true; for (j = 1; j <= sys->repeat; j++) { rotateDifferentialCoordinates(sys); for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]); EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]); } if (!EIG_linear_solver_solve(sys->context)) { sys->has_solution = false; break; } } if (sys->has_solution) { for (vid = 0; vid < sys->total_verts; vid++) { vertexCos[vid][0] = EIG_linear_solver_variable_get(sys->context, 0, vid); vertexCos[vid][1] = EIG_linear_solver_variable_get(sys->context, 1, vid); vertexCos[vid][2] = EIG_linear_solver_variable_get(sys->context, 2, vid); } } else { sys->has_solution = false; } } else { sys->has_solution = false; } sys->is_matrix_computed = true; } else if (sys->has_solution) { for (i = 0; i < n; i++) { EIG_linear_solver_right_hand_side_add(sys->context, 0, i, sys->delta[i][0]); EIG_linear_solver_right_hand_side_add(sys->context, 1, i, sys->delta[i][1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, i, sys->delta[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]); EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]); EIG_linear_solver_matrix_add(sys->context, n + i, vid, 1.0f); } if (EIG_linear_solver_solve(sys->context)) { sys->has_solution = true; for (j = 1; j <= sys->repeat; j++) { rotateDifferentialCoordinates(sys); for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; EIG_linear_solver_right_hand_side_add(sys->context, 0, n + i, vertexCos[vid][0]); EIG_linear_solver_right_hand_side_add(sys->context, 1, n + i, vertexCos[vid][1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, n + i, vertexCos[vid][2]); } if (!EIG_linear_solver_solve(sys->context)) { sys->has_solution = false; break; } } if (sys->has_solution) { for (vid = 0; vid < sys->total_verts; vid++) { vertexCos[vid][0] = EIG_linear_solver_variable_get(sys->context, 0, vid); vertexCos[vid][1] = EIG_linear_solver_variable_get(sys->context, 1, vid); vertexCos[vid][2] = EIG_linear_solver_variable_get(sys->context, 2, vid); } } else { sys->has_solution = false; } } else { sys->has_solution = false; } } }
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; sys = init_laplacian_system(dm->getNumEdges(dm), dm->getNumPolys(dm), dm->getNumLoops(dm), numVerts); if (!sys) { return; } sys->mpoly = dm->getPolyArray(dm); sys->mloop = dm->getLoopArray(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); sys->context = EIG_linear_least_squares_solver_new(numVerts, numVerts, 3); init_laplacian_matrix(sys); for (iter = 0; iter < smd->repeat; iter++) { for (i = 0; i < numVerts; i++) { EIG_linear_solver_variable_set(sys->context, 0, i, vertexCos[i][0]); EIG_linear_solver_variable_set(sys->context, 1, i, vertexCos[i][1]); EIG_linear_solver_variable_set(sys->context, 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); } dv = dvert; for (i = 0; i < numVerts; i++) { EIG_linear_solver_right_hand_side_add(sys->context, 0, i, vertexCos[i][0]); EIG_linear_solver_right_hand_side_add(sys->context, 1, i, vertexCos[i][1]); EIG_linear_solver_right_hand_side_add(sys->context, 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]) { EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + fabsf(smd->lambda) * wpaint); } else { EIG_linear_solver_matrix_add(sys->context, 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]) { EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + fabsf(smd->lambda) * wpaint / (4.0f * sys->ring_areas[i])); } else { EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f); } } } else { EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f); } } } if (iter == 0) { fill_laplacian_matrix(sys); } if (EIG_linear_solver_solve(sys->context)) { validate_solution(sys, smd->flag, smd->lambda, smd->lambda_border); } } EIG_linear_solver_delete(sys->context); sys->context = NULL; delete_laplacian_system(sys); }