コード例 #1
0
// remove tets with corners where phi=0 but are outside the volume
static void
remove_exterior_tets(TetMesh& mesh,
                     const std::vector<float> &vphi,
                     const SDF& sdf)
{
    for (size_t t=0; t<mesh.tSize(); ) {
        int i, j, k, l; assign(mesh.T(t), i, j, k, l);
        assert(vphi[i]<=0 && vphi[j]<=0 && vphi[k]<=0 && vphi[l]<=0);
        if (vphi[i]==0 && vphi[j]==0 && vphi[k]==0 && vphi[l]==0
            && sdf((mesh.V(i)+mesh.V(j)+mesh.V(k)+mesh.V(l))/4)>0) {
            mesh.T(t) = mesh.tets().back();
            mesh.tets().pop_back();
        } else {
            ++t;
        }
    }
}
コード例 #2
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; 
    }
}
コード例 #3
0
// Find all tets with vertices where a corner has vphi>0 and trim them back.
static void
trim_spikes(TetMesh& mesh,
            std::vector<float> &vphi)
{
    // keep track of edges we cut - store the index of the new vertex
    std::map<Vec2i,int> cut_map;
    // we have a separate list for the results of trimming tets
    std::vector<Vec4i> new_tets;
    // go through the existing tets to see what we have to trim
    for (int t=0; t<(int)mesh.tSize(); ++t) {
        int p, q, r, s; assign(mesh.T(t), p, q, r, s);
        if (vphi[p]<=0 && vphi[q]<=0 && vphi[r]<=0 && vphi[s]<=0)
            continue; // this tet doesn't stick out

        // We have a plethora of cases to deal with. Let's sort the vertices
        // by their phi values and break ties with index, remembering if we
        // have switched orientation or not, to cut down on the number of
        // cases to handle. Use a sorting network to do the job.
        bool flipped=false;
        if (vphi[p]<vphi[q] || (vphi[p]==vphi[q] && p<q)) {
            std::swap(p, q);
            flipped = !flipped;
        }
        if (vphi[r]<vphi[s] || (vphi[r]==vphi[s] && r<s)) {
            std::swap(r, s);
            flipped = !flipped;
        }
        if (vphi[p]<vphi[r] || (vphi[p]==vphi[r] && p<r)) {
            std::swap(p, r);
            flipped = !flipped;
        }
        if (vphi[q]<vphi[s] || (vphi[q]==vphi[s] && q<s)) {
            std::swap(q, s);
            flipped = !flipped;
        }
        if (vphi[q]<vphi[r] || (vphi[q]==vphi[r] && q<r)) {
            std::swap(q, r);
            flipped = !flipped;
        }

        // sanity checks
        assert(vphi[p]>=vphi[q] && vphi[q]>=vphi[r] && vphi[r]>=vphi[s]); //sort
        assert(vphi[p]>0); // we already skipped interior tets
        assert(vphi[s]<=0); // we never generate tets with all positive phi

        // now do the actual trimming
        if (vphi[s]==0) { // +++0 entirely outside
            mesh.T(t)=mesh.tets().back(); // overwrite with last tet
            mesh.tets().pop_back(); // get rid of the last one
            --t; // decrement to cancel the next for-loop increment

        } else if (vphi[r]>0) { // +++- just one vertex inside, three out
            // replace this tet with one clipped back to the isosurface
            int ps = cut_edge(p, s, mesh, vphi, cut_map),
                qs = cut_edge(q, s, mesh, vphi, cut_map),
                rs = cut_edge(r, s, mesh, vphi, cut_map);
            if (flipped)
                mesh.T(t) = Vec4i(qs, ps, rs, s);
            else
                mesh.T(t) = Vec4i(ps, qs, rs, s);

        } else if(vphi[q]<0) { // +--- just one vertex outside, three in
            // Have to tetrahedralize the resulting triangular prism.
            // Note that the quad faces have to be split in a way that will
            // be consistent with face-adjacent tets: our sort of pqrs with
            // consistently broken ties makes this work. We cut the quad to the
            // deepest vertex (phi as negative as possible).
            int pq = cut_edge(p, q, mesh, vphi, cut_map),
                pr = cut_edge(p, r, mesh, vphi, cut_map),
                ps = cut_edge(p, s, mesh, vphi, cut_map);
            if (flipped) {
                mesh.T(t) = Vec4i(q, pq, r, s);
                new_tets.push_back(Vec4i(r, pq, pr, s));
                new_tets.push_back(Vec4i(s, pq, pr, ps));
            } else {
                mesh.T(t)=Vec4i(pq, q, r, s);
                new_tets.push_back(Vec4i(pq, r, pr, s));
                new_tets.push_back(Vec4i(pq, s, pr, ps));
            }

        } else if (vphi[q]>0 && vphi[r]<0) { // ++-- two vertices out, two in
            int pr = cut_edge(p, r, mesh, vphi, cut_map),
                ps = cut_edge(p, s, mesh, vphi, cut_map),
                qr = cut_edge(q, r, mesh, vphi, cut_map),
                qs = cut_edge(q, s, mesh, vphi, cut_map);
            if (flipped) {
                mesh.T(t) = Vec4i(qr, pr, r, s);
                new_tets.push_back(Vec4i(qs, pr, qr, s));
                new_tets.push_back(Vec4i(ps, pr, qs, s));
            } else {
                mesh.T(t) = Vec4i(pr, qr, r, s);
                new_tets.push_back(Vec4i(pr, qs, qr, s));
                new_tets.push_back(Vec4i(pr, ps, qs, s));
            }

        } else if (vphi[q]==0 && vphi[r]==0) { // +00- 1 out, 1 in, 2 surface
            int ps = cut_edge(p, s, mesh, vphi, cut_map);
            if (flipped)
                mesh.T(t) = Vec4i(q, ps, r, s);
            else
                mesh.T(t) = Vec4i(ps, q, r, s);

        } else if (vphi[q]==0) { // +0-- 1 out, 2 in, 1 surface
            int pr = cut_edge(p, r, mesh, vphi, cut_map),
                ps = cut_edge(p, s, mesh, vphi, cut_map);
            if (flipped) {
                mesh.T(t) = Vec4i(q, pr, r, s);
                new_tets.push_back(Vec4i(q, ps, pr, s));
            } else {
                mesh.T(t) = Vec4i(pr, q, r, s);
                new_tets.push_back(Vec4i(ps, q, pr, s));
            }

        } else { // ++0- two out, one in, one surface
            int ps = cut_edge(p, s, mesh, vphi, cut_map),
                qs = cut_edge(q, s, mesh, vphi, cut_map);
            if (flipped)
                mesh.T(t) = Vec4i(qs, ps, r, s);
            else
                mesh.T(t) = Vec4i(ps, qs, r, s);
        }
    }
    // append all the remaining new tets
    for (size_t t=0; t<new_tets.size(); ++t)
        mesh.tets().push_back(new_tets[t]);
}