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); } } }
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; }