static void laplacian_system_delete(LaplacianSystem *sys)
{
	if (sys->verts) MEM_freeN(sys->verts);
	if (sys->varea) MEM_freeN(sys->varea);
	if (sys->vpinned) MEM_freeN(sys->vpinned);
	if (sys->faces) MEM_freeN(sys->faces);
	if (sys->fweights) MEM_freeN(sys->fweights);

	EIG_linear_solver_delete(sys->context);
	MEM_freeN(sys);
}
static void deleteLaplacianSystem(LaplacianSystem *sys)
{
	MEM_SAFE_FREE(sys->co);
	MEM_SAFE_FREE(sys->no);
	MEM_SAFE_FREE(sys->delta);
	MEM_SAFE_FREE(sys->tris);
	MEM_SAFE_FREE(sys->index_anchors);
	MEM_SAFE_FREE(sys->unit_verts);
	MEM_SAFE_FREE(sys->ringf_indices);
	MEM_SAFE_FREE(sys->ringv_indices);
	MEM_SAFE_FREE(sys->ringf_map);
	MEM_SAFE_FREE(sys->ringv_map);

	if (sys->context) {
		EIG_linear_solver_delete(sys->context);
	}
	MEM_SAFE_FREE(sys);
}
Example #3
0
static void delete_laplacian_system(LaplacianSystem *sys)
{
	MEM_SAFE_FREE(sys->eweights);
	MEM_SAFE_FREE(sys->fweights);
	MEM_SAFE_FREE(sys->numNeEd);
	MEM_SAFE_FREE(sys->numNeFa);
	MEM_SAFE_FREE(sys->ring_areas);
	MEM_SAFE_FREE(sys->vlengths);
	MEM_SAFE_FREE(sys->vweights);
	MEM_SAFE_FREE(sys->zerola);

	if (sys->context) {
		EIG_linear_solver_delete(sys->context);
	}
	sys->vertexCos = NULL;
	sys->mpoly = NULL;
	sys->mloop = NULL;
	sys->medges = NULL;
	MEM_freeN(sys);
}
static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind *mdb)
{
	LinearSolver *context;
	float vec[3], gridvec[3];
	int a, b, x, y, z, totvar;
	char message[256];

	/* 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 linear solver */
	context = EIG_linear_solver_new(totvar, totvar, 1);

	/* 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, context, x, y, z);

	/* solve for each cage vert */
	for (a = 0; a < mdb->totcagevert; a++) {
		/* 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, context, x, y, z, a);

		if (EIG_linear_solver_solve(context)) {
			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] = EIG_linear_solver_variable_get(context, 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 {
			modifier_setError(&mmd->modifier, "Failed to find bind solution (increase precision?)");
			error("Mesh Deform: failed to find bind solution.");
			break;
		}

		BLI_snprintf(message, sizeof(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 (fabsf(mdb->totalphi[b] - 1.0f) > 1e-4f)
				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);

	EIG_linear_solver_delete(context);
}
Example #5
0
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);
}