コード例 #1
0
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);
		}
	}
}
コード例 #2
0
void laplacian_add_right_hand_side(LaplacianSystem *sys, int v, float value)
{
	EIG_linear_solver_right_hand_side_add(sys->context, 0, v, value);
}
コード例 #3
0
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]);
		}
	}
}
コード例 #4
0
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;
		}
	}
}
コード例 #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);
}