ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
PoissonRecon.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7 
8 Redistributions of source code must retain the above copyright notice, this list of
9 conditions and the following disclaimer. Redistributions in binary form must reproduce
10 the above copyright notice, this list of conditions and the following disclaimer
11 in the documentation and/or other materials provided with the distribution.
12 
13 Neither the name of the Johns Hopkins University nor the names of its contributors
14 may be used to endorse or promote products derived from this software without specific
15 prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
20 SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26 DAMAGE.
27 */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <math.h>
32 #include <float.h>
33 #include <cmath>
34 #ifdef _WIN32
35 #include <Windows.h>
36 #include <Psapi.h>
37 #endif // _WIN32
38 #include "MyTime.h"
39 #include "MarchingCubes.h"
40 #include "Octree.h"
41 #include "SparseMatrix.h"
42 #include "CmdLineParser.h"
43 #include "PPolynomial.h"
44 #include "Ply.h"
45 #include "MemoryUsage.h"
46 #ifdef _OPENMP
47 #include "omp.h"
48 #endif // _OPENMP
49 
50 namespace {
51 
52 void DumpOutput( const char* format , ... );
53 void DumpOutput2( std::vector< char* >& comments , const char* format , ... );
54 #include "MultiGridOctreeData.h"
55 
56 #define DEFAULT_FULL_DEPTH 5
57 
58 #define XSTR(x) STR(x)
59 #define STR(x) #x
60 #if DEFAULT_FULL_DEPTH
61 // #pragma message ( "[WARNING] Setting default full depth to " XSTR(DEFAULT_FULL_DEPTH) )
62 #endif // DEFAULT_FULL_DEPTH
63 
64 #include <stdarg.h>
65 char* outputFile=NULL;
66 int echoStdout=0;
67 void DumpOutput( const char* format , ... )
68 {
69  if( outputFile )
70  {
71  FILE* fp = fopen( outputFile , "a" );
72  va_list args;
73  va_start( args , format );
74  vfprintf( fp , format , args );
75  fclose( fp );
76  va_end( args );
77  }
78  if( echoStdout )
79  {
80  va_list args;
81  va_start( args , format );
82  vprintf( format , args );
83  va_end( args );
84  }
85 }
86 void DumpOutput2( std::vector< char* >& comments , const char* format , ... )
87 {
88  if( outputFile )
89  {
90  FILE* fp = fopen( outputFile , "a" );
91  va_list args;
92  va_start( args , format );
93  vfprintf( fp , format , args );
94  fclose( fp );
95  va_end( args );
96  }
97  if( echoStdout )
98  {
99  va_list args;
100  va_start( args , format );
101  vprintf( format , args );
102  va_end( args );
103  }
104  comments.push_back( new char[1024] );
105  char* str = comments.back();
106  va_list args;
107  va_start( args , format );
108  vsprintf( str , format , args );
109  va_end( args );
110  if( str[strlen(str)-1]=='\n' ) str[strlen(str)-1] = 0;
111 }
112 
113 
115  In( "in" ) ,
116  Out( "out" ) ,
117  VoxelGrid( "voxel" ) ,
118  XForm( "xForm" );
119 
121 #ifdef _WIN32
122  Performance( "performance" ) ,
123 #endif // _WIN32
124  Complete( "complete" ) ,
125  ShowResidual( "showResidual" ) ,
126  NoComments( "noComments" ) ,
127  PolygonMesh( "polygonMesh" ) ,
128  Confidence( "confidence" ) ,
129  NormalWeights( "nWeights" ) ,
130  NonManifold( "nonManifold" ) ,
131  Dirichlet( "dirichlet" ) ,
132  ASCII( "ascii" ) ,
133  Density( "density" ) ,
134  LinearFit( "linearFit" ) ,
135  PrimalVoxel( "primalVoxel" ) ,
136  Verbose( "verbose" ) ,
137  Double( "double" );
138 
140  Degree( "degree" , 2 ) ,
141  Depth( "depth" , 8 ) ,
142  CGDepth( "cgDepth" , 0 ) ,
143  KernelDepth( "kernelDepth" ) ,
144  AdaptiveExponent( "adaptiveExp" , 1 ) ,
145  Iters( "iters" , 8 ) ,
146  VoxelDepth( "voxelDepth" , -1 ) ,
147  FullDepth( "fullDepth" , DEFAULT_FULL_DEPTH ) ,
148  MinDepth( "minDepth" , 0 ) ,
149  MaxSolveDepth( "maxSolveDepth" ) ,
150  Threads( "threads" , omp_get_num_procs() );
151 
153  Color( "color" , 16.f ) ,
154  SamplesPerNode( "samplesPerNode" , 1.5f ) ,
155  Scale( "scale" , 1.1f ) ,
156  CSSolverAccuracy( "cgAccuracy" , float(1e-3) ) ,
157  PointWeight( "pointWeight" , 4.f );
158 
159 
161 {
162  &In , &Degree , &Depth , &Out , &XForm ,
163  &Scale , &Verbose , &CSSolverAccuracy , &NoComments , &Double ,
164  &KernelDepth , &SamplesPerNode , &Confidence , &NormalWeights , &NonManifold , &PolygonMesh , &ASCII , &ShowResidual , &VoxelDepth ,
165  &PointWeight , &VoxelGrid , &Threads , &MaxSolveDepth ,
166  &AdaptiveExponent , &Dirichlet ,
167  &Density ,
168  &FullDepth ,
169  &MinDepth ,
170  &CGDepth , &Iters ,
171  &Complete ,
172  &Color ,
173  &LinearFit ,
174  &PrimalVoxel ,
175 #ifdef _WIN32
176  &Performance ,
177 #endif // _WIN32
178 };
179 
180 
181 void ShowUsage(char* ex)
182 {
183  printf( "Usage: %s\n" , ex );
184  printf( "\t --%s <input points>\n" , In.name );
185 
186  printf( "\t[--%s <ouput triangle mesh>]\n" , Out.name );
187  printf( "\t[--%s <ouput voxel grid>]\n" , VoxelGrid.name );
188 
189  printf( "\t[--%s <b-spline degree>=%d]\n" , Degree.name , Degree.value );
190 
191  printf( "\t[--%s <maximum reconstruction depth>=%d]\n" , Depth.name , Depth.value );
192  printf( "\t\t Running at depth d corresponds to solving on a 2^d x 2^d x 2^d\n" );
193  printf( "\t\t voxel grid.\n" );
194 
195  printf( "\t[--%s <full depth>=%d]\n" , FullDepth.name , FullDepth.value );
196  printf( "\t\t This flag specifies the depth up to which the octree should be complete.\n" );
197 
198  printf( "\t[--%s <depth at which to extract the voxel grid>=<%s>]\n" , VoxelDepth.name , Depth.name );
199 
200  printf( "\t[--%s <conjugate-gradients depth>=%d]\n" , CGDepth.name , CGDepth.value );
201  printf( "\t\t The depth up to which a conjugate-gradients solver should be used.\n");
202 
203  printf( "\t[--%s <scale factor>=%f]\n" , Scale.name , Scale.value );
204  printf( "\t\t Specifies the factor of the bounding cube that the input\n" );
205  printf( "\t\t samples should fit into.\n" );
206 
207  printf( "\t[--%s <minimum number of samples per node>=%f]\n" , SamplesPerNode.name, SamplesPerNode.value );
208  printf( "\t\t This parameter specifies the minimum number of points that\n" );
209  printf( "\t\t should fall within an octree node.\n" );
210 
211  printf( "\t[--%s <interpolation weight>=%f]\n" , PointWeight.name , PointWeight.value );
212  printf( "\t\t This value specifies the weight that point interpolation constraints are\n" );
213  printf( "\t\t given when defining the (screened) Poisson system.\n" );
214 
215  printf( "\t[--%s <iterations>=%d]\n" , Iters.name , Iters.value );
216  printf( "\t\t This flag specifies the (maximum if CG) number of solver iterations.\n" );
217 
218  printf( "\t[--%s <pull factor>]\n" , Color.name );
219  printf( "\t\t This flag specifies the pull factor for color interpolation\n" );
220 
221 #ifdef _OPENMP
222  printf( "\t[--%s <num threads>=%d]\n" , Threads.name , Threads.value );
223  printf( "\t\t This parameter specifies the number of threads across which\n" );
224  printf( "\t\t the solver should be parallelized.\n" );
225 #endif // _OPENMP
226 
227  printf( "\t[--%s]\n" , Confidence.name );
228  printf( "\t\t If this flag is enabled, the size of a sample's normals is\n" );
229  printf( "\t\t used as a confidence value, affecting the sample's\n" );
230  printf( "\t\t constribution to the reconstruction process.\n" );
231 
232  printf( "\t[--%s]\n" , NormalWeights.name );
233  printf( "\t\t If this flag is enabled, the size of a sample's normals is\n" );
234  printf( "\t\t used as to modulate the interpolation weight.\n" );
235 
236 #if 0
237  printf( "\t[--%s]\n" , NonManifold.name );
238  printf( "\t\t If this flag is enabled, the isosurface extraction does not add\n" );
239  printf( "\t\t a planar polygon's barycenter in order to ensure that the output\n" );
240  printf( "\t\t mesh is manifold.\n" );
241 #endif
242 
243  printf( "\t[--%s]\n" , PolygonMesh.name);
244  printf( "\t\t If this flag is enabled, the isosurface extraction returns polygons\n" );
245  printf( "\t\t rather than triangles.\n" );
246 
247 #if 0
248  printf( "\t[--%s <minimum depth>=%d]\n" , MinDepth.name , MinDepth.value );
249  printf( "\t\t This flag specifies the coarsest depth at which the system is to be solved.\n" );
250 
251  printf( "\t[--%s <cg solver accuracy>=%g]\n" , CSSolverAccuracy.name , CSSolverAccuracy.value );
252  printf( "\t\t This flag specifies the accuracy cut-off to be used for CG.\n" );
253 
254  printf( "\t[--%s <adaptive weighting exponent>=%d]\n", AdaptiveExponent.name , AdaptiveExponent.value );
255  printf( "\t\t This flag specifies the exponent scale for the adaptive weighting.\n" );
256 
257 #ifdef _WIN32
258  printf( "\t[--%s]\n" , Performance.name );
259  printf( "\t\t If this flag is enabled, the running time and peak memory usage\n" );
260  printf( "\t\t is output after the reconstruction.\n" );
261 #endif // _WIN32
262 #endif
263  printf( "\t[--%s]\n" , Dirichlet.name);
264  printf( "\t\t If this flag is enabled, Dirichlet boundary constraints are used for reconstruction.\n" );
265 
266  printf( "\t[--%s]\n" , Density.name );
267  printf( "\t\t If this flag is enabled, the sampling density is written out with the vertices.\n" );
268 
269  printf( "\t[--%s]\n" , LinearFit.name );
270  printf( "\t\t If this flag is enabled, the iso-surfacing will be performed using linear fitting.\n" );
271 
272  printf( "\t[--%s]\n" , PrimalVoxel.name );
273  printf( "\t\t If this flag is enabled, voxel sampling is performed at corners rather than centers.\n" );
274 
275 #if 0
276  printf( "\t[--%s]\n" , ASCII.name );
277  printf( "\t\t If this flag is enabled, the output file is written out in ASCII format.\n" );
278 
279  printf( "\t[--%s]\n" , NoComments.name );
280  printf( "\t\t If this flag is enabled, the output file will not include comments.\n" );
281 #endif
282 
283  printf( "\t[--%s]\n" , Double.name );
284  printf( "\t\t If this flag is enabled, the reconstruction will be performed with double-precision floats.\n" );
285 
286  printf( "\t[--%s]\n" , Verbose.name );
287  printf( "\t\t If this flag is enabled, the progress of the reconstructor will be output to STDOUT.\n" );
288 }
289 
290 Point3D< unsigned char > ReadASCIIColor( FILE* fp )
291 {
293  if( fscanf( fp , " %c %c %c " , &c[0] , &c[1] , &c[2] )!=3 ) fprintf( stderr , "[ERROR] Failed to read color\n" ) , exit( 0 );
294  return c;
295 }
296 
297 PlyProperty PlyColorProperties[]=
298 {
299  { "r" , PLY_UCHAR , PLY_UCHAR , int( offsetof( Point3D< unsigned char > , coords[0] ) ) , 0 , 0 , 0 , 0 } ,
300  { "g" , PLY_UCHAR , PLY_UCHAR , int( offsetof( Point3D< unsigned char > , coords[1] ) ) , 0 , 0 , 0 , 0 } ,
301  { "b" , PLY_UCHAR , PLY_UCHAR , int( offsetof( Point3D< unsigned char > , coords[2] ) ) , 0 , 0 , 0 , 0 } ,
302  { "red" , PLY_UCHAR , PLY_UCHAR , int( offsetof( Point3D< unsigned char > , coords[0] ) ) , 0 , 0 , 0 , 0 } ,
303  { "green" , PLY_UCHAR , PLY_UCHAR , int( offsetof( Point3D< unsigned char > , coords[1] ) ) , 0 , 0 , 0 , 0 } ,
304  { "blue" , PLY_UCHAR , PLY_UCHAR , int( offsetof( Point3D< unsigned char > , coords[2] ) ) , 0 , 0 , 0 , 0 }
305 };
306 
307 bool ValidPlyColorProperties( const bool* props ){ return ( props[0] || props[3] ) && ( props[1] || props[4] ) && ( props[2] || props[5] ); }
308 
309 template< class Real , int Degree , class Vertex >
310 int _Execute( int argc , char* argv[] )
311 {
312  Reset< Real >();
313  int paramNum = sizeof(params)/sizeof(cmdLineReadable*);
314  std::vector< char* > comments;
315 
316  if( Verbose.set ) echoStdout=1;
317 
318  XForm4x4< Real > xForm , iXForm;
319  if( XForm.set )
320  {
321  FILE* fp = fopen( XForm.value , "r" );
322  if( !fp )
323  {
324  fprintf( stderr , "[WARNING] Could not read x-form from: %s\n" , XForm.value );
325  xForm = XForm4x4< Real >::Identity();
326  }
327  else
328  {
329  for( int i=0 ; i<4 ; i++ ) for( int j=0 ; j<4 ; j++ )
330  {
331  float f;
332  if( fscanf( fp , " %f " , &f )!=1 ) fprintf( stderr , "[ERROR] Execute: Failed to read xform\n" ) , exit( 0 );
333  xForm(i,j) = (Real)f;
334  }
335  fclose( fp );
336  }
337  }
338  else xForm = XForm4x4< Real >::Identity();
339  iXForm = xForm.inverse();
340 
341  DumpOutput2( comments , "Running Screened Poisson Reconstruction (Version 8.0)\n" );
342  char str[1024];
343  for( int i=0 ; i<paramNum ; i++ )
344  if( params[i]->set )
345  {
346  params[i]->writeValue( str );
347  if( strlen( str ) ) DumpOutput2( comments , "\t--%s %s\n" , params[i]->name , str );
348  else DumpOutput2( comments , "\t--%s\n" , params[i]->name );
349  }
350 
351  double t;
352  double tt=Time();
353  Real isoValue = 0;
354 
355  Octree< Real > tree;
356  tree.threads = Threads.value;
357  if( !In.set )
358  {
359  ShowUsage( argv[0] );
360  return 0;
361  }
362  if( !MaxSolveDepth.set ) MaxSolveDepth.value = Depth.value;
363 
364  OctNode< TreeNodeData >::SetAllocator( MEMORY_ALLOCATOR_BLOCK_SIZE );
365 
366  t=Time();
367  int kernelDepth = KernelDepth.set ? KernelDepth.value : Depth.value-2;
368  if( kernelDepth>Depth.value )
369  {
370  fprintf( stderr,"[WARNING] %s can't be greater than %s: %d <= %d\n" , KernelDepth.name , Depth.name , KernelDepth.value , Depth.value );
371  kernelDepth = Depth.value;
372  }
373 
374  double maxMemoryUsage;
375  t=Time() , tree.maxMemoryUsage=0;
380  int pointCount;
381  typedef typename Octree< Real >::template ProjectiveData< Point3D< Real > > ProjectiveColor;
383 
384  char* ext = GetFileExtension( In.value );
385  if( Color.set && Color.value>0 )
386  {
389  if ( !strcasecmp( ext , "bnpts" ) ) pointStream = new BinaryOrientedPointStreamWithData< float , Point3D< unsigned char > >( In.value );
390  else if( !strcasecmp( ext , "ply" ) ) pointStream = new PLYOrientedPointStreamWithData< float , Point3D< unsigned char > >( In.value , PlyColorProperties , 6 , ValidPlyColorProperties );
391  else pointStream = new ASCIIOrientedPointStreamWithData< float , Point3D< unsigned char > >( In.value , ReadASCIIColor );
392  pointCount = tree.template SetTree< float , NORMAL_DEGREE , WEIGHT_DEGREE , DATA_DEGREE , Point3D< unsigned char > >( pointStream , MinDepth.value , Depth.value , FullDepth.value , kernelDepth , Real(SamplesPerNode.value) , Scale.value , Confidence.set , NormalWeights.set , PointWeight.value , AdaptiveExponent.value , *densityWeights , *pointInfo , *normalInfo , *nodeWeights , colorData , xForm , Dirichlet.set , Complete.set );
393  delete pointStream;
394 
395  for( const OctNode< TreeNodeData >* n = tree.tree().nextNode() ; n!=NULL ; n=tree.tree().nextNode( n ) )
396  {
397  int idx = colorData->index( n );
398  if( idx>=0 ) colorData->data[idx] *= (Real)pow( Color.value , n->depth() );
399  }
400  }
401  else
402  {
403  OrientedPointStream< float >* pointStream;
404  if ( !strcasecmp( ext , "bnpts" ) ) pointStream = new BinaryOrientedPointStream< float >( In.value );
405  else if( !strcasecmp( ext , "ply" ) ) pointStream = new PLYOrientedPointStream< float >( In.value );
406  else pointStream = new ASCIIOrientedPointStream< float >( In.value );
407  pointCount = tree.template SetTree< float , NORMAL_DEGREE , WEIGHT_DEGREE , DATA_DEGREE , Point3D< unsigned char > >( pointStream , MinDepth.value , Depth.value , FullDepth.value , kernelDepth , Real(SamplesPerNode.value) , Scale.value , Confidence.set , NormalWeights.set , PointWeight.value , AdaptiveExponent.value , *densityWeights , *pointInfo , *normalInfo , *nodeWeights , colorData , xForm , Dirichlet.set , Complete.set );
408  delete pointStream;
409  }
410  delete[] ext;
411  if( !Density.set ) delete densityWeights , densityWeights = NULL;
412  {
413  std::vector< int > indexMap;
414  if( NORMAL_DEGREE>Degree ) tree.template EnableMultigrid< NORMAL_DEGREE >( &indexMap );
415  else tree.template EnableMultigrid< Degree >( &indexMap );
416  if( pointInfo ) pointInfo->remapIndices( indexMap );
417  if( normalInfo ) normalInfo->remapIndices( indexMap );
418  if( densityWeights ) densityWeights->remapIndices( indexMap );
419  if( nodeWeights ) nodeWeights->remapIndices( indexMap );
420  if( colorData ) colorData->remapIndices( indexMap );
421  }
422 
423  DumpOutput2( comments , "# Tree set in: %9.1f (s), %9.1f (MB)\n" , Time()-t , tree.maxMemoryUsage );
424  DumpOutput( "Input Points: %d\n" , pointCount );
425  DumpOutput( "Leaves/Nodes: %d/%d\n" , tree.leaves() , tree.nodes() );
426  DumpOutput( "Memory Usage: %.3f MB\n" , float( MemoryInfo::Usage() )/(1<<20) );
427 
428  maxMemoryUsage = tree.maxMemoryUsage;
429  t=Time() , tree.maxMemoryUsage=0;
430  DenseNodeData< Real , Degree > constraints = tree.template SetLaplacianConstraints< Degree >( *normalInfo );
431  delete normalInfo;
432  DumpOutput2( comments , "# Constraints set in: %9.1f (s), %9.1f (MB)\n" , Time()-t , tree.maxMemoryUsage );
433  DumpOutput( "Memory Usage: %.3f MB\n" , float( MemoryInfo::Usage())/(1<<20) );
434  maxMemoryUsage = std::max< double >( maxMemoryUsage , tree.maxMemoryUsage );
435 
436  t=Time() , tree.maxMemoryUsage=0;
437  DenseNodeData< Real , Degree > solution = tree.SolveSystem( *pointInfo , constraints , ShowResidual.set , Iters.value , MaxSolveDepth.value , CGDepth.value , CSSolverAccuracy.value );
438  delete pointInfo;
439  constraints.resize( 0 );
440 
441  DumpOutput2( comments , "# Linear system solved in: %9.1f (s), %9.1f (MB)\n" , Time()-t , tree.maxMemoryUsage );
442  DumpOutput( "Memory Usage: %.3f MB\n" , float( MemoryInfo::Usage() )/(1<<20) );
443  maxMemoryUsage = std::max< double >( maxMemoryUsage , tree.maxMemoryUsage );
444 
446 
447  if( Verbose.set ) tree.maxMemoryUsage=0;
448  t=Time();
449  isoValue = tree.GetIsoValue( solution , *nodeWeights );
450  delete nodeWeights;
451  DumpOutput( "Got average in: %f\n" , Time()-t );
452  DumpOutput( "Iso-Value: %e\n" , isoValue );
453 
454  if( VoxelGrid.set )
455  {
456  double t = Time();
457  FILE* fp = fopen( VoxelGrid.value , "wb" );
458  if( !fp ) fprintf( stderr , "Failed to open voxel file for writing: %s\n" , VoxelGrid.value );
459  else
460  {
461  int res = 0;
462  Pointer( Real ) values = tree.Evaluate( solution , res , isoValue , VoxelDepth.value , PrimalVoxel.set );
463  fwrite( &res , sizeof(int) , 1 , fp );
464  if( sizeof(Real)==sizeof(float) ) fwrite( values , sizeof(float) , res*res*res , fp );
465  else
466  {
467  float *fValues = new float[res*res*res];
468  for( int i=0 ; i<res*res*res ; i++ ) fValues[i] = float( values[i] );
469  fwrite( fValues , sizeof(float) , res*res*res , fp );
470  delete[] fValues;
471  }
472  fclose( fp );
473  DeletePointer( values );
474  }
475  DumpOutput( "Got voxel grid in: %f\n" , Time()-t );
476  }
477 
478  if( Out.set )
479  {
480  t = Time() , tree.maxMemoryUsage = 0;
481  tree.template GetMCIsoSurface< Degree , WEIGHT_DEGREE , DATA_DEGREE >( densityWeights , colorData , solution , isoValue , mesh , !LinearFit.set , !NonManifold.set , PolygonMesh.set );
482  if( PolygonMesh.set ) DumpOutput2( comments , "# Got polygons in: %9.1f (s), %9.1f (MB)\n" , Time()-t , tree.maxMemoryUsage );
483  else DumpOutput2( comments , "# Got triangles in: %9.1f (s), %9.1f (MB)\n" , Time()-t , tree.maxMemoryUsage );
484  maxMemoryUsage = std::max< double >( maxMemoryUsage , tree.maxMemoryUsage );
485  DumpOutput2( comments , "# Total Solve: %9.1f (s), %9.1f (MB)\n" , Time()-tt , maxMemoryUsage );
486 
487  if( NoComments.set )
488  {
489  if( ASCII.set ) PlyWritePolygons( Out.value , &mesh , PLY_ASCII , NULL , 0 , iXForm );
490  else PlyWritePolygons( Out.value , &mesh , PLY_BINARY_NATIVE , NULL , 0 , iXForm );
491  }
492  else
493  {
494  if( ASCII.set ) PlyWritePolygons( Out.value , &mesh , PLY_ASCII , &comments[0] , (int)comments.size() , iXForm );
495  else PlyWritePolygons( Out.value , &mesh , PLY_BINARY_NATIVE , &comments[0] , (int)comments.size() , iXForm );
496  }
497  DumpOutput( "Vertices / Polygons: %d / %d\n" , mesh.outOfCorePointCount()+mesh.inCorePoints.size() , mesh.polygonCount() );
498  }
499  solution.resize( 0 );
500  if( colorData ){ delete colorData ; colorData = NULL; }
501  return 1;
502 }
503 
504 #ifdef _WIN32
505 inline double to_seconds( const FILETIME& ft )
506 {
507  const double low_to_sec=100e-9; // 100 nanoseconds
508  const double high_to_sec=low_to_sec*4294967296.0;
509  return ft.dwLowDateTime*low_to_sec+ft.dwHighDateTime*high_to_sec;
510 }
511 #endif // _WIN32
512 
513 template< class Real , class Vertex >
514 int Execute( int argc , char* argv[] )
515 {
516  switch( Degree.value )
517  {
518  case 1: return _Execute< Real , 1 , Vertex >( argc , argv );
519  case 2: return _Execute< Real , 2 , Vertex >( argc , argv );
520  case 3: return _Execute< Real , 3 , Vertex >( argc , argv );
521  case 4: return _Execute< Real , 4 , Vertex >( argc , argv );
522  default:
523  fprintf( stderr , "[ERROR] Only B-Splines of degree 1 - 4 are supported" );
524  return EXIT_FAILURE;
525  }
526 }
527 
528 } // namespace
529 
530 int PoissonRecon( int argc , char* argv[] )
531 {
532 #if defined(_WIN32) && defined(MAX_MEMORY_GB)
533  if( MAX_MEMORY_GB>0 )
534  {
535  SIZE_T peakMemory = 1;
536  peakMemory <<= 30;
537  peakMemory *= MAX_MEMORY_GB;
538  printf( "Limiting memory usage to %.2f GB\n" , float( peakMemory>>30 ) );
539  HANDLE h = CreateJobObject( NULL , NULL );
540  AssignProcessToJobObject( h , GetCurrentProcess() );
541 
542  JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
543  jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_JOB_MEMORY;
544  jeli.JobMemoryLimit = peakMemory;
545  if( !SetInformationJobObject( h , JobObjectExtendedLimitInformation , &jeli , sizeof( jeli ) ) )
546  fprintf( stderr , "Failed to set memory limit\n" );
547  }
548 #endif // defined(WIN32) && defined(MAX_MEMORY_GB)
549  double t = Time();
550 
551  cmdLineParse( argc-1 , &argv[1] , sizeof(params)/sizeof(cmdLineReadable*) , params , 1 );
552  if( Density.set )
553  if( Color.set )
554  if( Double.set ) Execute< double , PlyColorAndValueVertex< float > >( argc , argv );
555  else Execute< float , PlyColorAndValueVertex< float > >( argc , argv );
556  else
557  if( Double.set ) Execute< double , PlyValueVertex< float > >( argc , argv );
558  else Execute< float , PlyValueVertex< float > >( argc , argv );
559  else
560  if( Color.set )
561  if( Double.set ) Execute< double , PlyColorVertex< float > >( argc , argv );
562  else Execute< float , PlyColorVertex< float > >( argc , argv );
563  else
564  if( Double.set ) Execute< double , PlyVertex< float > >( argc , argv );
565  else Execute< float , PlyVertex< float > >( argc , argv );
566 #ifdef _WIN32
567  if( Performance.set )
568  {
569  HANDLE cur_thread=GetCurrentThread();
570  FILETIME tcreat, texit, tkernel, tuser;
571  if( GetThreadTimes( cur_thread , &tcreat , &texit , &tkernel , &tuser ) )
572  printf( "Time (Wall/User/Kernel): %.2f / %.2f / %.2f\n" , Time()-t , to_seconds( tuser ) , to_seconds( tkernel ) );
573  else printf( "Time: %.2f\n" , Time()-t );
574  HANDLE h = GetCurrentProcess();
575  PROCESS_MEMORY_COUNTERS pmc;
576  if( GetProcessMemoryInfo( h , &pmc , sizeof(pmc) ) ) printf( "Peak Memory (MB): %d\n" , pmc.PeakWorkingSetSize>>20 );
577  }
578 #endif // _WIN32
579  return EXIT_SUCCESS;
580 }
#define DeletePointer(...)
Definition: Array.h:90
#define Pointer(...)
Definition: Array.h:84
void cmdLineParse(int argc, char **argv, int num, cmdLineReadable **readable, int dumpError)
char * GetFileExtension(char *fileName)
filament::Texture::InternalFormat format
std::string name
#define MAX_MEMORY_GB
#define NORMAL_DEGREE
int omp_get_num_procs(void)
double Time(void)
Definition: MyTime.h:38
#define PLY_ASCII
Definition: Ply.h:51
int PlyWritePolygons(char *fileName, CoredMeshData< Vertex > *mesh, int file_type, const Point3D< float > &translate, float scale, char **comments=NULL, int commentNum=0, XForm4x4< Real > xForm=XForm4x4< Real >::Identity())
Definition: Ply.h:790
#define PLY_UCHAR
Definition: Ply.h:65
#define PLY_BINARY_NATIVE
Definition: Ply.h:54
int PoissonRecon(int argc, char *argv[])
#define DEFAULT_FULL_DEPTH
cmdLineReadable * params[]
void ShowUsage(char *ex)
cmdLineString Out("out")
cmdLineString In("in")
int Execute(void)
cmdLineReadable PolygonMesh("polygonMesh")
#define NULL
int polygonCount(void)
int outOfCorePointCount(void)
std::vector< Vertex > inCorePoints
Definition: Geometry.h:304
static size_t Usage(void)
Definition: MemoryUsage.h:90
const OctNode * nextNode(const OctNode *currentNode=NULL) const
static void SetAllocator(int blockSize)
static double maxMemoryUsage
Real GetIsoValue(const DenseNodeData< Real, FEMDegree > &solution, const SparseNodeData< Real, NormalDegree > &nodeWeights)
V Evaluate(const DenseNodeData< V, DataDegree > &coefficients, Point3D< Real > p, const BSplineData< DataDegree > &bsData) const
const TreeOctNode & tree(void) const
size_t leaves(void) const
size_t nodes(void) const
DenseNodeData< Real, FEMDegree > SolveSystem(SparseNodeData< PointData< Real >, 0 > &pointInfo, DenseNodeData< Real, FEMDegree > &constraints, bool showResidual, int iters, int maxSolveDepth, int cgDepth=0, double cgAccuracy=0)
virtual void writeValue(char *str)
#define offsetof(STRUCTURE, FIELD)
Definition: sqlite3.c:14241
void resize(size_t sz)
XForm4x4 inverse(void) const
Definition: Geometry.h:158
static XForm4x4 Identity(void)
Definition: Geometry.h:120