static void meshdeform_matrix_add_cell(MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z)
{
	MDefBoundIsect *isect;
	float weight, totweight;
	int i, a, acenter;

	acenter = meshdeform_index(mdb, x, y, z, 0);
	if (mdb->tag[acenter] == MESHDEFORM_TAG_EXTERIOR)
		return;

	EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[acenter], 1.0f);
	
	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 || mdb->tag[a] == MESHDEFORM_TAG_EXTERIOR)
			continue;

		isect = mdb->boundisect[acenter][i - 1];
		if (!isect) {
			weight = (1.0f / mdb->width[0]) / totweight;
			EIG_linear_solver_matrix_add(context, mdb->varidx[acenter], mdb->varidx[a], -weight);
		}
	}
}
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);
		}
	}
}
Esempio n. 3
0
static void meshdeform_bind_floodfill(MeshDeformBind *mdb)
{
	int *stack, *tag= mdb->tag;
	int a, b, i, xyz[3], stacksize, size= mdb->size;

	stack= MEM_callocN(sizeof(int)*mdb->size3, "MeshDeformBindStack");

	/* we know lower left corner is EXTERIOR because of padding */
	tag[0]= MESHDEFORM_TAG_EXTERIOR;
	stack[0]= 0;
	stacksize= 1;

	/* floodfill exterior tag */
	while(stacksize > 0) {
		a= stack[--stacksize];

		xyz[2]= a/(size*size);
		xyz[1]= (a - xyz[2]*size*size)/size;
		xyz[0]= a - xyz[1]*size - xyz[2]*size*size;

		for(i=1; i<=6; i++) {
			b= meshdeform_index(mdb, xyz[0], xyz[1], xyz[2], i);

			if(b != -1) {
				if(tag[b] == MESHDEFORM_TAG_UNTYPED ||
				   (tag[b] == MESHDEFORM_TAG_BOUNDARY && !mdb->boundisect[a][i-1])) {
					tag[b]= MESHDEFORM_TAG_EXTERIOR;
					stack[stacksize++]= b;
				}
			}
		}
	}

	/* other cells are interior */
	for(a=0; a<size*size*size; a++)
		if(tag[a]==MESHDEFORM_TAG_UNTYPED)
			tag[a]= MESHDEFORM_TAG_INTERIOR;

#if 0
	{
		int tb, ti, te, ts;
		tb= ti= te= ts= 0;
		for(a=0; a<size*size*size; a++)
			if(tag[a]==MESHDEFORM_TAG_BOUNDARY)
				tb++;
			else if(tag[a]==MESHDEFORM_TAG_INTERIOR)
				ti++;
			else if(tag[a]==MESHDEFORM_TAG_EXTERIOR) {
				te++;

				if(mdb->semibound[a])
					ts++;
			}
		
		printf("interior %d exterior %d boundary %d semi-boundary %d\n", ti, te, tb, ts);
	}
#endif

	MEM_freeN(stack);
}
static void meshdeform_check_semibound(MeshDeformBind *mdb, int x, int y, int z)
{
	int i, a;

	a = meshdeform_index(mdb, x, y, z, 0);
	if (mdb->tag[a] != MESHDEFORM_TAG_EXTERIOR)
		return;

	for (i = 1; i <= 6; i++)
		if (mdb->boundisect[a][i - 1])
			mdb->semibound[a] = 1;
}
static void meshdeform_matrix_add_exterior_phi(MeshDeformBind *mdb, int x, int y, int z, int UNUSED(cagevert))
{
	float phi, totweight;
	int i, a, acenter;

	acenter = meshdeform_index(mdb, x, y, z, 0);
	if (mdb->tag[acenter] != MESHDEFORM_TAG_EXTERIOR || mdb->semibound[acenter])
		return;

	phi = 0.0f;
	totweight = 0.0f;
	for (i = 1; i <= 6; i++) {
		a = meshdeform_index(mdb, x, y, z, i);

		if (a != -1 && mdb->semibound[a]) {
			phi += mdb->phi[a];
			totweight += 1.0f;
		}
	}

	if (totweight != 0.0f)
		mdb->phi[acenter] = phi / totweight;
}
static void meshdeform_add_intersections(MeshDeformBind *mdb, int x, int y, int z)
{
	MDefBoundIsect *isect;
	float center[3], ncenter[3];
	int i, a;

	a = meshdeform_index(mdb, x, y, z, 0);
	meshdeform_cell_center(mdb, x, y, z, 0, center);

	/* check each outgoing edge for intersection */
	for (i = 1; i <= 6; i++) {
		if (meshdeform_index(mdb, x, y, z, i) == -1)
			continue;

		meshdeform_cell_center(mdb, x, y, z, i, ncenter);

		isect = meshdeform_ray_tree_intersect(mdb, center, ncenter);
		if (isect) {
			mdb->boundisect[a][i - 1] = isect;
			mdb->tag[a] = MESHDEFORM_TAG_BOUNDARY;
		}
	}
}
static float meshdeform_boundary_total_weight(MeshDeformBind *mdb, int x, int y, int z)
{
	float weight, totweight = 0.0f;
	int i, a;

	a = meshdeform_index(mdb, x, y, z, 0);

	/* count weight for neighbor cells */
	for (i = 1; i <= 6; i++) {
		if (meshdeform_index(mdb, x, y, z, i) == -1)
			continue;

		if (mdb->boundisect[a][i - 1])
			weight = 1.0f / mdb->boundisect[a][i - 1]->len;
		else if (!mdb->semibound[a])
			weight = 1.0f / mdb->width[0];
		else
			weight = 0.0f;

		totweight += weight;
	}

	return totweight;
}
static void meshdeform_matrix_add_semibound_phi(MeshDeformBind *mdb, int x, int y, int z, int cagevert)
{
	MDefBoundIsect *isect;
	float rhs, weight, totweight;
	int i, a;

	a = meshdeform_index(mdb, x, y, z, 0);
	if (!mdb->semibound[a])
		return;
	
	mdb->phi[a] = 0.0f;

	totweight = meshdeform_boundary_total_weight(mdb, x, y, z);
	for (i = 1; i <= 6; i++) {
		isect = mdb->boundisect[a][i - 1];

		if (isect) {
			weight = (1.0f / isect->len) / totweight;
			rhs = weight * meshdeform_boundary_phi(mdb, isect, cagevert);
			mdb->phi[a] += rhs;
		}
	}
}
static float meshdeform_interp_w(MeshDeformBind *mdb, float *gridvec, float *UNUSED(vec), int UNUSED(cagevert))
{
	float dvec[3], ivec[3], wx, wy, wz, result = 0.0f;
	float weight, totweight = 0.0f;
	int i, a, x, y, z;

	for (i = 0; i < 3; i++) {
		ivec[i] = (int)gridvec[i];
		dvec[i] = gridvec[i] - ivec[i];
	}

	for (i = 0; i < 8; i++) {
		if (i & 1) { x = ivec[0] + 1; wx = dvec[0]; }
		else       { x = ivec[0];     wx = 1.0f - dvec[0]; }

		if (i & 2) { y = ivec[1] + 1; wy = dvec[1]; }
		else       { y = ivec[1];     wy = 1.0f - dvec[1]; }

		if (i & 4) { z = ivec[2] + 1; wz = dvec[2]; }
		else       { z = ivec[2];     wz = 1.0f - dvec[2]; }

		CLAMP(x, 0, mdb->size - 1);
		CLAMP(y, 0, mdb->size - 1);
		CLAMP(z, 0, mdb->size - 1);

		a = meshdeform_index(mdb, x, y, z, 0);
		weight = wx * wy * wz;
		result += weight * mdb->phi[a];
		totweight += weight;
	}

	if (totweight > 0.0f)
		result /= totweight;

	return result;
}