//-- // // ComputeVertexNormals // //-- // Compute unit normal of every vertex void Mesh::ComputeVertexNormals() { int i; // Assume that face normals are computed assert( FaceNormalNumber() == FaceNumber() ); // Resize and initialize vertex normal array vertex_normals.assign( VertexNumber(), Vector3d(0,0,0) ); // For every face for( i=0 ; i<FaceNumber() ; i++ ) { // Add face normal to vertex normal VertexNormal(i,0) += FaceNormal(i); VertexNormal(i,1) += FaceNormal(i); VertexNormal(i,2) += FaceNormal(i); } // For every vertex for( i=0 ; i<VertexNumber() ; i++) { // Normalize vertex normal VertexNormal(i).Normalize(); } }
//-- // // ReconstructCurrentLevel // //-- bool MultiresolutionMesh::ReconstructCurrentLevel() { // Test if we are not already at the finest level if( current_level_number <= 0 ) return false; // Recontruct the next fine level current_level_number--; // Insert odd vertices std::list<PairContraction>::iterator it = levels[current_level_number].pair_contractions.begin(); while( it != levels[current_level_number].pair_contractions.end() ) { // Expand candidate of the current pair contraction Expand( *it ); // Next pair contraction ++it; } // Reconstruct odd vertices for( int i=0; i<VertexNumber(); i++ ) { if( levels[current_level_number].vertex_types[i] != ODD_VERTEX ) continue; Vertex(i) = ReconstructVertex(i); } /* // Reconstruct even vertices std::vector<Vector3d> temp_vertices = vertices; for( int i=0; i<VertexNumber(); i++ ) { if( levels[current_level_number].vertex_types[i] != EVEN_VERTEX ) continue; temp_vertices[i] = ReconstructVertex(i); } vertices = temp_vertices; */ if( use_color ) { // Reconstruct odd vertices for( int i=0; i<VertexNumber(); i++ ) { if( levels[current_level_number].vertex_types[i] != ODD_VERTEX ) continue; Color(i) = ReconstructVertexColor(i); } /* // Reconstruct even vertices temp_vertices = colors; for( int i=0; i<VertexNumber(); i++ ) { if( levels[current_level_number].vertex_types[i] != EVEN_VERTEX ) continue; temp_vertices[i] = ReconstructVertexColor(i); } colors = temp_vertices; */ } return true; }
bool neighbour3D::Build_P2P_Neigh(){ if(VertexNumber() == 0 || FaceNumber() == 0) return false; //building an array of empty sets of size of vertices int VertexSize = VertexNumber(); for(int i = 0; i < VertexSize; i++){ set<int> myset; P2P.push_back(myset); } int FaceSize = FaceNumber(); for(int i = 0; i<FaceSize; i++){ Vector3i V(Face(i)); //now we have three vertex INDICES of the face[i] in V P2P.at(V[0]).insert(V[1]);P2P.at(V[0]).insert(V[2]); P2P.at(V[1]).insert(V[2]);P2P.at(V[1]).insert(V[0]); P2P.at(V[2]).insert(V[0]);P2P.at(V[2]).insert(V[1]); } return true; }
//-- // // ComputeGaussianCurvature // //-- void MultiresolutionMesh::ComputeGaussianCurvature() { for( int i=0; i<VertexNumber(); i++ ) { if( IsProgressiveVertexValid(i) == false ) { continue; } gaussian_curvature[i] = GaussianCurvature(this, i); } }
//-- // // ComputeMeanCurvature // //-- void MultiresolutionMesh::ComputeMeanCurvature() { for( int i=0; i<VertexNumber(); i++ ) { if( IsProgressiveVertexValid(i) == false ) { continue; } mean_curvature[i] = MeanCurvatureNormal(this, i).Length() / 2.0; } }
bool neighbour3D :: Build_P2F_Neigh() { int vn = VertexNumber(); int fn = FaceNumber(); if(vn == 0 || fn == 0) return false; for( int i=0; i<vn; i++) { set <int> myset; P2F.push_back(myset); } // now span all the faces, and adds the faces within the corresponding sets for( int i=0; i<fn; i++) { Vector3i F(face(i)); for( int j=0; j<3; j++) P2F[F[j]].insert(i); } return true; }
//-- // // Analysis // //-- bool MultiresolutionMesh::Analysis(int) { // // HSI // #ifdef _HSI_COLOR_ std::vector<Vector3d> color_backup; if( ColorNumber() == VertexNumber() ) { color_backup = colors; Vector3d tmp_hsi; for( int i=0; i<ColorNumber(); i++ ) { Rgb2Hsi( Color(i), tmp_hsi ); Color(i) = tmp_hsi; } } #endif // // RGB 2 Grayscale // #ifdef _RGB_2_GRAYSCALE_ std::vector<Vector3d> color_backup; if( ColorNumber() == VertexNumber() ) { color_backup = colors; double tmp; for( int i=0; i<ColorNumber(); i++ ) { tmp = (Color(i)[0]+Color(i)[1]+Color(i)[2])/3.0; Color(i) = tmp; } } #endif // Initialize member variables current_level_number = -1; levels.clear(); mean_curvature.clear(); gaussian_curvature.clear(); texture.Reset(); vertex_map.clear(); edge_list.clear(); // Initialize normals ComputeFaceNormals(); ComputeVertexNormals(); // Initialize progressive decomposition BeginProgressiveDecomposition(); // Initialize curvatures // mean_curvature.resize( VertexNumber() ); // gaussian_curvature.resize( VertexNumber() ); // ComputeMeanCurvature(); // ComputeGaussianCurvature(); // Initialize texture if( (TextureNumber()!=0) && (TextureName().empty()==false) ) { use_texture = texture.ReadFile( TextureName() ); } else { use_texture = false; } if( ColorNumber() == VertexNumber() ) { use_color = true; } else { use_color = false; } use_normal = true; // permutation.assign(VertexNumber(), -1); // map.assign( VertexNumber(), -1); // Initialize vertex map // This table indicates on which vertex each vertex has collapsed to vertex_map.resize( VertexNumber() ); for( int i=0; i<VertexNumber(); i++ ) { vertex_map[i] = i; } // std::cout<<bounding_box.Center()<<std::endl; // for( int i=0; i<VertexNumber(); i++ ) { // if( // Vertex(i)[0]>-0.01 && // Vertex(i)[2]>-0.01 && // Vertex(i)[0]<0.01 && // Vertex(i)[2]<0.01 // ) // std::cout<<i<<" "<<Vertex(i)<<std::endl; // } ConstPairContractionIterator itp; ConstNeighborIterator itn; std::vector<bool> locked_vertices(VertexNumber(), false); // levels.resize( base_level ); current_level_number = 0; //-- Test -- //int vnum = VertexNumber(); //timer.Reset(); //timer.Start(); //test<<current_level_number<<'\t'<<vnum<<endl; //-- #ifdef _OUTPUT_LEVELS_ // Write the finest level statistics std::ofstream level_stats_file("levels.log"); level_stats_file<<current_level_number<<'\t'<<ValidVertexNumber()<<'\t'<<ValidFaceNumber()<<std::endl; // Write the finest level mesh (the initial mesh) char filename[255]; sprintf(filename,"level%02d.wrl",current_level_number); WriteFile(filename); #endif // // Create the levels of details // while( 1 ) { // Add a new level levels.push_back( ResolutionLevel() ); // // Select the odd vertices // Remove the odd vertices // Lock the neighbors // Odd vertices are a set of independent vertices selected to be removed // The remaining (even) vertices compose the next coarse level // while( !pair_contractions.empty() ) { #ifdef _TEST_PLAN_ // Lock one predefined vertex locked_vertices[1844] = true; // plan-20000 // locked_vertices[30670] = true; // plan-irregulier #endif // Get pair contraction with minimum cost PairContraction pair = MinimumPairContraction(); // Remove pair from contraction candidate list RemovePairContraction( pair.Candidate() ); // Do not perform bad contraction until the level of detail is very low if( pair.Cost()>=invalid_contraction_penalty && current_level_number<15 ) { locked_vertices[pair.Candidate()] = true; continue; } // Test to see if after the pair contraction, // one vertex has a valence of 3 // This case screws up the predict operator itn = NeighborVertices(pair.Candidate()).begin(); while( itn != NeighborVertices(pair.Candidate()).end() ) { if(current_level_number<15 && NeighborVertexNumber(*itn)==4 && FindNeighborVertex(pair.Target(), *itn) && !IsBorderVertex(*itn)) { locked_vertices[pair.Candidate()] = true; } ++itn; } if( locked_vertices[pair.Candidate()] ) continue; // Map the candidate to the target vertex_map[pair.Candidate()] = pair.Target(); // Lock the selected vertex and its neighbors // valid_vertices[pair.Candidate()] = false; // Collapse candidate Collapse( pair ); // Update normals UpdateNormals( pair ); // Update quadrics UpdateQuadrics(pair); // Update pair cost of surronding vertices if( pair.Target() >= 0 ) { // Compute neighbor vertex cost itn = NeighborVertices(pair.Target()).begin(); while( itn != NeighborVertices(pair.Target()).end() ) { if( locked_vertices[*itn] == false ) { RemovePairContraction(*itn); ComputeEdgeCostAtVertex(*itn); } ++itn; } } // Lock the neighborhood of the selected vertex itn = NeighborVertices(pair.Candidate()).begin(); while( itn != NeighborVertices(pair.Candidate()).end() ) { // If the vertex is not already locked if( locked_vertices[*itn] == false ) { // Remove its pair contraction estimation RemovePairContraction(*itn); // Lock it locked_vertices[*itn] = true; } // Next neighbor ++itn; } // Record pair contraction levels[current_level_number].pair_contractions.push_front( pair ); } // bool left = false; int left_vertex_number = 0; // Compute new edge collapse pairs for(int i=0; i<VertexNumber(); i++ ) { if( valid_vertices[i] == false ) continue; left_vertex_number++; locked_vertices[i] = false; ComputeEdgeCostAtVertex(i); } // Update the normals ComputeProgressiveFaceNormals(); ComputeProgressiveVertexNormals(); // Next level current_level_number++; #ifdef _OUTPUT_LEVELS_ // Write the current level statistics level_stats_file<<current_level_number<<'\t'<<ValidVertexNumber()<<'\t'<<ValidFaceNumber()<<std::endl; // Write the current level mesh sprintf(filename,"level%02d.wrl",current_level_number); WriteFile(filename); #endif // Is there any vertex left ? // if( left_vertex_number == 0 ) break; // if( left_vertex_number < 100 ) break; if( left_vertex_number < 10 ) break; } // End the progressive decomposition EndProgressiveDecomposition(); // Reset locked_vertices.clear(); // // Go back the initial fine level // Reconstruct all levels // while( current_level_number > 0 ) { // Next level current_level_number--; // Insert odd vertices itp = levels[current_level_number].pair_contractions.begin(); while( itp != levels[current_level_number].pair_contractions.end() ) { // Expand candidate of current pair contraction Expand( *itp ); // Next pair contraction ++itp; } } // Update the normals ComputeProgressiveFaceNormals(); ComputeProgressiveVertexNormals(); for( int i=0; i<(int)levels.size(); i++ ) { levels[i].Resize( VertexNumber() ); } // // Compute the details // while( current_level_number < LevelNumber() ) { // // Predict odd vertices // itp = levels[current_level_number].pair_contractions.begin(); while( itp != levels[current_level_number].pair_contractions.end() ) { // Compute wavelet coefficient PredictVertex( itp->Candidate(), ODD_VERTEX ); // Invalidate the odd vertex valid_vertices[itp->Candidate()] = false; #ifdef _TEST_PLAN_ // Null the details levels[current_level_number].geometric_details[itp->Candidate()] = 0; #endif // Next pair contraction ++itp; } // // Predict even vertices // for(int i=0; i<VertexNumber(); i++ ) { // Valid vertex ? if( valid_vertices[i] == false ) continue; // Predict even vertex PredictVertex( i, EVEN_VERTEX ); #ifdef _TEST_PLAN_ // Null the details levels[current_level_number].geometric_details[i] = 0; #endif } // // Simplify // Removed odd vertices to go to next coarse level // itp = levels[current_level_number].pair_contractions.begin(); while( itp != levels[current_level_number].pair_contractions.end() ) { // Collapse candidate Collapse( *itp ); // Next Pair contrction ++itp; } // Update the normals ComputeProgressiveFaceNormals(); ComputeProgressiveVertexNormals(); // Go to the next coarse level current_level_number++; } // Test plan #ifdef _TEST_PLAN_ Vertex(1844)[1] = -1.0; // plan-2000 // Vertex(30670)[1] = -1.0; // plan-irregulier char filename[255]; sprintf(filename,"plan-base.wrl"); WriteFile(filename); #endif //-- Test -- //timer.Stop(); //test<<VertexNumber()<<'\t'<<vnum<<'\t'<<((double)VertexNumber()/vnum - 1.0)*100.0<<'\t'<<timer.Total()<<'\t'<<memory<<endl; //-- // // HSI // /* #ifdef _HSI_COLOR_ if( ColorNumber() == VertexNumber() ) { colors = color_backup; } #endif */ return true; }