예제 #1
0
// Fix some edge crossings by warping vertices if it's admissible
static void
warp_vertices(const float threshold,
              TetMesh& mesh,
              std::vector<float>& vphi)
{
    assert(threshold>=0 && threshold<=0.5);
    std::vector<float> warp(mesh.vSize(), FLT_MAX);
    std::vector<int> warp_nbr(mesh.vSize(), -1);
    std::vector<Vec3f> d(mesh.vSize(), Vec3f(0,0,0));
    // it's wasteful to iterate through tets just to look at edges; oh well
    for (size_t t=0; t<mesh.tSize(); ++t) {
        for (int u=0; u<3; ++u) {
            int i = mesh.T(t)[u];
            for (int v=u+1; v<4; ++v) {
                int j = mesh.T(t)[v];
                if ((vphi[i]<0 && vphi[j]>0) || (vphi[i]>0 && vphi[j]<0)) {
                    float alpha = vphi[i]/(vphi[i]-vphi[j]);
                    if (alpha < threshold) { // warp i?
                        float d2 = alpha*dist2(mesh.V(i), mesh.V(j));
                        if (d2 < warp[i]) {
                            warp[i] = d2;
                            warp_nbr[i] = j;
                            d[i] = alpha*(mesh.V(j)-mesh.V(i));
                        }
                    } else if (alpha > 1-threshold) { // warp j?
                        float d2 = (1-alpha)*dist2(mesh.V(i), mesh.V(j));
                        if (d2 < warp[j]) {
                            warp[j] = d2;
                            warp_nbr[j] = i;
                            d[j] = (1-alpha)*(mesh.V(i)-mesh.V(j));
                        }
                    }
                }
            }
        }
    }
    // do the warps (also wasteful to loop over all vertices; oh well)
    for (size_t i=0; i<mesh.vSize(); ++i) if(warp_nbr[i]>=0) {
        mesh.V(i) += d[i];
        vphi[i] = 0; 
    }
}
예제 #2
0
// cut a chunk of the lattice out to roughly match the shape
static void
cut_lattice(const SDF& sdf,
            TetMesh& mesh,
            std::vector<float>& vphi) // phi evaluated at vertices
{
    std::map<Vec3i,int> lattice_map;
    // loop over tiles that overlap bounding box
    int i, j, k;
    for (k=0; k<sdf.phi.nk; k+=4) for (j=0; j<sdf.phi.nj; j+=4) 
      for (i=0; i<sdf.phi.ni; i+=4) {
        for (int t=0; t<num_lattice_tets; ++t) {
            // check this tet is entirely inside the grid & has a negative phi
            bool good_tet = true;
            bool negative_phi = false;
            for (int u=0; u<4; ++u) {
                int a = lattice_node[lattice_tet[t][u]][0]+i;
                if (a >= sdf.phi.ni) { good_tet=false; break; }
                int b = lattice_node[lattice_tet[t][u]][1]+j;
                if (b >= sdf.phi.nj) { good_tet=false; break; }
                int c = lattice_node[lattice_tet[t][u]][2]+k;
                if (c >= sdf.phi.nk) { good_tet=false; break; }
                if (sdf.phi(a,b,c) < 0)
                    negative_phi = true;
            }
            if (good_tet && negative_phi) {
                // add vertices if they don't exist yet, find actual tet to add
                Vec4i actual_tet(-1,-1,-1,-1);
                for (int u=0; u<4; ++u) {
                    Vec3i vertex=lattice_node[lattice_tet[t][u]]+Vec3i(i,j,k);
                    std::map<Vec3i,int>::iterator p = lattice_map.find(vertex);
                    if (p == lattice_map.end()) {
                        actual_tet[u] = mesh.vSize();
                        lattice_map[vertex] = actual_tet[u];
                        mesh.verts().push_back(sdf.origin+sdf.dx*Vec3f(vertex));
                        vphi.push_back(sdf.phi(vertex[0],vertex[1],vertex[2]));
                    } else {
                        actual_tet[u]=p->second;
                    }
                }
                mesh.tets().push_back(actual_tet);
            }
        }
    }
}
예제 #3
0
// assuming vphi[i] and vphi[j] have different signs, find or create a new
// vertex on the edge between them where phi interpolates to zero.
static int
cut_edge(int i, int j,
         TetMesh& mesh,
         std::vector<float> &vphi,
         std::map<Vec2i,int> &cut_map)
{
    assert((vphi[i]<0 && vphi[j]>0) || (vphi[i]>0 && vphi[j]<0));
    Vec2i edge(min(i,j), max(i,j));
    std::map<Vec2i,int>::iterator p = cut_map.find(edge);
    if (p == cut_map.end()) { // this edge hasn't been cut yet?
        int v = (int)mesh.vSize();
        float alpha = vphi[i]/(vphi[i]-vphi[j]);
        mesh.verts().push_back((1-alpha)*mesh.V(i) + alpha*mesh.V(j));
        vphi.push_back(0);
        cut_map[edge] = v;
        return v;
    } else { // already done this edge
        return p->second;
    }
}