int laplacian_system_solve(LaplacianSystem *sys) { nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); sys->nlbegun = 0; //nlPrintMatrix(); return nlSolveAdvanced(NULL, NL_TRUE); }
NLboolean nlSolve() { NLboolean result = NL_TRUE; __nlCheckState(__NL_STATE_SYSTEM_CONSTRUCTED); result = __nlSolve_SUPERLU(NL_TRUE); __nlVectorToVariables(); __nlTransition(__NL_STATE_SYSTEM_CONSTRUCTED, __NL_STATE_SOLVED); return result; return nlSolveAdvanced(NULL, NL_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; 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 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 }
NLboolean nlSolve() { return nlSolveAdvanced(NULL, NL_FALSE); }