static LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq) { LaplacianSystem *sys; sys = MEM_callocN(sizeof(LaplacianSystem), "LaplacianSystem"); sys->verts = MEM_callocN(sizeof(float *) * totvert, "LaplacianSystemVerts"); sys->vpinned = MEM_callocN(sizeof(char) * totvert, "LaplacianSystemVpinned"); sys->faces = MEM_callocN(sizeof(int) * 3 * totface, "LaplacianSystemFaces"); sys->totvert = 0; sys->totface = 0; sys->areaweights = 1; sys->storeweights = 0; /* create linear solver */ if (lsq) sys->context = EIG_linear_least_squares_solver_new(0, totvert, 1); else sys->context = EIG_linear_solver_new(0, totvert, 1); return sys; }
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); }