예제 #1
0
파일: gui.cpp 프로젝트: ipa-nhg/kukadu
int Upper_Leaves_CB( Togl *togl, int argc, const char *argv[] )
{
    int i;

    if( uleaves ) {
        // Include all leaves above the current level
        for( i = 0; i < num_leaves; i++ ) {
            if( leaves[i]->Level() < level ) {
                which_pieces.Add_Grow( leaves[i], 10 );
            }
        }
    } else {
        // Remove all leaves above the current level
        SWIFT_Array<SWIFT_BV*> new_which_pieces;

        new_which_pieces.Create( which_pieces.Length() );
        new_which_pieces.Set_Length( 0 );
        for( i = 0; i < which_pieces.Length(); i++ ) {
            if( !which_pieces[i]->Is_Leaf() ||
                which_pieces[i]->Level() == level
            ) {
                // Keep this piece
                new_which_pieces.Add( which_pieces[i] );
            }
        }

        which_pieces.Destroy();
        which_pieces = new_which_pieces;
        new_which_pieces.Nullify();
    }

    Togl_PostRedisplay( t );
    return TCL_OK;
}
예제 #2
0
void Create_One_Piece( SWIFT_Tri_Mesh* m, SWIFT_Array<int>& piece_ids,
                       SWIFT_Array< SWIFT_Array<int> >& mfs,
                       SWIFT_Array< SWIFT_Array<SWIFT_Tri_Face> >& vfs )
{
    int i;

    piece_ids.Create( m->Num_Faces() );
    mfs.Create( 1 );
    mfs[0].Create( m->Num_Faces() );
    for( i = 0; i < m->Num_Faces(); i++ ) {
        mfs[0][i] = i;
        piece_ids[i] = 0;
    }

    vfs.Create( 1 );
}
예제 #3
0
파일: gui.cpp 프로젝트: ipa-nhg/kukadu
int Key_K_CB( Togl *togl, int argc, const char *argv[] )
{
    if( dh == DRAW_HIERARCHY ) {
        if( which_pieces.Length() != 1 ) {
            // Go up the hierarchy
            int i;
            SWIFT_Array<SWIFT_BV*> new_which_pieces( which_pieces.Length() );
            SWIFT_BV* parent;

            new_which_pieces.Set_Length( 0 );
            parent = NULL;
            for( i = 0; i < which_pieces.Length(); i++ ) {
                if( uleaves && which_pieces[i]->Is_Leaf() &&
                    which_pieces[i]->Level() < level
                ) {
                    new_which_pieces.Add( which_pieces[i] );
                } else if( parent != which_pieces[i]->Parent() ) {
                    parent = which_pieces[i]->Parent();
                    new_which_pieces.Add( parent );
                }
            }

            level--;

            // Include the new leaves at this level if uleaves is false
            if( !uleaves ) {
                for( i = 0; i < num_leaves; i++ ) {
                    if( leaves[i]->Level() == level ) {
                        new_which_pieces.Add_Grow( leaves[i], 10 );
                    }
                }
            }

            which_pieces.Destroy();
            which_pieces = new_which_pieces;
            new_which_pieces.Nullify();
        }
    } else {
            // Show next convex piece and set text field
            char temp[80];

            if( which_cps.Length() == 0 ) {
                which_cps.Set_Length( 1 );
                which_cps[0] = 0;
            } else {
                which_cps[0] = (which_cps[0] == which_cps.Max_Length()-1 ?
                                                0 : which_cps[0]+1);
                which_cps.Set_Length( 1 );
            }
            sprintf( temp, "set which_cps %d", which_cps[0] );
            Tcl_Eval( Togl_Interp( togl ), temp );
    }

    Togl_PostRedisplay( togl );
    return TCL_OK;
}
예제 #4
0
파일: gui.cpp 프로젝트: ipa-nhg/kukadu
void Compute_Leaves( SWIFT_BV* piece )
{
    int i;

    if( piece == mesh->Root() ) {
        leaves.Destroy();
        leaves.Create( num_leaves );
        leaves.Set_Length( 0 );
    }

    if( piece->Is_Leaf() ) {
        leaves.Add( piece );
    } else {
        for( i = 0; i < piece->Num_Children(); i++ ) {
            Compute_Leaves( piece->Children()[i] );
        }
    }
}
예제 #5
0
void Compute_Convex_Hull( SWIFT_Array<SWIFT_Tri_Vertex>& vs, int*& fs, int& fn )
{
    int i;
    //coordT *qhv = new coordT[vs.Length()*3];
    coordT *qhv = (coordT*)malloc( sizeof(coordT)*vs.Length()*3 );
    coordT *p = qhv;

    // Load the coordinates into the vertex array for qhull since SWIFT_Real
    // may not be the same type.
    for( i = 0; i < vs.Length(); i++ ) {
        *p++ = vs[i].Coords().X();
        *p++ = vs[i].Coords().Y();
        *p++ = vs[i].Coords().Z();
    }

    Compute_Convex_Hull( qhv, vs.Length(), fs, fn );

    // Do not delete these here since they are deleted in the qh_init_B fcn
    //free( qhv );
    //delete qhv;
}
예제 #6
0
파일: gui.cpp 프로젝트: ipa-nhg/kukadu
void Compute_Piece_Centers_Of_Mass( )
{
    int i, j;
    SWIFT_Real area;
    SWIFT_Real total_area;
    SWIFT_Triple areav;
    SWIFT_Triple com;

    if( model_faces.Length() != 0 ) {
        piece_coms.Create( model_faces.Length() );
        for( i = 0; i < model_faces.Length(); i++ ) { 
            com.Set_Value( 0.0, 0.0, 0.0 );
            total_area = 0.0;
            for( j = 0; j < model_faces[i].Length(); j++ ) {
                areav = (mesh->Faces()[model_faces[i][j]].Edge1().Origin()->Coords() -
                         mesh->Faces()[model_faces[i][j]].Edge2().Origin()->Coords()) %
                        (mesh->Faces()[model_faces[i][j]].Edge1().Origin()->Coords() -
                         mesh->Faces()[model_faces[i][j]].Edge3().Origin()->Coords());
                area = 0.5 * areav.Length();
                total_area += area;
                com += area * (mesh->Faces()[model_faces[i][j]].Edge1().Origin()->Coords() +
                               mesh->Faces()[model_faces[i][j]].Edge2().Origin()->Coords() +
                               mesh->Faces()[model_faces[i][j]].Edge3().Origin()->Coords() );
            }
            for( j = 0; j < virtual_faces[i].Length(); j++ ) {
                areav = (virtual_faces[i][j].Edge1().Origin()->Coords() -
                        virtual_faces[i][j].Edge2().Origin()->Coords()) %
                        (virtual_faces[i][j].Edge1().Origin()->Coords() -
                        virtual_faces[i][j].Edge3().Origin()->Coords());
                area = 0.5 * areav.Length();
                total_area += area;
                com += area * (virtual_faces[i][j].Edge1().Origin()->Coords() +
                               virtual_faces[i][j].Edge2().Origin()->Coords() +
                               virtual_faces[i][j].Edge3().Origin()->Coords() );
            }

            piece_coms[i] = com / (3.0 * total_area);
        }
    }
}
예제 #7
0
void Convex_Initialize( SWIFT_Tri_Mesh* m )
{
    int i;
    Convex_Utilities_Initialize( m );

    // Store the mesh's twin info in the twin's list
    twins.Create( m->Num_Faces() );
    for( i = 0; i < m->Num_Faces(); i++ ) {
        twins[i][0] = m->Faces()[i].Edge1().Twin();
        twins[i][1] = m->Faces()[i].Edge2().Twin();
        twins[i][2] = m->Faces()[i].Edge3().Twin();
    }
}
예제 #8
0
파일: gui.cpp 프로젝트: ipa-nhg/kukadu
int Key_J_CB( Togl *togl, int argc, const char *argv[] )
{
    if( dh == DRAW_HIERARCHY ) {
        int i, j;
        bool advanced = false;
        SWIFT_Array<SWIFT_BV*> new_which_pieces( 100 );

        new_which_pieces.Set_Length( 0 );
        for( i = 0; i < which_pieces.Length(); i++ ) {
            if( uleaves && which_pieces[i]->Is_Leaf() ) {
                // Keep this leaf
                new_which_pieces.Add_Grow( which_pieces[i], 10 );
            } else {
                for( j = 0; j < which_pieces[i]->Num_Children(); j++ ) {
                    new_which_pieces.Add_Grow(
                                        which_pieces[i]->Children()[j], 10 );
                    advanced = true;
                }
            }
        }

        if( advanced ) {
            level++;
            which_pieces.Destroy();
            which_pieces = new_which_pieces;
            new_which_pieces.Nullify();
        }
    } else {
            // Show previous convex piece and set text field
            char temp[80];

            if( which_cps.Length() == 0 ) {
                which_cps.Set_Length( 1 );
                which_cps[0] = 0;
            } else {
                which_cps[0] = (which_cps[0] == 0 ?
                                   which_cps.Max_Length()-1 : which_cps[0]-1);
                which_cps.Set_Length( 1 );
            }
            sprintf( temp, "set which_cps %d", which_cps[0] );
            Tcl_Eval( Togl_Interp( togl ), temp );
    }

    Togl_PostRedisplay( togl );
    return TCL_OK;
}
예제 #9
0
파일: gui.cpp 프로젝트: ipa-nhg/kukadu
int Convex_Pieces_CB( Togl *togl, int argc, const char *argv[] )
{
    if( argv[2][0] == 'A' || argv[2][0] == 'a' ) {
        // Want to draw all pieces
        int i;
        which_cps.Set_Length( which_cps.Max_Length() );
        for( i = 0; i < which_cps.Length(); i++ ) {
            which_cps[i] = i;
        }
    } else {
        // Parse the string to determine which ones to draw
        long upper, lower;
        const char* str = argv[2];
        char* endp;
        int i;
        SWIFT_Array<int> which_cps_back = which_cps;

        which_cps.Set_Length( 0 );

        while( *str != '\0' && which_cps.Length() != which_cps.Max_Length() ) {
            if( isdigit( *str ) ) {
                // Read the next segment
                lower = strtol( str, &endp, 10 );
                str = endp;
                if( lower < 0 ) {
                    lower = 0;
                }
                if( lower >= which_cps.Max_Length() ) {
                    lower = which_cps.Max_Length()-1;
                }
                upper = lower;
                if( *str == '-' ) {
                    str++;
                    if( isdigit( *str ) ) {
                        upper = strtol( str, &endp, 10 );
                        str = endp;
                        if( upper < 0 ) {
                            upper = 0;
                        }
                        if( upper >= which_cps.Max_Length() ) {
                            upper = which_cps.Max_Length()-1;
                        }
                        if( upper < lower ) {
                            int j = lower;
                            lower = upper;
                            upper = j;
                        }
                    } else {
                        cerr << "Error: Expecting number after '-'" << endl;
                        which_cps = which_cps_back;
                        break;
                    }
                }

                // Save the segment
                for( i = lower; i <= upper &&
                     which_cps.Length() != which_cps.Max_Length(); i++
                ) {
                    which_cps.Add( i );
                }

                // Done this segment
                if( *str == ',' ) {
                    str++;
                } else {
                    // Assume that we found the end of the list
                    break;
                }
            } else {
                break;
            }
        }
    }

    Togl_PostRedisplay( t );
    return TCL_OK;
}
예제 #10
0
파일: gui.cpp 프로젝트: ipa-nhg/kukadu
void Gui_Init_Before_TclTk( char* filename )
{
#ifdef DECOMP_GRAPHICS
    if( g ) {
        // toggle and radio button variables
        backface = 1;
        wireframe = 0;
        color = 1;
        axes = 1;

        explode = 0;
        prevdh = DRAW_DECOMPOSITION;
        dh = DRAW_DECOMPOSITION;
        edge_conv = 0;
        vfaces = 0;
        save_vfaces = 1;    // turn vfaces on by default for the hierarchy

        tcolor = 0;
        uleaves = 0;

        level = 0;

        // Mode variables
        dragging = false;

        VIEWER_Initialize();
    }
#endif

    mesh = NULL;

    Mesh_Utils_Initialize();

    if( filename != NULL ) {
        int i, j, k;

        if( !Load_File( filename, mesh, split, already_decomp, already_hier,
                        piece_ids, model_faces, virtual_faces )
        ) {
            cerr << "Exiting..." << endl;
            exit( 0 );
            return;
        }

        if( already_hier ) {
            // Have to compute the mesh geometry
            mesh->Compute_All_Hierarchy_Geometry();
        }

        mesh->Compute_Edge_Convexities( edge_convexities );
        if( !already_decomp ) {
            if( jitter ) {
                cerr << "Jittering with amplitude = " << jampl << endl << endl;
                Jitter( mesh, jampl );
            }
            if( ef ) {
                // Flip edges
                cerr << "Flipping edges with tolerance = " << edge_flip_tol
                     << endl << endl;
                Edge_Flip( mesh, edge_flip_tol );
                if( ef_filename != NULL ) {
                    cerr << "Saving edge flipped mesh" << endl << endl;
                    Save_Model_File( ef_filename, mesh );
                }
            }
            if( one_piece ) {
                cerr << "Creating one piece" << endl;
                Create_One_Piece( mesh, piece_ids, model_faces, virtual_faces );
                num_pieces = 1;
            } else {
                Decompose_Mesh( );
            }

            // Write the result to a file if that option is on
            if( w ) {
                cerr << "Saving decomposition result" << endl << endl;
                Save_Decomposition_File( decomp_filename, mesh, piece_ids,
                                         model_faces, virtual_faces );
            }
        } else if( !already_hier ) {
            num_pieces = model_faces.Length();
        } else {
            num_pieces = (mesh->Num_BVs()+1)/2;
        }

        if( hierarchy ) {
            // Create the bounding volume hierarchy
            num_leaves = num_pieces;
            if( !already_hier ) {
                cerr << "Creating convex hierarchy" << endl;
                mesh->Create_BV_Hierarchy( split, piece_ids, model_faces,
                                           virtual_faces, st_faces, st_twins );
                if( hier_filename != NULL ) {
                    cerr << "Saving convex hierarchy" << endl << endl;
                    Save_Hierarchy_File( hier_filename, mesh,
                                         st_faces, st_twins );
                }
            }
#ifdef DECOMP_GRAPHICS
        } else {
            if( g ) {
                // Compute the virtual face normals
                for( i = 0; i < virtual_faces.Length(); i++ ) {
                    for( j = 0; j < virtual_faces[i].Length(); j++ ) {
                        virtual_faces[i][j].Edge1().Compute_Direction_Length();
                        virtual_faces[i][j].Edge2().Compute_Direction_Length();
                        virtual_faces[i][j].Edge3().Compute_Direction_Length();
                        virtual_faces[i][j].Compute_Plane_From_Edges();
                    }
                }
            }
#endif
        }
        cerr << "COM = " << mesh->Center_Of_Mass() << endl;

#ifdef DECOMP_GRAPHICS
        if( g ) {
            if( hierarchy ) {
                // Hierarchy has been created.

                if( already_hier ) {
                    // Create the piece_ids and the virtual faces
                    piece_ids.Create( mesh->Num_Faces() );
                    virtual_faces.Create( num_pieces );
                    for( i = 0, k = 0; i < mesh->Num_BVs(); i++ ){
                        if( !mesh->BVs()[i].Is_Leaf() ) {
                            continue;
                        }
                        for( j = 0; j < mesh->BVs()[i].Num_Other_Faces(); j++ ){
                            piece_ids[mesh->Face_Id(
                                    mesh->BVs()[i].Other_Faces()[j] )] = k;
                        }
                        virtual_faces[k].Create( mesh->BVs()[i].Num_Faces() );
                        for( j = 0; j < virtual_faces[k].Length(); j++ ) {
                            virtual_faces[k][j] = mesh->BVs()[i].Faces()[j];
                            virtual_faces[k][j].Edge1().Nullify_Twins();
                            virtual_faces[k][j].Edge2().Nullify_Twins();
                            virtual_faces[k][j].Edge3().Nullify_Twins();
                        }
                        k++;
                    }

                    // Create the model faces
                    model_faces.Create( num_pieces );
                    for( i = 0; i < mesh->Num_Faces(); i++ ) {
                        model_faces[piece_ids[i]].Add_Grow( i, 10 );
                    }
                }

                Compute_Leaves( mesh->Root() );

                which_pieces.Create( 1 );
                which_pieces[0] = mesh->Root();
            }

            which_cps.Create( num_pieces );
            for( i = 0; i < num_pieces; i++ ) {
                which_cps[i] = i;
            }
            Compute_Piece_Centers_Of_Mass();
            Initialize_For_New_Model();
            Save_Camera( 1 );
        }
#endif
    } else {
        cerr << "No filename given to initialize -- Exiting..." << endl;
    }
}
예제 #11
0
int Decompose_DFS( SWIFT_Tri_Mesh* m, SWIFT_Array<int>& piece_ids,
                   SWIFT_Array< SWIFT_Array<int> >& mfs,
                   SWIFT_Array< SWIFT_Array<SWIFT_Tri_Face> >& vfs,
                   bool random )
{
    // Start performing DFS on the dual graph maintaining a convex hull along
    // the way.

    cerr << endl << "Starting ";
    if( random ) { 
        cerr << "randomized ";
    }
    cerr << "DFS decomposition" << endl;

    const unsigned int max_faces_in_a_chull = (m->Num_Vertices() - 2) << 1;
    int i, j, k, l, p;
    int created_faces = 0;
    int top, id;
    // The faces stack
    SWIFT_Array<SWIFT_Tri_Face*> sfs;
    // Keeps track of all the faces that were marked as failed so that they can
    // be unmarked efficiently.
    SWIFT_Array<SWIFT_Tri_Face*> mark_failed;
    // The current convex hull
    SWIFT_Array<SWIFT_Tri_Face> chull;
    // Pointers to faces indicating whether the face on the convex hull is a
    // model face or a virtual face (entry is NULL)
    SWIFT_Array<SWIFT_Tri_Face*> cfs;
    // Which faces on the original model are allowed to be added
    SWIFT_Array<bool> fallowed;
    // Which vertices exist on the convex hull
    SWIFT_Array<bool> cvs;
    // Ids of vertices belonging to the convex hull 
    SWIFT_Array<int> cvs_idx;
    // Ids of faces that are added at each iteration
    SWIFT_Array<int> addedfs;
    // The model face ids that belong to a single convex hull
    SWIFT_Array<int> temp_mfs_1d;
    // The model face ids that belong to each convex hull
    SWIFT_Array< SWIFT_Array<int> > temp_mfs_2d;

    sfs.Create( m->Num_Faces() );
    mark_failed.Create( m->Num_Faces() );
    chull.Create( max_faces_in_a_chull );
    cfs.Create( max_faces_in_a_chull );
    fallowed.Create( m->Num_Faces() );
    cvs.Create( m->Num_Vertices() );
    cvs_idx.Create( m->Num_Vertices() );
    addedfs.Create( m->Num_Faces() );
    temp_mfs_1d.Create( m->Num_Faces() );
    temp_mfs_2d.Create( m->Num_Faces() );

    vfs.Create( m->Num_Faces() );
    piece_ids.Create( m->Num_Faces() );

    Prepare_Mesh_For_Decomposition( m );

    for( i = 0; i < m->Num_Faces(); i++ ) {
        fallowed[i] = true;
    }
    for( i = 0; i < m->Num_Vertices(); i++ ) {
        cvs[i] = false;
    }
    cvs_idx.Set_Length( 0 );

    id = 0;
    for( p = 0; p < m->Num_Faces(); ) {
        // Try to advance p
        for( ; p < m->Num_Faces() && m->Faces()[p].Marked(); p++ );
        if( p == m->Num_Faces() ) break;
        if( random ) {
            // Find a random i in the range [p,m->Num_Faces()-1]
            while( m->Faces()[i = (int) ((SWIFT_Real)(m->Num_Faces()-p) *
                                         drand48()) + p].Marked() );
        } else {
            i = p;
        }

        top = 0;
        sfs[0] = m->Faces()(i);
        mark_failed.Set_Length( 0 );
        temp_mfs_1d.Set_Length( 0 );

        Create_First_Face( m->Faces()(i), chull, cfs );

        // Unset all the vertex membership flags
        for( j = 0; j < cvs_idx.Length(); j++ ) { 
            cvs[cvs_idx[j]] = false;
        }
        cvs_idx.Set_Length( 0 );

        // Mark the first three vertices as added to the hull
        cvs_idx.Add( m->Vertex_Id( m->Faces()[i].Edge1().Origin() ) );
        cvs_idx.Add( m->Vertex_Id( m->Faces()[i].Edge2().Origin() ) );
        cvs_idx.Add( m->Vertex_Id( m->Faces()[i].Edge3().Origin() ) );
        cvs[cvs_idx[0]] = true;
        cvs[cvs_idx[1]] = true;
        cvs[cvs_idx[2]] = true;

        // Add the first face
        piece_ids[i] = id;
        m->Faces()[i].Mark();
        temp_mfs_1d.Add( i );
        l = 1;
        addedfs.Set_Length( 1 );
        addedfs[0] = i;
        fallowed[i] = false;

        while( top != -1 ) {
            if( sfs[top]->Edge1().Marked() &&
                sfs[top]->Edge1().Twin()->Adj_Face()->Unmarked()
            ) {
                if( Add_To_Convex_Hull( m, chull, cfs, fallowed, cvs, addedfs,
                            sfs[top]->Edge1().Twin()->Adj_Face(),
                            sfs[top]->Edge1P(),
                            sfs[top]->Edge1().Twin()->Prev()->Origin() )
                ) {
                    cvs_idx.Add( m->Vertex_Id(
                                 sfs[top]->Edge1().Twin()->Prev()->Origin() ) );
                    sfs[top+1] = sfs[top]->Edge1().Twin()->Adj_Face();
                    top++;
                    // Mark all the faces that were added to the chull
                    for( j = l; j < addedfs.Length(); j++ ) {
                        fallowed[addedfs[j]] = false;
                        if( m->Faces()[addedfs[j]].Unmarked() ) {
                            m->Faces()[addedfs[j]].Mark();
                            piece_ids[addedfs[j]] = id;
                            temp_mfs_1d.Add( addedfs[j] );
                        }
                    }
                    l = addedfs.Length();
                    continue;
                } else {
                    mark_failed.Add( sfs[top]->Edge1().Twin()->Adj_Face() );
                    sfs[top]->Edge1().Twin()->Adj_Face()->Mark();
                    fallowed[m->Face_Id(sfs[top]->Edge1().Twin()->Adj_Face())]
                        = false;
                }
            }
            if( sfs[top]->Edge2().Marked() &&
                sfs[top]->Edge2().Twin()->Adj_Face()->Unmarked()
            ) {
                if( Add_To_Convex_Hull( m, chull, cfs, fallowed, cvs, addedfs,
                            sfs[top]->Edge2().Twin()->Adj_Face(),
                            sfs[top]->Edge2P(),
                            sfs[top]->Edge2().Twin()->Prev()->Origin() )
                ) {
                    cvs_idx.Add( m->Vertex_Id(
                                 sfs[top]->Edge2().Twin()->Prev()->Origin() ) );
                    sfs[top+1] = sfs[top]->Edge2().Twin()->Adj_Face();
                    top++;
                    // Mark all the faces that were added to the chull
                    for( j = l; j < addedfs.Length(); j++ ) {
                        fallowed[addedfs[j]] = false;
                        if( m->Faces()[addedfs[j]].Unmarked() ) {
                            m->Faces()[addedfs[j]].Mark();
                            piece_ids[addedfs[j]] = id;
                            temp_mfs_1d.Add( addedfs[j] );
                        }
                    }
                    l = addedfs.Length();
                    continue;
                } else {
                    mark_failed.Add( sfs[top]->Edge2().Twin()->Adj_Face() );
                    sfs[top]->Edge2().Twin()->Adj_Face()->Mark();
                    fallowed[m->Face_Id(sfs[top]->Edge2().Twin()->Adj_Face())]
                        = false;
                }
            }
            if( sfs[top]->Edge3().Marked() &&
                sfs[top]->Edge3().Twin()->Adj_Face()->Unmarked()
            ) {
                if( Add_To_Convex_Hull( m, chull, cfs, fallowed, cvs, addedfs,
                            sfs[top]->Edge3().Twin()->Adj_Face(),
                            sfs[top]->Edge3P(),
                            sfs[top]->Edge3().Twin()->Prev()->Origin() )
                ) {
                    cvs_idx.Add( m->Vertex_Id(
                                 sfs[top]->Edge3().Twin()->Prev()->Origin() ) );
                    sfs[top+1] = sfs[top]->Edge3().Twin()->Adj_Face();
                    top++;
                    // Mark all the faces that were added to the chull
                    for( j = l; j < addedfs.Length(); j++ ) {
                        fallowed[addedfs[j]] = false;
                        if( m->Faces()[addedfs[j]].Unmarked() ) {
                            m->Faces()[addedfs[j]].Mark();
                            piece_ids[addedfs[j]] = id;
                            temp_mfs_1d.Add( addedfs[j] );
                        }
                    }
                    l = addedfs.Length();
                    continue;
                } else {
                    mark_failed.Add( sfs[top]->Edge3().Twin()->Adj_Face() );
                    sfs[top]->Edge3().Twin()->Adj_Face()->Mark();
                    fallowed[m->Face_Id(sfs[top]->Edge3().Twin()->Adj_Face())]
                        = false;
                }
            }

            top--;
        }

        // Unmark all the failed faces.
        for( j = 0; j < mark_failed.Length(); j++ ) {
            mark_failed[j]->Unmark();
            fallowed[m->Face_Id( mark_failed[j] )] = true;
        }

        // Copy the virtual faces for this piece
        for( j = 0, k = 0; j < chull.Length(); j++ ) {
            if( chull[j].Unmarked() && cfs[j] == NULL ) {
                k++;
            }
        }
        created_faces += k;

        vfs[id].Create( k );
        for( j = 0, k = 0; j < chull.Length(); j++ ) {
            if( chull[j].Unmarked() && cfs[j] == NULL ) {
                vfs[id][k].Set_Normal_N( chull[j].Normal() );
                vfs[id][k].Set_Distance( chull[j].Distance() );
                vfs[id][k].Edge1().Set_Direction_N(
                                                chull[j].Edge1().Direction() );
                vfs[id][k].Edge2().Set_Direction_N(
                                                chull[j].Edge2().Direction() );
                vfs[id][k].Edge3().Set_Direction_N(
                                                chull[j].Edge3().Direction() );
                vfs[id][k].Edge1().Set_Length( chull[j].Edge1().Length() );
                vfs[id][k].Edge2().Set_Length( chull[j].Edge2().Length() );
                vfs[id][k].Edge3().Set_Length( chull[j].Edge3().Length() );
                vfs[id][k].Edge1().Set_Origin( chull[j].Edge1().Origin() );
                vfs[id][k].Edge2().Set_Origin( chull[j].Edge2().Origin() );
                vfs[id][k].Edge3().Set_Origin( chull[j].Edge3().Origin() );
                vfs[id][k].Edge1().Set_Twin( chull[j].Edge1().Twin() );
                vfs[id][k].Edge2().Set_Twin( chull[j].Edge2().Twin() );
                vfs[id][k].Edge3().Set_Twin( chull[j].Edge3().Twin() );
                chull[j].Edge1().Twin()->Set_Twin( vfs[id][k].Edge1P() );
                chull[j].Edge2().Twin()->Set_Twin( vfs[id][k].Edge2P() );
                chull[j].Edge3().Twin()->Set_Twin( vfs[id][k].Edge3P() );
                k++;
            }
        }

        // Copy the model faces for this piece
        temp_mfs_2d[id].Copy_Length( temp_mfs_1d );

        id++;
        if( !random ) {
            p++;
        }
    }
    temp_mfs_2d.Set_Length( id );
    vfs.Set_Length( id );

    // Unmark all the faces and edges
    for( i = 0; i < m->Num_Faces(); i++ ) {
        m->Faces()[i].Unmark();
        m->Faces()[i].Edge1().Unmark();
        m->Faces()[i].Edge2().Unmark();
        m->Faces()[i].Edge3().Unmark();
    }

    // Copy the mfs
    mfs.Copy_Length( temp_mfs_2d );
    for( i = 0; i < temp_mfs_2d.Length(); i++ ) {
        temp_mfs_2d[i].Nullify();
    }

    cerr << "Created " << id << " pieces" << endl;
    cerr << "Original faces = " << m->Num_Faces() << endl;
    cerr << "Created virtual faces = " << created_faces << endl << endl;

    return id;
}
예제 #12
0
int Decompose_Cresting_BFS( SWIFT_Tri_Mesh* m, SWIFT_Array<int>& piece_ids,
                            SWIFT_Array< SWIFT_Array<int> >& mfs,
                            SWIFT_Array< SWIFT_Array<SWIFT_Tri_Face> >& vfs )
{
    // Start performing BFS on the dual graph maintaining a convex hull along
    // the way.

    cerr << endl << "Starting cresting BFS decomposition" << endl;

    const unsigned int max_faces_in_a_chull = (m->Num_Vertices() - 2) << 1;
    int i, j, k, l;
    int created_faces = 0;
    int front, id;
    bool add_children;
    SWIFT_Tri_Edge* e;
    SWIFT_Tri_Vertex* v;
    SWIFT_Array<SWIFT_Tri_Face*> qfs;   // The queue
    SWIFT_Array<SWIFT_Tri_Face*> qfs_parents;
    SWIFT_Array<int> qmap;
    SWIFT_Array<int> qmap_idx;
    SWIFT_Array<SWIFT_Tri_Face*> mark_failed;
    SWIFT_Array<SWIFT_Tri_Face> chull;
    SWIFT_Array<SWIFT_Tri_Face*> cfs;
    SWIFT_Array<bool> fallowed;
    SWIFT_Array<bool> cvs;
    SWIFT_Array<int> cvs_idx;
    SWIFT_Array<int> addedfs;
    SWIFT_Array<int> temp_mfs_1d;
    SWIFT_Array< SWIFT_Array<int> > temp_mfs_2d;

    // The priority queue
    SWIFT_Array<int> lengths( m->Num_Faces() );
    SWIFT_Array<int> bmap( m->Num_Faces() );
    SWIFT_Array<int> fmap( m->Num_Faces() );

    qfs.Create( m->Num_Faces() );
    qfs_parents.Create( m->Num_Faces() );
    qmap.Create( m->Num_Faces() );
    qmap_idx.Create( m->Num_Faces() );
    mark_failed.Create( m->Num_Faces() );
    chull.Create( max_faces_in_a_chull );
    cfs.Create( max_faces_in_a_chull );
    fallowed.Create( m->Num_Faces() );
    cvs.Create( m->Num_Vertices() );
    cvs_idx.Create( m->Num_Vertices() );
    addedfs.Create( m->Num_Faces() );
    temp_mfs_1d.Create( m->Num_Faces() );
    temp_mfs_2d.Create( m->Num_Faces() );

    vfs.Create( m->Num_Faces() );
    piece_ids.Create( m->Num_Faces() );

    Prepare_Mesh_For_Decomposition( m );

    cvs_idx.Set_Length( 0 );
    qmap_idx.Set_Length( 0 );
    for( i = 0; i < m->Num_Vertices(); i++ ) {
        cvs[i] = false;
    }
    for( i = 0; i < m->Num_Faces(); i++ ) {
        fallowed[i] = true;
        piece_ids[i] = -1;
        qmap[i] = -1;
        bmap[i] = fmap[i] = i;
        if( m->Faces()[i].Edge1().Unmarked() ||
            m->Faces()[i].Edge2().Unmarked() ||
            m->Faces()[i].Edge3().Unmarked()
        ) {
            lengths[i] = 0;
            qmap_idx.Add( i );
        } else {
            lengths[i] = -1;
        }
    }

    id = 0;

    // Calculate distances for each face and create priority queue
    if( !qmap_idx.Empty() ) {
        // This is a convex object
        for( i = 0; i < qmap_idx.Max_Length(); i++ ) {
            if( m->Faces()[qmap_idx[i]].Edge1().Twin() != NULL ) {
                k = m->Face_Id(
                        m->Faces()[qmap_idx[i]].Edge1().Twin()->Adj_Face() );
                if( lengths[k] == -1 ) {
                    lengths[k] = lengths[qmap_idx[i]]+1;
                    qmap_idx.Add( k );
                }
            }
            if( m->Faces()[qmap_idx[i]].Edge2().Twin() != NULL ) {
                k = m->Face_Id(
                        m->Faces()[qmap_idx[i]].Edge2().Twin()->Adj_Face() );
                if( lengths[k] == -1 ) {
                    lengths[k] = lengths[qmap_idx[i]]+1;
                    qmap_idx.Add( k );
                }
            }
            if( m->Faces()[qmap_idx[i]].Edge3().Twin() != NULL ) {
                k = m->Face_Id(
                        m->Faces()[qmap_idx[i]].Edge3().Twin()->Adj_Face() );
                if( lengths[k] == -1 ) {
                    lengths[k] = lengths[qmap_idx[i]]+1;
                    qmap_idx.Add( k );
                }
            }
        }

        Build_Heap( lengths, bmap, fmap );
    }
    qmap_idx.Set_Length( 0 );

    // Process the priority queue by doing BFS
    while( !lengths.Empty() ) {
        i = bmap[0];

        // Unset all the qmappings
        for( j = 0; j < qmap_idx.Length(); j++ ) { 
            qmap[qmap_idx[j]] = -1;
        }
        qmap_idx.Set_Length( 0 );
        qfs.Set_Length( 0 );
        qfs_parents.Set_Length( 0 );
        front = 0;

        if( m->Faces()[i].Edge1().Marked() &&
            m->Faces()[i].Edge1().Twin()->Adj_Face()->Unmarked()
        ) {
            j = m->Face_Id( m->Faces()[i].Edge1().Twin()->Adj_Face() );
            qmap_idx.Add( j );
            qmap[j] = qfs.Length();
            qfs.Add( m->Faces()(j) );
            m->Faces()(j)->Mark();
            qfs_parents.Add( m->Faces()(i) );
        }
        if( m->Faces()[i].Edge2().Marked() &&
            m->Faces()[i].Edge2().Twin()->Adj_Face()->Unmarked()
        ) {
            j = m->Face_Id( m->Faces()[i].Edge2().Twin()->Adj_Face() );
            qmap_idx.Add( j );
            qmap[j] = qfs.Length();
            qfs.Add( m->Faces()(j) );
            m->Faces()(j)->Mark();
            qfs_parents.Add( m->Faces()(i) );
        }
        if( m->Faces()[i].Edge3().Marked() &&
            m->Faces()[i].Edge3().Twin()->Adj_Face()->Unmarked()
        ) {
            j = m->Face_Id( m->Faces()[i].Edge3().Twin()->Adj_Face() );
            qmap_idx.Add( j );
            qmap[j] = qfs.Length();
            qfs.Add( m->Faces()(j) );
            m->Faces()(j)->Mark();
            qfs_parents.Add( m->Faces()(i) );
        }

        mark_failed.Set_Length( 0 );
        temp_mfs_1d.Set_Length( 0 );

        Create_First_Face( m->Faces()(i), chull, cfs );

        // Unset all the vertex membership flags
        for( j = 0; j < cvs_idx.Length(); j++ ) { 
            cvs[cvs_idx[j]] = false;
        }
        cvs_idx.Set_Length( 0 );

        // Mark the first three vertices as added to the hull
        cvs_idx.Add( m->Vertex_Id( m->Faces()[i].Edge1().Origin() ) );
        cvs_idx.Add( m->Vertex_Id( m->Faces()[i].Edge2().Origin() ) );
        cvs_idx.Add( m->Vertex_Id( m->Faces()[i].Edge3().Origin() ) );
        cvs[cvs_idx[0]] = true;
        cvs[cvs_idx[1]] = true;
        cvs[cvs_idx[2]] = true;

        // Add the first face
        piece_ids[i] = id;
        m->Faces()[i].Mark();
        temp_mfs_1d.Add( i );
        l = 1;
        addedfs.Set_Length( 1 );
        addedfs[0] = i;
        fallowed[i] = false;


        // The strategy here is a bit different from that of DFS.  Whatever
        // is at the front of the queue is tested for validity and if so, it
        // is added and the unmarked neighbors are placed at the end of the
        // queue.
        while( front < qfs.Length() ) {

            if( qmap[ m->Face_Id( qfs[front] ) ] >= 0 ) {
                if( qfs[front]->Edge1().Twin() != NULL &&
                    qfs_parents[front] == qfs[front]->Edge1().Twin()->Adj_Face()
                ) {
                    e = qfs[front]->Edge1().Twin();
                    v = qfs[front]->Edge3().Origin();
                } else if( qfs[front]->Edge2().Twin() != NULL &&
                    qfs_parents[front] == qfs[front]->Edge2().Twin()->Adj_Face()
                ) {
                    e = qfs[front]->Edge2().Twin();
                    v = qfs[front]->Edge1().Origin();
                } else {
                    e = qfs[front]->Edge3().Twin();
                    v = qfs[front]->Edge2().Origin();
                }
                add_children = Add_To_Convex_Hull( m, chull, cfs, fallowed,
                                                   cvs, addedfs,
                                                   qfs[front], e, v );
                if( add_children ) {
                    // Add the face to the current piece
                    cvs_idx.Add( m->Vertex_Id( v ) );
                    // Mark all the faces that were added to the chull
                    for( j = l; j < addedfs.Length(); j++ ) {
                        fallowed[addedfs[j]] = false;
                        if( piece_ids[addedfs[j]] == -1 ) {
                            // Remove faces that were added if they exist in q
                            if( qmap[addedfs[j]] == -1 ) {
                                qmap_idx.Add( addedfs[j] );
                            }
                            qmap[addedfs[j]] = -2;
                            piece_ids[addedfs[j]] = id;
                            temp_mfs_1d.Add( addedfs[j] );
                            Delete_From_Heap( lengths, bmap, fmap,
                                              fmap[addedfs[j]] );
                        }
                    }
                    l = addedfs.Length();
                }
            } else {
                add_children = true;
            }

            if( add_children ) {
                // Expand the front by adding unmarked neighbors to the queue
                if( qfs[front]->Edge1().Marked() &&
                    qfs[front]->Edge1().Twin()->Adj_Face()->Unmarked()
                ) {
                    j = m->Face_Id( qfs[front]->Edge1().Twin()->Adj_Face() );
                    if( qmap[j] == -2 ) {
                        qmap[j] = -1;
                    } else {
                        qmap[j] = qfs.Length();
                        qmap_idx.Add( j );
                    }
                    qfs.Add( m->Faces()(j) );
                    m->Faces()(j)->Mark();
                    qfs_parents.Add( qfs[front] );
                }
                if( qfs[front]->Edge2().Marked() &&
                    qfs[front]->Edge2().Twin()->Adj_Face()->Unmarked()
                ) {
                    j = m->Face_Id( qfs[front]->Edge2().Twin()->Adj_Face() );
                    if( qmap[j] == -2 ) {
                        qmap[j] = -1;
                    } else {
                        qmap[j] = qfs.Length();
                        qmap_idx.Add( j );
                    }
                    qfs.Add( m->Faces()(j) );
                    m->Faces()(j)->Mark();
                    qfs_parents.Add( qfs[front] );
                }
                if( qfs[front]->Edge3().Marked() &&
                    qfs[front]->Edge3().Twin()->Adj_Face()->Unmarked()
                ) {
                    j = m->Face_Id( qfs[front]->Edge3().Twin()->Adj_Face() );
                    if( qmap[j] == -2 ) {
                        qmap[j] = -1;
                    } else {
                        qmap[j] = qfs.Length();
                        qmap_idx.Add( j );
                    }
                    qfs.Add( m->Faces()(j) );
                    m->Faces()(j)->Mark();
                    qfs_parents.Add( qfs[front] );
                }
            } else {
                mark_failed.Add( qfs[front] );
            }
            front++;
        }

        // Unmark all the failed faces.
        for( j = 0; j < mark_failed.Length(); j++ ) {
            mark_failed[j]->Unmark();
        }

        // Copy the virtual faces for this piece
        for( j = 0, k = 0; j < chull.Length(); j++ ) {
            if( chull[j].Unmarked() && cfs[j] == NULL ) {
                k++;
            }
        }
        created_faces += k;

        vfs[id].Create( k );
        for( j = 0, k = 0; j < chull.Length(); j++ ) {
            if( chull[j].Unmarked() && cfs[j] == NULL ) {
                vfs[id][k].Set_Normal_N( chull[j].Normal() );
                vfs[id][k].Set_Distance( chull[j].Distance() );
                vfs[id][k].Edge1().Set_Direction_N(
                                                chull[j].Edge1().Direction() );
                vfs[id][k].Edge2().Set_Direction_N(
                                                chull[j].Edge2().Direction() );
                vfs[id][k].Edge3().Set_Direction_N(
                                                chull[j].Edge3().Direction() );
                vfs[id][k].Edge1().Set_Length( chull[j].Edge1().Length() );
                vfs[id][k].Edge2().Set_Length( chull[j].Edge2().Length() );
                vfs[id][k].Edge3().Set_Length( chull[j].Edge3().Length() );
                vfs[id][k].Edge1().Set_Origin( chull[j].Edge1().Origin() );
                vfs[id][k].Edge2().Set_Origin( chull[j].Edge2().Origin() );
                vfs[id][k].Edge3().Set_Origin( chull[j].Edge3().Origin() );
                vfs[id][k].Edge1().Set_Twin( chull[j].Edge1().Twin() );
                vfs[id][k].Edge2().Set_Twin( chull[j].Edge2().Twin() );
                vfs[id][k].Edge3().Set_Twin( chull[j].Edge3().Twin() );
                chull[j].Edge1().Twin()->Set_Twin( vfs[id][k].Edge1P() );
                chull[j].Edge2().Twin()->Set_Twin( vfs[id][k].Edge2P() );
                chull[j].Edge3().Twin()->Set_Twin( vfs[id][k].Edge3P() );
                k++;
            }
        }

        // Copy the model faces for this piece
        temp_mfs_2d[id].Copy_Length( temp_mfs_1d );

        id++;

        // Remove this face from the priority queue
        Delete_From_Heap( lengths, bmap, fmap, fmap[i] );
    }
    temp_mfs_2d.Set_Length( id );
    vfs.Set_Length( id );

    // Unmark all the faces and edges
    for( i = 0; i < m->Num_Faces(); i++ ) {
        m->Faces()[i].Unmark();
        m->Faces()[i].Edge1().Unmark();
        m->Faces()[i].Edge2().Unmark();
        m->Faces()[i].Edge3().Unmark();
    }

    // Copy the mfs
    mfs.Copy_Length( temp_mfs_2d );
    for( i = 0; i < temp_mfs_2d.Length(); i++ ) {
        temp_mfs_2d[i].Nullify();
    }

    cerr << "Created " << id << " pieces" << endl;
    cerr << "Original faces = " << m->Num_Faces() << endl;
    cerr << "Created virtual faces = " << created_faces << endl << endl;

    return id;
}
예제 #13
0
void Edge_Flip( SWIFT_Tri_Mesh* m, SWIFT_Real etol )
{
    const SWIFT_Real etol_sq = etol*etol;
    int i;
    SWIFT_Tri_Face f;
    SWIFT_Array<SWIFT_Tri_Edge*> fedges;

    // Have all the convex edges marked
    Prepare_Mesh_For_Decomposition( m );

    // Traverse all the faces, marking edges that are not allowed to be flipped
    for( i = 0; i < m->Num_Faces(); i++ ) {
        if( m->Faces()[i].Edge1().Unmarked() ) {
            // May be able to flip this edge

            // Build the proposed edge
            f.Edge1().Set_Origin( m->Faces()[i].Edge3().Origin() );
            f.Edge2().Set_Origin(
                            m->Faces()[i].Edge1().Twin()->Prev()->Origin() );
            f.Edge1().Compute_Direction_Length();
            if( Edge_Flip_Allowed( m->Faces()[i].Edge1P(), f.Edge1P(), etol_sq )
            ) {
                fedges.Add_Grow( m->Faces()[i].Edge1P(), 100 );
                // Have to mark other edges in these two faces as well as
                // their twins
                m->Faces()[i].Edge2().Mark();
                m->Faces()[i].Edge2().Twin()->Mark();
                m->Faces()[i].Edge3().Mark();
                m->Faces()[i].Edge3().Twin()->Mark();

                m->Faces()[i].Edge1().Twin()->Next()->Mark();
                m->Faces()[i].Edge1().Twin()->Next()->Twin()->Mark();
                m->Faces()[i].Edge1().Twin()->Prev()->Mark();
                m->Faces()[i].Edge1().Twin()->Prev()->Twin()->Mark();
            }
            m->Faces()[i].Edge1().Mark();
            m->Faces()[i].Edge1().Twin()->Mark();
        }
        if( m->Faces()[i].Edge2().Unmarked() ) {
            // May be able to flip this edge

            // Build the proposed edge
            f.Edge1().Set_Origin( m->Faces()[i].Edge1().Origin() );
            f.Edge2().Set_Origin(
                            m->Faces()[i].Edge2().Twin()->Prev()->Origin() );
            f.Edge1().Compute_Direction_Length();
            if( Edge_Flip_Allowed( m->Faces()[i].Edge2P(), f.Edge1P(), etol_sq )
            ) {
                fedges.Add_Grow( m->Faces()[i].Edge2P(), 100 );
                m->Faces()[i].Edge1().Mark();
                m->Faces()[i].Edge1().Twin()->Mark();
                m->Faces()[i].Edge3().Mark();
                m->Faces()[i].Edge3().Twin()->Mark();

                m->Faces()[i].Edge2().Twin()->Next()->Mark();
                m->Faces()[i].Edge2().Twin()->Next()->Twin()->Mark();
                m->Faces()[i].Edge2().Twin()->Prev()->Mark();
                m->Faces()[i].Edge2().Twin()->Prev()->Twin()->Mark();
            }
            m->Faces()[i].Edge2().Mark();
            m->Faces()[i].Edge2().Twin()->Mark();
        }
        if( m->Faces()[i].Edge3().Unmarked() ) {
            // May be able to flip this edge

            // Build the proposed edge
            f.Edge1().Set_Origin( m->Faces()[i].Edge2().Origin() );
            f.Edge2().Set_Origin(
                            m->Faces()[i].Edge3().Twin()->Prev()->Origin() );
            f.Edge1().Compute_Direction_Length();
            if( Edge_Flip_Allowed( m->Faces()[i].Edge3P(), f.Edge1P(), etol_sq )
            ) {
                fedges.Add_Grow( m->Faces()[i].Edge3P(), 100 );
                m->Faces()[i].Edge1().Mark();
                m->Faces()[i].Edge1().Twin()->Mark();
                m->Faces()[i].Edge2().Mark();
                m->Faces()[i].Edge2().Twin()->Mark();

                m->Faces()[i].Edge3().Twin()->Next()->Mark();
                m->Faces()[i].Edge3().Twin()->Next()->Twin()->Mark();
                m->Faces()[i].Edge3().Twin()->Prev()->Mark();
                m->Faces()[i].Edge3().Twin()->Prev()->Twin()->Mark();
            }
            m->Faces()[i].Edge3().Mark();
            m->Faces()[i].Edge3().Twin()->Mark();
        }
    }

    cerr << "Flipped " << fedges.Length() << " edges" << endl;

    // Do the actual swaps
    for( i = 0; i < fedges.Length(); i++ ) {
        SWIFT_Tri_Edge* t1 = fedges[i]->Prev()->Twin();
        SWIFT_Tri_Edge* t2 = fedges[i]->Twin()->Prev()->Twin();

        // Set the origins
        fedges[i]->Set_Origin( fedges[i]->Twin()->Prev()->Origin() );
        fedges[i]->Twin()->Set_Origin( fedges[i]->Prev()->Origin() );

        // Set the flipped edge twins
        fedges[i]->Prev()->Set_Twin( fedges[i]->Twin()->Prev() );
        fedges[i]->Twin()->Prev()->Set_Twin( fedges[i]->Prev() );

        // Set the lengths, directions and twins
        fedges[i]->Twin()->Set_Length( t1->Length() );
        fedges[i]->Twin()->Set_Direction_N( -t1->Direction() );
        fedges[i]->Twin()->Set_Twin( t1 );
        t1->Set_Twin( fedges[i]->Twin() );

        fedges[i]->Set_Length( t2->Length() );
        fedges[i]->Set_Direction_N( -t2->Direction() );
        fedges[i]->Set_Twin( t2 );
        t2->Set_Twin( fedges[i] );

        // Compute the lengths and directions of the flipped edge
        fedges[i]->Prev()->Compute_Direction_Length_Twin();

        // Compute the face normals using the two "good" edges
        fedges[i]->Adj_Face()->Compute_Plane_From_Edges( fedges[i] );
        fedges[i]->Prev()->Twin()->Adj_Face()->Compute_Plane_From_Edges(
                                fedges[i]->Prev()->Twin()->Next() );

        // Set the adjacent edges for the vertices
        fedges[i]->Origin()->Set_Adj_Edge( fedges[i] );
        fedges[i]->Next()->Origin()->Set_Adj_Edge( fedges[i]->Next() );
        fedges[i]->Prev()->Origin()->Set_Adj_Edge( fedges[i]->Prev() );
        fedges[i]->Prev()->Twin()->Prev()->Origin()->Set_Adj_Edge(
                                        fedges[i]->Prev()->Twin()->Prev() );
    }
    Prepare_Mesh_For_Decomposition( m );
}
예제 #14
0
void Compute_Spread( SWIFT_Array<SWIFT_Tri_Vertex>& vs, SWIFT_Triple& center,
                     bool compute_spreads,
                     SWIFT_Triple& min_dir, SWIFT_Real& min_spread,
                     SWIFT_Triple& mid_dir, SWIFT_Real& mid_spread,
                     SWIFT_Triple& max_dir, SWIFT_Real& max_spread )
{
    int fn;
    int* fs;

    if( vs.Length() == 3 ) {
        fs = new int[6];
        fs[0] = 0; fs[1] = 1; fs[2] = 2;
        fs[3] = 0; fs[4] = 2; fs[5] = 1;
        fn = 2;
    } else {
        Compute_Convex_Hull( vs, fs, fn );
    }

    Compute_Spread( vs, fs, fn, false, center, min_dir, mid_dir, max_dir );

    if( compute_spreads ) {
        // Now we have compute the spreads.  This can be done by inserting
        // convex hull vertices into an OBB or by doing hill climbing on the
        // convex hull.  We will go for the first option since building the
        // connectivity of the convex hull is too expensive.

        int i;
        SWIFT_Real min_min_spread = SWIFT_INFINITY;
        SWIFT_Real min_mid_spread = SWIFT_INFINITY;
        SWIFT_Real min_max_spread = SWIFT_INFINITY;
        min_spread = -SWIFT_INFINITY;
        mid_spread = -SWIFT_INFINITY;
        max_spread = -SWIFT_INFINITY;

        for( i = 0; i < fn*3; ) {
            const SWIFT_Triple& v1 = vs[fs[i++]].Coords();
            const SWIFT_Triple& v2 = vs[fs[i++]].Coords();
            const SWIFT_Triple& v3 = vs[fs[i++]].Coords();

            const SWIFT_Real min_dot1 = min_dir * v1;
            const SWIFT_Real min_dot2 = min_dir * v2;
            const SWIFT_Real min_dot3 = min_dir * v3;

            const SWIFT_Real mid_dot1 = mid_dir * v1;
            const SWIFT_Real mid_dot2 = mid_dir * v2;
            const SWIFT_Real mid_dot3 = mid_dir * v3;

            const SWIFT_Real max_dot1 = max_dir * v1;
            const SWIFT_Real max_dot2 = max_dir * v2;
            const SWIFT_Real max_dot3 = max_dir * v3;

            Min_And_Max( min_min_spread, min_spread, min_dot1 );
            Min_And_Max( min_min_spread, min_spread, min_dot2 );
            Min_And_Max( min_min_spread, min_spread, min_dot3 );

            Min_And_Max( min_mid_spread, mid_spread, mid_dot1 );
            Min_And_Max( min_mid_spread, mid_spread, mid_dot2 );
            Min_And_Max( min_mid_spread, mid_spread, mid_dot3 );

            Min_And_Max( min_max_spread, max_spread, max_dot1 );
            Min_And_Max( min_max_spread, max_spread, max_dot2 );
            Min_And_Max( min_max_spread, max_spread, max_dot3 );
        }

        // Recompute the center
        center = 0.5 * (SWIFT_Triple( max_spread, mid_spread, min_spread ) +
             SWIFT_Triple( min_max_spread, min_mid_spread, min_min_spread ));

        min_spread -= min_min_spread;
        mid_spread -= min_mid_spread;
        max_spread -= min_max_spread;
    }

    delete fs;
}
예제 #15
0
// Save a hierarchy file
bool Save_Hierarchy_File( const char* filename, SWIFT_Tri_Mesh* m,
                          SWIFT_Array<SWIFT_Tri_Face*>& st_faces,    
                          SWIFT_Array<SWIFT_Tri_Edge*>& st_twins )
{
    ofstream fout;

    // Try to open the file
    if( filename == NULL ) {
        cerr << "Error: Invalid filename given to write model" << endl;
        return false;
    }

#ifdef WIN32
    fout.open( filename, ios::out | ios::binary );
#else
    fout.open( filename, ios::out );
#endif

    if( !fout.rdbuf()->is_open( ) ) {
        cerr << "Error: file could not be opened for writing \""
             << filename << "\"" << endl;
        return false;
    }

    int i, j, k, l;
    int ntf, ncf, net;
    SWIFT_Array<int> bvq( m->Num_BVs() );
    SWIFT_Array<int> bvs_bmap( m->Num_BVs() );
    SWIFT_Array<int> flen_accum( m->Num_BVs()+1 );
    SWIFT_Array<int> cflen_accum( m->Num_BVs()+1 );
    SWIFT_Tri_Edge* e;
    SWIFT_Tri_Face* f;
    SWIFT_Real* vs;
    SWIFT_Real* vs_walk;
    int* fs;
    char* cs;

    fout << '\0';
    fout << "Convex_Hierarchy" << endl;

    if( machine_is_big_endian ) {
        fout << "binary big_endian" << endl;
    } else {
        fout << "binary little_endian" << endl;
    }

    if( sizeof(SWIFT_Real) == sizeof(float) ) {
        fout << "real float" << endl;
    } else {
        fout << "real double" << endl;
    }

    // Traverse the hierarchy BF counting stuff
    bvq.Set_Length( 0 );
    bvq.Add( 0 );
    bvs_bmap[0] = 0;

    ntf = m->Num_Faces();
    ncf = 0;
    net = 0;

    // Count total twin lengths
    for( i = 0; i < m->Num_Faces(); i++ ) {
        net += m->Faces()[i].Twins_Length();
    }
    
    flen_accum[0] = ntf;
    cflen_accum[0] = ncf;

    for( i = 0; i < bvq.Length(); i++ ) {
        for( j = 0; j < m->BVs()[bvq[i]].Num_Faces(); j++ ) {
            net += m->BVs()[bvq[i]].Faces()[j].Twins_Length();
        }
        ntf += m->BVs()[bvq[i]].Num_Faces();
        ncf += m->BVs()[bvq[i]].Num_Other_Faces();
        flen_accum[i+1] = ntf;
        cflen_accum[i+1] = ncf;
        if( m->BVs()[bvq[i]].Num_Children() != 0 ) {
            bvq.Add( m->BVs().Position( m->BVs()[bvq[i]].Children()[0] ) );
            bvs_bmap[bvq.Last()] = bvq.Length()-1;
            bvq.Add( m->BVs().Position( m->BVs()[bvq[i]].Children()[1] ) );
            bvs_bmap[bvq.Last()] = bvq.Length()-1;
        }
    }

    net *= 3;

    // Write out the counts
    fout << "vertices " << m->Num_Vertices() << endl;
    fout << "map_vids " << m->Map_Vertex_Ids().Length() << endl;
    fout << "map_fids " << m->Map_Face_Ids().Length() << endl;
    fout << "orig_faces " << m->Num_Faces() << endl;
    fout << "orig_hier_faces " << st_faces.Length() << endl;
    fout << "total_faces " << ntf << endl;
    fout << "copied_faces " << ncf << endl;
    fout << "edge_twins " << net << endl;
    fout << "nodes " << m->Num_BVs() << endl;

    // Write out the SWIFT_Tri_Mesh record
    cs = new char[sizeof(int)+7*sizeof(SWIFT_Real)];

    *((int*)cs) = m->Height();
    *((SWIFT_Real*)(cs+sizeof(int))) = m->Center_Of_Mass().X();
    *((SWIFT_Real*)(cs+sizeof(int)+sizeof(SWIFT_Real))) =
                                                m->Center_Of_Mass().Y();
    *((SWIFT_Real*)(cs+sizeof(int)+2*sizeof(SWIFT_Real))) =
                                                m->Center_Of_Mass().Z();
    *((SWIFT_Real*)(cs+sizeof(int)+3*sizeof(SWIFT_Real))) = m->Center().X();
    *((SWIFT_Real*)(cs+sizeof(int)+4*sizeof(SWIFT_Real))) = m->Center().Y();
    *((SWIFT_Real*)(cs+sizeof(int)+5*sizeof(SWIFT_Real))) = m->Center().Z();
    *((SWIFT_Real*)(cs+sizeof(int)+6*sizeof(SWIFT_Real))) = m->Radius();

    fout.write( cs, sizeof(int)+7*sizeof(SWIFT_Real) );

    delete cs;

    // Compose the vertices into an array
    vs = new SWIFT_Real[m->Num_Vertices()*3];
    vs_walk = vs;
    for( i = 0; i < m->Num_Vertices(); i++, vs_walk += 3 ) {
        m->Vertices()[i].Coords().Get_Value( vs_walk );
    }

    // Write the vertices
    fout.write( (char*)vs, m->Num_Vertices()*3*sizeof(SWIFT_Real) );
    delete vs;

    // Write out vertex mapping
    if( !m->No_Duplicate_Vertices() ) {
        fout.write( (char*)m->Map_Vertex_Ids().Data(),
                    m->Num_Vertices()*sizeof(int) );
    }

    // Write out face mapping
    if( !m->Only_Triangles() ) {
        fout.write( (char*)m->Map_Face_Ids().Data(),
                    m->Num_Faces()*sizeof(int) );
    }

    // Write out the faces
    fs = new int[ntf*4];

    // faces in the mesh
    for( i = 0, k = 0, l = 0; i < m->Num_Faces(); i++, k += 4, l++ ) {
        fs[k] = m->Vertex_Id( m->Faces()[i].Vertex1() );
        fs[k+1] = m->Vertex_Id( m->Faces()[i].Vertex2() );
        fs[k+2] = m->Vertex_Id( m->Faces()[i].Vertex3() );
        fs[k+3] = m->Faces()[i].Bit_Field();
        // Store the global id of this face in the face
        m->Faces()[i].Edge1().Set_Next( (SWIFT_Tri_Edge*)l );
    }

    // faces in the hierarchy
    for( i = 0; i < bvq.Length(); i++ ) {
        for( j = 0; j < m->BVs()[bvq[i]].Num_Faces(); j++, k += 4, l++ ){
            fs[k] = m->Vertex_Id( m->BVs()[bvq[i]].Faces()[j].Vertex1() );
            fs[k+1] = m->Vertex_Id( m->BVs()[bvq[i]].Faces()[j].Vertex2() );
            fs[k+2] = m->Vertex_Id( m->BVs()[bvq[i]].Faces()[j].Vertex3() );
            fs[k+3] = m->BVs()[bvq[i]].Faces()[j].Bit_Field();
            // Store the global id of this face in the face
            m->BVs()[bvq[i]].Faces()[j].Edge1().Set_Next(
                                                    (SWIFT_Tri_Edge*)l );
        }
    }

    fout.write( (char*)fs, ntf*4*sizeof(int) );
    delete fs;

    // Write the copied face indices
    fs = new int[ncf];
    for( i = 0, k = 0; i < bvq.Length(); i++ ) {
        for( j = 0; j < m->BVs()[bvq[i]].Num_Other_Faces(); j++, k++ ) {
            // Global id is simply stored in the face
            fs[k] = (int)(m->BVs()[bvq[i]].Other_Faces()[j]->
                                                        Edge1().Next());
        }
    }

    fout.write( (char*)fs, ncf*sizeof(int) );
    delete fs;

    // Write out original twins
    fs = new int[3*m->Num_Faces()];
    for( i = 0, l = 0; i < m->Num_Faces(); i++, l += 3 ) {
        e = m->Faces()[i].Edge1().Twin();
        fs[l] = (e == NULL ? -1 :
                            ((int)(e->Adj_Face()->Edge1().Next())<<2) +
                             e->Adj_Face()->Edge_Id( e ));

        e = m->Faces()[i].Edge2().Twin();
        fs[l+1] = (e == NULL ? -1 :
                            ((int)(e->Adj_Face()->Edge1().Next())<<2) +
                             e->Adj_Face()->Edge_Id( e ));

        e = m->Faces()[i].Edge3().Twin();
        fs[l+2] = (e == NULL ? -1 :
                            ((int)(e->Adj_Face()->Edge1().Next())<<2) +
                             e->Adj_Face()->Edge_Id( e ));
    }

    fout.write( (char*)fs, 3*m->Num_Faces()*sizeof(int) );
    delete fs;

    // Write out ids of original faces living in the hierarchy along with their
    // twins which point to edges in the main mesh.
    fs = new int[st_faces.Length()+st_twins.Length()];
    for( i = 0, j = 0, k = 0; i < st_faces.Length(); i++, j += 3, k += 4 ) {
        fs[k] = (int)(st_faces[i]->Edge1().Next());
        f = st_twins[j]->Adj_Face();
        fs[k+1] = ((int)(f->Edge1().Next())<<2) + f->Edge_Id( st_twins[j] );
        f = st_twins[j+1]->Adj_Face();
        fs[k+2] = ((int)(f->Edge1().Next())<<2) + f->Edge_Id( st_twins[j+1] );
        f = st_twins[j+2]->Adj_Face();
        fs[k+3] = ((int)(f->Edge1().Next())<<2) + f->Edge_Id( st_twins[j+2] );
    }

    fout.write( (char*)fs, (st_faces.Length()+st_twins.Length())*sizeof(int) );
    delete fs;

    // Write the edge twins
    fs = new int[net];
    for( i = 0, l = 0; i < m->Num_Faces();
         l += 3*m->Faces()[i].Twins_Length(), i++
    ) {
        const int first_base = l;
        const int second_base = l+m->Faces()[i].Twins_Length();
        const int third_base = l+(m->Faces()[i].Twins_Length()<<1);
        const int face_level = m->Faces()[i].Starting_Level();
        for( k = face_level;
             k < m->Faces()[i].Twins_Length() + face_level; k++
        ) {
            e = m->Faces()[i].Edge1().Twin( k );
            f = e->Adj_Face();
            fs[first_base+k-face_level] =
                            ((int)(f->Edge1().Next())<<2) + f->Edge_Id( e );

            e = m->Faces()[i].Edge2().Twin( k );
            f = e->Adj_Face();
            fs[second_base+k-face_level] =
                            ((int)(f->Edge1().Next())<<2) + f->Edge_Id( e );

            e = m->Faces()[i].Edge3().Twin( k );
            f = e->Adj_Face();
            fs[third_base+k-face_level] = 
                            ((int)(f->Edge1().Next())<<2) + f->Edge_Id( e );
        }
    }

    for( i = 0; i < bvq.Length(); i++ ) {
        for( j = 0; j < m->BVs()[bvq[i]].Num_Faces();
             l += 3*m->BVs()[bvq[i]].Faces()[j].Twins_Length(), j++
        ) {
            const int first_base = l;
            const int second_base =
                            l+m->BVs()[bvq[i]].Faces()[j].Twins_Length();
            const int third_base =
                        l+(m->BVs()[bvq[i]].Faces()[j].Twins_Length()<<1);
            const int face_level =
                        m->BVs()[bvq[i]].Faces()[j].Starting_Level();
            for( k = face_level; k < m->BVs()[bvq[i]].Faces()[j].
                                           Twins_Length() + face_level; k++
            ) {
                e = m->BVs()[bvq[i]].Faces()[j].Edge1().Twin( k );
                f = e->Adj_Face();
                fs[first_base+k-face_level] =
                            ((int)(f->Edge1().Next())<<2) + f->Edge_Id( e );

                e = m->BVs()[bvq[i]].Faces()[j].Edge2().Twin( k );
                f = e->Adj_Face();
                fs[second_base+k-face_level] =
                            ((int)(f->Edge1().Next())<<2) + f->Edge_Id( e );

                e = m->BVs()[bvq[i]].Faces()[j].Edge3().Twin( k );
                f = e->Adj_Face();
                fs[third_base+k-face_level] = 
                            ((int)(f->Edge1().Next())<<2) + f->Edge_Id( e );
            }
        }
    }

    fout.write( (char*)fs, net*sizeof(int) );
    delete fs;

    // Write the BV records
    for( i = 0; i < bvq.Length(); i++ ) {
        const int BV_bytes = 9*sizeof(int)+4*sizeof(SWIFT_Real)+
                     m->BVs()[bvq[i]].Lookup_Table_Size()*sizeof(int);
        int cs_off = 0;
        cs = new char[BV_bytes];

        // Copied faces
        *((int*)cs+cs_off) = m->BVs()[bvq[i]].Num_Other_Faces();
        cs_off += sizeof(int);
        *((int*)(cs+cs_off)) = cflen_accum[i];
        cs_off += sizeof(int);

        // Faces
        *((int*)(cs+cs_off)) = m->BVs()[bvq[i]].Num_Faces();
        cs_off += sizeof(int);
        *((int*)(cs+cs_off)) = flen_accum[i];
        cs_off += sizeof(int);

        // Parent
        *((int*)(cs+cs_off)) = (i == 0 ? -1 :
                    bvs_bmap[m->BVs().Position(m->BVs()[bvq[i]].Parent())]);
        cs_off += sizeof(int);

        // Children
        *((int*)(cs+cs_off)) = m->BVs()[bvq[i]].Num_Children() == 0 ? -1 :
            bvs_bmap[m->BVs().Position(m->BVs()[bvq[i]].Children()[0])];
        cs_off += sizeof(int);
        *((int*)(cs+cs_off)) = m->BVs()[bvq[i]].Num_Children() == 0 ? -1 :
            bvs_bmap[m->BVs().Position(m->BVs()[bvq[i]].Children()[1])];
        cs_off += sizeof(int);

        // Level
        *((int*)(cs+cs_off)) = m->BVs()[bvq[i]].Level();
        cs_off += sizeof(int);

        // COM, Radius
        *((SWIFT_Real*)(cs+cs_off)) = m->BVs()[bvq[i]].Center_Of_Mass().X();
        cs_off += sizeof(SWIFT_Real);
        *((SWIFT_Real*)(cs+cs_off)) = m->BVs()[bvq[i]].Center_Of_Mass().Y();
        cs_off += sizeof(SWIFT_Real);
        *((SWIFT_Real*)(cs+cs_off)) = m->BVs()[bvq[i]].Center_Of_Mass().Z();
        cs_off += sizeof(SWIFT_Real);
        *((SWIFT_Real*)(cs+cs_off)) = m->BVs()[bvq[i]].Radius();
        cs_off += sizeof(SWIFT_Real);

        // LUT
        *((int*)(cs+cs_off)) = m->BVs()[bvq[i]].Lookup_Table().Type();
        cs_off += sizeof(int);

        for( k = 0; k < m->BVs()[bvq[i]].Lookup_Table_Size(); k++ ) {
            e = m->BVs()[bvq[i]].Lookup_Table().Table()[k];
            f = e->Adj_Face();
            ((int*)(cs+cs_off))[k] =
                            ((int)(f->Edge1().Next())<<2) + f->Edge_Id( e );
        }

        fout.write( cs, BV_bytes );
        delete cs;
    }

    // Restore the edge1 next ptrs
    for( i = 0; i < m->Num_Faces(); i++ ) {
        m->Faces()[i].Edge1().Set_Next( m->Faces()[i].Edge2P() );
    }
    for( i = 0; i < bvq.Length(); i++ ) {
        for( j = 0; j < m->BVs()[bvq[i]].Num_Faces(); j++ ) {
            m->BVs()[bvq[i]].Faces()[j].Edge1().Set_Next(
                                m->BVs()[bvq[i]].Faces()[j].Edge2P() );
        }
    }

    fout.close();

    return true;
}
예제 #16
0
// Save a decomposition file
bool Save_Decomposition_File( const char* filename, SWIFT_Tri_Mesh* m,
                              SWIFT_Array<int>& piece_ids,
                              SWIFT_Array< SWIFT_Array<int> >& mfs,
                              SWIFT_Array< SWIFT_Array<SWIFT_Tri_Face> >& vfs )
{
    int i, j, k;
    int num_vfaces;
    int num_mfaces;
    ofstream fout;
    SWIFT_Real* vs;
    SWIFT_Real* vs_walk;
    int* fs;

    // Try to open the file
    if( filename == NULL ) {
        cerr << "Error: Invalid filename given to write decomp" << endl;
        return false;
    }

#ifdef WIN32
    fout.open( filename, ios::out | ios::binary );
#else
    fout.open( filename, ios::out );
#endif

    if( !fout.rdbuf()->is_open( ) ) {
        cerr << "Error: file could not be opened for writing \""
             << filename << "\"" << endl;
        return false;
    }

    fout << '\0';
    fout << "Convex_Decomposition" << endl;

    if( machine_is_big_endian ) {
        fout << "binary big_endian" << endl;
    } else {
        fout << "binary little_endian" << endl;
    }

    if( sizeof(SWIFT_Real) == sizeof(float) ) {
        fout << "real float" << endl;
    } else {
        fout << "real double" << endl;
    }

    fout << "vertices " << m->Num_Vertices() << endl;
    fout << "faces " << m->Num_Faces() << endl;
    fout << "map_vids " << m->Map_Vertex_Ids().Length() << endl;
    fout << "map_fids " << m->Map_Face_Ids().Length() << endl;
    fout << "pieces " << mfs.Length() << endl;

    // Compose the vertices into an array
    vs = new SWIFT_Real[m->Num_Vertices()*3];
    vs_walk = vs;
    for( i = 0; i < m->Num_Vertices(); i++, vs_walk += 3 ) {
        m->Vertices()[i].Coords().Get_Value( vs_walk );
    }

    // Write the vertices
    fout.write( (char*)vs, m->Num_Vertices()*3*sizeof(SWIFT_Real) );
    delete [] vs;

    // Compose the faces into an array
    fs = new int[m->Num_Faces()*3];
    for( i = 0, j = 0; i < m->Num_Faces(); i++, j += 3 ) {
        fs[j] = m->Vertex_Id( m->Faces()[i].Edge1().Origin() );
        fs[j+1] = m->Vertex_Id( m->Faces()[i].Edge2().Origin() );
        fs[j+2] = m->Vertex_Id( m->Faces()[i].Edge3().Origin() );
    }

    // Write out the faces
    fout.write( (char*)fs, m->Num_Faces()*3*sizeof(int) );
    delete [] fs;

    // Write out vertex mapping
    if( !m->No_Duplicate_Vertices() ) {
        fout.write( (char*)m->Map_Vertex_Ids().Data(),
                    m->Num_Vertices()*sizeof(int) );
    }

    // Write out face mapping
    if( !m->Only_Triangles() ) {
        fout.write( (char*)m->Map_Face_Ids().Data(),
                    m->Num_Faces()*sizeof(int) );
    }

    // Write out piece ids array
    fout.write( (char*)piece_ids.Data(), piece_ids.Length()*sizeof(int) );

    // Compose the original faces lengths into an array
    fs = new int[mfs.Length()];
    for( i = 0; i < mfs.Length(); i++ ) {
        fs[i] = mfs[i].Length();
    }

    // Write out the original faces lengths
    fout.write( (char*)fs, mfs.Length()*sizeof(int) );
    delete [] fs;

    // Compose the virtual faces lengths into an array
    num_vfaces = 0;
    fs = new int[vfs.Length()];
    for( i = 0; i < vfs.Length(); i++ ) {
        num_vfaces += vfs[i].Length();
        fs[i] = vfs[i].Length();
    }

    // Write out the virtual faces lengths
    fout.write( (char*)fs, vfs.Length()*sizeof(int) );
    delete [] fs;

    // Compose the original face ids into an array
    num_mfaces = 0;
    for( i = 0; i < mfs.Length(); i++ ) {
        num_mfaces += mfs[i].Length();
    }
    fs = new int[num_mfaces];
    for( i = 0, k = 0; i < mfs.Length(); i++ ) {
        for( j = 0; j < mfs[i].Length(); j++, k++ ) {
            fs[k] = mfs[i][j];
        }
    }

    // Write out the original face ids
    fout.write( (char*)fs, num_mfaces*sizeof(int) );
    delete [] fs;

    // Compose the virtual face vertex ids into an array
    fs = new int[num_vfaces*3];
    for( i = 0, k = 0; i < vfs.Length(); i++ ) {
        for( j = 0; j < vfs[i].Length(); j++, k += 3 ) {
            fs[k] = m->Vertex_Id( vfs[i][j].Edge1().Origin() );
            fs[k+1] = m->Vertex_Id( vfs[i][j].Edge2().Origin() );
            fs[k+2] = m->Vertex_Id( vfs[i][j].Edge3().Origin() );
        }
    }

    // Write out the virtual face vertex ids
    fout.write( (char*)fs, num_vfaces*3*sizeof(int) );
    delete [] fs;

    fout.close();

    return true;
}