From 7a3db196e6a2b1ced0098029cb5732ed2d0944f8 Mon Sep 17 00:00:00 2001 From: mkazhdan Date: Wed, 6 Feb 2019 21:38:31 -0500 Subject: [PATCH] Resolved bug that would cause a bad memory access when the octree had empty slices. --- README.md | 13 +++-- Src/AdaptiveTreeVisualization.cpp | 84 +++++++++++++++--------------- Src/FEMTree.h | 2 +- Src/Image.h | 36 +++++++++++++ Src/PoissonRecon.cpp | 85 +++++++++++++++---------------- Src/SSDRecon.cpp | 85 +++++++++++++++---------------- Src/SparseMatrix.inl | 9 +++- 7 files changed, 179 insertions(+), 135 deletions(-) diff --git a/README.md b/README.md index b73caf5..d6920ca 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

Adaptive Multigrid Solvers (Version 10.06)

+

Adaptive Multigrid Solvers (Version 10.07)

links executables @@ -27,10 +27,11 @@ This code-base was born from the Poisson Surface Reconstruction code. It has evo [Kazhdan and Hoppe, 2013]
Executables: -Win64
+Win64
Source Code: -ZIP GitHub
+ZIP GitHub
Older Versions: +V10.06, V10.05, V10.04, V10.03, @@ -805,6 +806,12 @@ Similarly, to reduce compilation times, support for specific degrees can be remo
  • Modified the 2D implementations of PoissonRecon, SSDRecon, and AdaptiveTreeVisualization to support ouput to .jpg and .png image files. +Version 10.06: +
      +
    1. Removed a bug that would cause memory access errors when some slices were empty. +g image files. +
    + diff --git a/Src/AdaptiveTreeVisualization.cpp b/Src/AdaptiveTreeVisualization.cpp index 9f2e7b5..6720cdc 100644 --- a/Src/AdaptiveTreeVisualization.cpp +++ b/Src/AdaptiveTreeVisualization.cpp @@ -91,61 +91,59 @@ void ShowUsage( char* ex ) } template< typename Real , unsigned int Dim > -bool WriteImage( const Real *values , int res , const char *fileName , bool verbose ) +void WriteGrid( ConstPointer( Real ) values , int res , const char *fileName ) { - if( Dim!=2 ) return false; int resolution = 1; for( int d=0 ; d [0,255]\n" , avg - 2*std , avg + 2*std ); - - unsigned char *pixels = new unsigned char[ resolution*3 ]; -#pragma omp parallel for - for( int i=0 ; i( (Real)1. , std::max< Real >( (Real)-1. , ( values[i] - avg ) / (2*std ) ) ); - v = (Real)( ( v + 1. ) / 2. * 256. ); - unsigned char color = (unsigned char )std::min< Real >( (Real)255. , std::max< Real >( (Real)0. , v ) ); - for( int c=0 ; c<3 ; c++ ) pixels[i*3+c ] = color; + Real avg = 0; +#pragma omp parallel for reduction( + : avg ) + for( int i=0 ; i [0,255]\n" , avg - 2*std , avg + 2*std ); + + unsigned char *pixels = new unsigned char[ resolution*3 ]; +#pragma omp parallel for + for( int i=0 ; i( (Real)1. , std::max< Real >( (Real)-1. , ( values[i] - avg ) / (2*std ) ) ); + v = (Real)( ( v + 1. ) / 2. * 256. ); + unsigned char color = (unsigned char )std::min< Real >( (Real)255. , std::max< Real >( (Real)0. , v ) ); + for( int c=0 ; c<3 ; c++ ) pixels[i*3+c ] = color; + } + ImageWriter::Write( fileName , pixels , res , res , 3 ); + delete[] pixels; } - bool success = true; - try{ ImageWriter::Write( fileName , pixels , res , res , 3 ); } - catch( MKExceptions::Exception & ){ success = false; } - delete[] pixels; - return success; -} - -template< typename Real , unsigned int Dim > -void WriteGrid( const Real *values , int res , const char *fileName ) -{ - int resolution = 1; - for( int d=0 ; d @@ -163,7 +161,7 @@ void _Execute( const FEMTree< Dim , Real >* tree , FILE* fp ) double t = Time(); Pointer( Real ) values = tree->template regularGridEvaluate< true >( coefficients , res , -1 , PrimalGrid.set ); if( Verbose.set ) printf( "Got grid: %.2f(s)\n" , Time()-t ); - if( !WriteImage< Real , Dim >( values , res , OutGrid.value , Verbose.set ) ) WriteGrid< Real , Dim >( values , res , OutGrid.value ); + WriteGrid< Real , Dim >( values , res , OutGrid.value ); DeletePointer( values ); } diff --git a/Src/FEMTree.h b/Src/FEMTree.h index 767403c..a15a254 100644 --- a/Src/FEMTree.h +++ b/Src/FEMTree.h @@ -42,7 +42,7 @@ DAMAGE. #ifndef FEM_TREE_INCLUDED #define FEM_TREE_INCLUDED -#define VERSION "10.06" +#define VERSION "10.07" #define MEMORY_ALLOCATOR_BLOCK_SIZE 1<<12 #define NEW_CODE diff --git a/Src/Image.h b/Src/Image.h index 315ba51..345a3d7 100644 --- a/Src/Image.h +++ b/Src/Image.h @@ -37,6 +37,7 @@ struct ImageReader return pixels; } + static bool ValidExtension( const char *ext ); static ImageReader* Get( const char* fileName ); static void GetInfo( const char* fileName , unsigned int& width , unsigned int& height , unsigned int& channels ); virtual ~ImageReader( void ){ } @@ -70,6 +71,8 @@ struct ImageWriter for( unsigned int j=0 ; jnextRow( pixels + j*width*channels ); delete writer; } + + static bool ValidExtension( const char *ext ); static ImageWriter* Get( const char* fileName , unsigned int width , unsigned int height , unsigned int channels , ImageWriterParams params=ImageWriterParams() ); virtual ~ImageWriter( void ){ } unsigned int width( void ) const { return _width; } @@ -160,6 +163,20 @@ protected: } }; +inline bool ImageReader::ValidExtension( const char *ext ) +{ +#ifdef WIN32 + if ( !_stricmp( ext , "jpeg" ) || !_stricmp( ext , "jpg" ) ) return true; + else if( !_stricmp( ext , "png" ) ) return true; + else if( !_stricmp( ext , "iGrid" ) ) return true; +#else // !WIN32 + if( !strcasecmp( ext , "jpeg" ) || !strcasecmp( ext , "jpg" ) ) return true; + else if( !strcasecmp( ext , "png" ) ) return true; + else if( !strcasecmp( ext , "iGrid" ) ) return true; +#endif // WIN32 + return false; +} + inline ImageReader* ImageReader::Get( const char* fileName ) { unsigned int width , height , channels; @@ -200,6 +217,25 @@ inline void ImageReader::GetInfo( const char* fileName , unsigned int& width , u #endif // WIN32 delete[] ext; } + +inline bool ImageWriter::ValidExtension( const char *ext ) +{ +#ifdef WIN32 + if( !_stricmp( ext , "jpeg" ) || !_stricmp( ext , "jpg" ) ) return true; + else if( !_stricmp( ext , "png" ) ) return true; +#ifdef SUPPORT_TILES + else if( !_stricmp( ext , "iGrid" ) ) return true; +#endif // SUPPORT_TILES +#else // !WIN32 + if( !strcasecmp( ext , "jpeg" ) || !strcasecmp( ext , "jpg" ) ) return true; + else if( !strcasecmp( ext , "png" ) ) return true; +#ifdef SUPPORT_TILES + else if( !strcasecmp( ext , "iGrid" ) ) return true; +#endif // SUPPORT_TILES +#endif // WIN32 + return false; +} + inline ImageWriter* ImageWriter::Get( const char* fileName , unsigned int width , unsigned int height , unsigned int channels , ImageWriterParams params ) { ImageWriter* writer = NULL; diff --git a/Src/PoissonRecon.cpp b/Src/PoissonRecon.cpp index bdaafb7..d6a194d 100644 --- a/Src/PoissonRecon.cpp +++ b/Src/PoissonRecon.cpp @@ -353,63 +353,62 @@ void ExtractMesh( UIntPack< FEMSigs ... > , std::tuple< SampleData ... > , FEMTr } template< typename Real , unsigned int Dim > -bool WriteImage( const Real *values , int res , const char *fileName , bool verbose ) +void WriteGrid( ConstPointer( Real ) values , int res , const char *fileName ) { - if( Dim!=2 ) return false; int resolution = 1; for( int d=0 ; d [0,255]\n" , avg - 2*std , avg + 2*std ); - - unsigned char *pixels = new unsigned char[ resolution*3 ]; -#pragma omp parallel for - for( int i=0 ; i( (Real)1. , std::max< Real >( (Real)-1. , ( values[i] - avg ) / (2*std ) ) ); - v = (Real)( ( v + 1. ) / 2. * 256. ); - unsigned char color = (unsigned char )std::min< Real >( (Real)255. , std::max< Real >( (Real)0. , v ) ); - for( int c=0 ; c<3 ; c++ ) pixels[i*3+c ] = color; + Real avg = 0; +#pragma omp parallel for reduction( + : avg ) + for( int i=0 ; i [0,255]\n" , avg - 2*std , avg + 2*std ); + + unsigned char *pixels = new unsigned char[ resolution*3 ]; +#pragma omp parallel for + for( int i=0 ; i( (Real)1. , std::max< Real >( (Real)-1. , ( values[i] - avg ) / (2*std ) ) ); + v = (Real)( ( v + 1. ) / 2. * 256. ); + unsigned char color = (unsigned char )std::min< Real >( (Real)255. , std::max< Real >( (Real)0. , v ) ); + for( int c=0 ; c<3 ; c++ ) pixels[i*3+c ] = color; + } + ImageWriter::Write( fileName , pixels , res , res , 3 ); + delete[] pixels; } - bool success = true; - try{ ImageWriter::Write( fileName , pixels , res , res , 3 ); } - catch( MKExceptions::Exception & ){ success = false; } - delete[] pixels; - return success; -} - -template< typename Real , unsigned int Dim > -void WriteGrid( const Real *values , int res , const char *fileName ) -{ - int resolution = 1; - for( int d=0 ; d void Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) { @@ -669,7 +668,7 @@ void Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) #pragma omp parallel for for( int i=0 ; i( values , res , Grid.value , Verbose.set ) ) WriteGrid< Real , DIMENSION >( values , res , Grid.value ); + WriteGrid< Real , DIMENSION >( values , res , Grid.value ); DeletePointer( values ); if( Verbose.set ) { diff --git a/Src/SSDRecon.cpp b/Src/SSDRecon.cpp index cc92e44..e966acd 100644 --- a/Src/SSDRecon.cpp +++ b/Src/SSDRecon.cpp @@ -377,63 +377,62 @@ void ExtractMesh( UIntPack< FEMSigs ... > , std::tuple< SampleData ... > , FEMTr } template< typename Real , unsigned int Dim > -bool WriteImage( const Real *values , int res , const char *fileName , bool verbose ) +void WriteGrid( ConstPointer( Real ) values , int res , const char *fileName ) { - if( Dim!=2 ) return false; int resolution = 1; for( int d=0 ; d [0,255]\n" , avg - 2*std , avg + 2*std ); - - unsigned char *pixels = new unsigned char[ resolution*3 ]; -#pragma omp parallel for - for( int i=0 ; i( (Real)1. , std::max< Real >( (Real)-1. , ( values[i] - avg ) / (2*std ) ) ); - v = (Real)( ( v + 1. ) / 2. * 256. ); - unsigned char color = (unsigned char )std::min< Real >( (Real)255. , std::max< Real >( (Real)0. , v ) ); - for( int c=0 ; c<3 ; c++ ) pixels[i*3+c ] = color; + Real avg = 0; +#pragma omp parallel for reduction( + : avg ) + for( int i=0 ; i [0,255]\n" , avg - 2*std , avg + 2*std ); + + unsigned char *pixels = new unsigned char[ resolution*3 ]; +#pragma omp parallel for + for( int i=0 ; i( (Real)1. , std::max< Real >( (Real)-1. , ( values[i] - avg ) / (2*std ) ) ); + v = (Real)( ( v + 1. ) / 2. * 256. ); + unsigned char color = (unsigned char )std::min< Real >( (Real)255. , std::max< Real >( (Real)0. , v ) ); + for( int c=0 ; c<3 ; c++ ) pixels[i*3+c ] = color; + } + ImageWriter::Write( fileName , pixels , res , res , 3 ); + delete[] pixels; } - bool success = true; - try{ ImageWriter::Write( fileName , pixels , res , res , 3 ); } - catch( MKExceptions::Exception & ){ success = false; } - delete[] pixels; - return success; -} - -template< typename Real , unsigned int Dim > -void WriteGrid( const Real *values , int res , const char *fileName ) -{ - int resolution = 1; - for( int d=0 ; d void Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) { @@ -674,7 +673,7 @@ void Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) #pragma omp parallel for for( int i=0 ; i( values , res , Grid.value , Verbose.set ) ) WriteGrid< Real , DIMENSION >( values , res , Grid.value ); + WriteGrid< Real , DIMENSION >( values , res , Grid.value ); DeletePointer( values ); if( Verbose.set ) { diff --git a/Src/SparseMatrix.inl b/Src/SparseMatrix.inl index d912c1d..d7a6d1c 100644 --- a/Src/SparseMatrix.inl +++ b/Src/SparseMatrix.inl @@ -598,13 +598,18 @@ template< class T , class IndexType , size_t MaxRowSize > template< class T2 > void SparseMatrix< T , IndexType , MaxRowSize >::operator() ( const T2* in , T2* out ) const { Interface::multiply( in , out ); } -template< class T , class IndexType , size_t MaxRowSize > SparseMatrix< T , IndexType , MaxRowSize >::~SparseMatrix( void ) { resize( 0 ); } +template< class T , class IndexType , size_t MaxRowSize > +SparseMatrix< T , IndexType , MaxRowSize >::~SparseMatrix( void ) +{ + FreePointer( _rowSizes ); + FreePointer( _entries ); +} template< class T , class IndexType , size_t MaxRowSize > void SparseMatrix< T , IndexType , MaxRowSize >::resize( size_t rowNum ) { _rowNum = rowNum; - if( !rowNum || rowNum>_maxRows ) + if( rowNum>_maxRows ) { FreePointer( _rowSizes ); FreePointer( _entries );