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; }
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 ); }
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; }
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] ); } } }
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; }
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); } } }
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(); } }
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; }
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; }
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; } }
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; }
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; }
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 ); }
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; }
// 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; }
// 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; }