Subversion Repositories gelsvn

Rev

Rev 507 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "build_bbtree.h"

#include <HMesh/Manifold.h>

using namespace CGLA;
using namespace std;
using namespace HMesh;

namespace
{
    const float EDGE_MIN_SQ_LENGTH = CGLA::MINUTE;

    inline bool degenerate_edge(const Manifold& m, HalfEdgeID h)
    {
                HalfEdgeWalker w = m.halfedgewalker(h);
        if(sqr_length(m.pos(w.vertex()) - m.pos(w.opp().vertex())) < 1e-8)
            return true;
        return false;
    }

}

namespace Geometry
{

    template<class BBTree>
    void build_tree_robust(Manifold& m, BBTree& tree)
    {
#ifdef COMPUTE_SIGN
        vector<Vec3f> face_normals(m.no_faces());

        int i=0;
        for(FaceHandle fi=m.fhandles_begin(); fi != m.fhandles_end();++fi,++i)
        {
            face_normals[i] = normal(fi);
            fi.get().touched = i;
        }

        for(HalfEdgeHandle ei = m.hhandles_begin(); ei != m.hhandles_end(); ++ei)
            ei.get().touched = -1;

        i=0;
        vector<Vec3f> edge_normals(0);
        for(HalfEdgeHandle ei = m.hhandles_begin(); ei != m.hhandles_end(); ++ei){
            if(ei.get().touched == -1){
                Vec3f n_a = face_normals[ei.face().get().touched];
                Vec3f n_b = n_a;
                if(ei.opp().face() != NULL_FHANDLE)
                    n_b = face_normals[ei.opp().face().get().touched];

                edge_normals.push_back(normalize(n_a+n_b));
                ei.get().touched = i;
                ei.opp().get().touched = i;
                ++i;
            }
        }

        for(VertexHandle vi = m.vhandles_begin(); vi != m.vhandles_end(); ++vi)
            vi.get().touched = -1;

        int vertex_cluster_number=0;
        vector<Vec3f> vertex_normals(m.no_vertices());
        for(VertexHandle vi = m.vhandles_begin(); vi != m.vhandles_end(); ++vi){
            if(vi.get().touched == -1){
                int cluster_size = 0;
                Vec3f nsum(0);
                vector<VertexHandle> cluster(1,vi);
                while(!cluster.empty()){
                    cluster_size ++;
                    VertexHandle vert_handle = cluster.back();
                    cluster.pop_back();
                    vert_handle.get().touched = vertex_cluster_number;

                    vector<VertexHandle> nbrs;
                    VertexCirculator vc(vert_handle);
                    for(;!vc.end();++vc)
                        nbrs.push_back(vc.vertex());

                    IndexType N = vc.no_steps();
                    Vec3f p = vert_handle.get().pos;
                    for(IndexType j = 0; j < N; ++j){
                        Vec3f va = nbrs[(j+1)%N].get().pos - p;
                        Vec3f vb = nbrs[j].get().pos - p;
                        if(sqr_length(vb) > EDGE_MIN_SQ_LENGTH){
                            if(sqr_length(va) > EDGE_MIN_SQ_LENGTH){
                                va.normalize();
                                vb.normalize();
                                float a = acos(dot(va,vb));
                                nsum += a*normalize(cross(va,vb));
                            }
                        }
                        else{
                            if(nbrs[j].get().touched != vertex_cluster_number){
                                assert(nbrs[j].get().touched == -1);
                                cluster.push_back(nbrs[j]);
                            }
                        }
                    }
                }
                vertex_normals[vertex_cluster_number] = normalize(nsum);
                ++vertex_cluster_number;
                if(cluster_size > 1) cout << "Cluster Size " 
                    << cluster_size << " normal " 
                    << normalize(nsum) << endl;
            }
        }

        vector<Triangle> triangle_vec;

        i=0;
        for(FaceHandle fi = m.fhandles_begin(); fi != m.fhandles_end();++fi,++i)
        {
            Vec3f fn = face_normals[fi.get().touched];

            FaceCirculator fc(fi);

            Vec3f v0,v1,v2;
            Vec3f vn0,vn1,vn2;
            Vec3f en0,en1,en2;

            v0  = fc.vertex().get().pos;
            vn0 = vertex_normals[fc.vertex().get().touched];
            en0 = edge_normals[fc.next_halfedge().get().touched];

            ++fc;

            v1  = fc.vertex().get().pos;
            vn1 = vertex_normals[fc.vertex().get().touched];
            en1 = edge_normals[fc.next_halfedge().get().touched];

            ++fc;

            v2  = fc.vertex().get().pos;
            vn2 = vertex_normals[fc.vertex().get().touched];
            en2 = edge_normals[fc.next_halfedge().get().touched];

            if(sqr_length(v0-v1)>EDGE_MIN_SQ_LENGTH &&
                sqr_length(v1-v2)>EDGE_MIN_SQ_LENGTH &&
                sqr_length(v2-v0)>EDGE_MIN_SQ_LENGTH)
                triangle_vec.push_back(Triangle(v0,v1,v2,vn0,vn1,vn2,en0,en1,en2));
            else
                cout << "Killing degenerate triangle" << endl;
        }
#else
        vector<Triangle> triangle_vec;
        int i=0;
        for(FaceIter fi=m.fhandles_begin(); fi != m.fhandles_end();++fi,++i)
        {
            FaceCirculator fc(fi);
            Vec3f v0,v1,v2;
            Vec3f dmy(0);
            v0  = fc.get_vertex()->get_pos();
            ++fc;
            v1  = fc.get_vertex()->get_pos();
            ++fc;
            v2  = fc.get_vertex()->get_pos();
            if(sqr_length(v0-v1)>EDGE_MIN_SQ_LENGTH &&
                sqr_length(v1-v2)>EDGE_MIN_SQ_LENGTH &&
                sqr_length(v2-v0)>EDGE_MIN_SQ_LENGTH)
                triangle_vec.push_back(Triangle(v0,v1,v2,dmy,dmy,dmy,dmy,dmy,dmy));
        }
#endif

        tree.build(triangle_vec);
    }

    void build_OBBTree(HMesh::Manifold& m, OBBTree& tree)
    {
        build_tree_robust<OBBTree>(m, tree);
    }

    void build_AABBTree(HMesh::Manifold& m, AABBTree& tree)
    {
        build_tree_robust<AABBTree>(m, tree);
    }

}