52 void DumpOutput(
const char*
format , ... );
53 void DumpOutput2( std::vector< char* >& comments ,
const char*
format , ... );
56 #define DEFAULT_FULL_DEPTH 5
58 #define XSTR(x) STR(x)
60 #if DEFAULT_FULL_DEPTH
65 char* outputFile=
NULL;
67 void DumpOutput(
const char*
format , ... )
71 FILE* fp = fopen( outputFile ,
"a" );
74 vfprintf( fp ,
format , args );
86 void DumpOutput2( std::vector< char* >& comments ,
const char*
format , ... )
90 FILE* fp = fopen( outputFile ,
"a" );
93 vfprintf( fp ,
format , args );
100 va_start( args ,
format );
104 comments.push_back(
new char[1024] );
105 char* str = comments.back();
107 va_start( args ,
format );
108 vsprintf( str ,
format , args );
110 if( str[strlen(str)-1]==
'\n' ) str[strlen(str)-1] = 0;
117 VoxelGrid(
"voxel" ) ,
122 Performance(
"performance" ) ,
124 Complete(
"complete" ) ,
125 ShowResidual(
"showResidual" ) ,
126 NoComments(
"noComments" ) ,
128 Confidence(
"confidence" ) ,
129 NormalWeights(
"nWeights" ) ,
130 NonManifold(
"nonManifold" ) ,
131 Dirichlet(
"dirichlet" ) ,
133 Density(
"density" ) ,
134 LinearFit(
"linearFit" ) ,
135 PrimalVoxel(
"primalVoxel" ) ,
136 Verbose(
"verbose" ) ,
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 ) ,
148 MinDepth(
"minDepth" , 0 ) ,
149 MaxSolveDepth(
"maxSolveDepth" ) ,
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 );
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 ,
183 printf(
"Usage: %s\n" , ex );
184 printf(
"\t --%s <input points>\n" ,
In.
name );
186 printf(
"\t[--%s <ouput triangle mesh>]\n" ,
Out.
name );
187 printf(
"\t[--%s <ouput voxel grid>]\n" , VoxelGrid.name );
189 printf(
"\t[--%s <b-spline degree>=%d]\n" , Degree.name , Degree.value );
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" );
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" );
198 printf(
"\t[--%s <depth at which to extract the voxel grid>=<%s>]\n" , VoxelDepth.name , Depth.name );
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");
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" );
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" );
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" );
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" );
218 printf(
"\t[--%s <pull factor>]\n" , Color.name );
219 printf(
"\t\t This flag specifies the pull factor for color interpolation\n" );
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" );
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" );
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" );
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" );
244 printf(
"\t\t If this flag is enabled, the isosurface extraction returns polygons\n" );
245 printf(
"\t\t rather than triangles.\n" );
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" );
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" );
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" );
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" );
263 printf(
"\t[--%s]\n" , Dirichlet.name);
264 printf(
"\t\t If this flag is enabled, Dirichlet boundary constraints are used for reconstruction.\n" );
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" );
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" );
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" );
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" );
279 printf(
"\t[--%s]\n" , NoComments.name );
280 printf(
"\t\t If this flag is enabled, the output file will not include comments.\n" );
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" );
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" );
293 if( fscanf( fp ,
" %c %c %c " , &c[0] , &c[1] , &c[2] )!=3 ) fprintf( stderr ,
"[ERROR] Failed to read color\n" ) , exit( 0 );
307 bool ValidPlyColorProperties(
const bool* props ){
return ( props[0] || props[3] ) && ( props[1] || props[4] ) && ( props[2] || props[5] ); }
309 template<
class Real ,
int Degree ,
class Vertex >
310 int _Execute(
int argc ,
char* argv[] )
314 std::vector< char* > comments;
316 if( Verbose.set ) echoStdout=1;
321 FILE* fp = fopen( XForm.value ,
"r" );
324 fprintf( stderr ,
"[WARNING] Could not read x-form from: %s\n" , XForm.value );
329 for(
int i=0 ; i<4 ; i++ )
for(
int j=0 ; j<4 ; j++ )
332 if( fscanf( fp ,
" %f " , &f )!=1 ) fprintf( stderr ,
"[ERROR] Execute: Failed to read xform\n" ) , exit( 0 );
333 xForm(i,j) = (Real)f;
341 DumpOutput2( comments ,
"Running Screened Poisson Reconstruction (Version 8.0)\n" );
343 for(
int i=0 ; i<paramNum ; i++ )
347 if( strlen( str ) ) DumpOutput2( comments ,
"\t--%s %s\n" ,
params[i]->
name , str );
348 else DumpOutput2( comments ,
"\t--%s\n" ,
params[i]->
name );
362 if( !MaxSolveDepth.set ) MaxSolveDepth.value = Depth.value;
367 int kernelDepth = KernelDepth.set ? KernelDepth.value : Depth.value-2;
368 if( kernelDepth>Depth.value )
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;
374 double maxMemoryUsage;
385 if( Color.set && Color.value>0 )
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 );
397 int idx = colorData->index( n );
398 if( idx>=0 ) colorData->data[idx] *= (Real)pow( Color.value , n->depth() );
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 );
411 if( !Density.set )
delete densityWeights , densityWeights =
NULL;
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 );
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() );
432 DumpOutput2( comments ,
"# Constraints set in: %9.1f (s), %9.1f (MB)\n" ,
Time()-t , tree.
maxMemoryUsage );
434 maxMemoryUsage = std::max< double >( maxMemoryUsage , tree.
maxMemoryUsage );
441 DumpOutput2( comments ,
"# Linear system solved in: %9.1f (s), %9.1f (MB)\n" ,
Time()-t , tree.
maxMemoryUsage );
443 maxMemoryUsage = std::max< double >( maxMemoryUsage , tree.
maxMemoryUsage );
449 isoValue = tree.
GetIsoValue( solution , *nodeWeights );
451 DumpOutput(
"Got average in: %f\n" ,
Time()-t );
452 DumpOutput(
"Iso-Value: %e\n" , isoValue );
457 FILE* fp = fopen( VoxelGrid.value ,
"wb" );
458 if( !fp ) fprintf( stderr ,
"Failed to open voxel file for writing: %s\n" , VoxelGrid.value );
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 );
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 );
475 DumpOutput(
"Got voxel grid in: %f\n" ,
Time()-t );
481 tree.template GetMCIsoSurface< Degree , WEIGHT_DEGREE , DATA_DEGREE >( densityWeights , colorData , solution , isoValue , mesh , !LinearFit.set , !NonManifold.set ,
PolygonMesh.
set );
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 );
500 if( colorData ){
delete colorData ; colorData =
NULL; }
505 inline double to_seconds(
const FILETIME& ft )
507 const double low_to_sec=100e-9;
508 const double high_to_sec=low_to_sec*4294967296.0;
509 return ft.dwLowDateTime*low_to_sec+ft.dwHighDateTime*high_to_sec;
513 template<
class Real ,
class Vertex >
514 int Execute(
int argc ,
char* argv[] )
516 switch( Degree.value )
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 );
523 fprintf( stderr ,
"[ERROR] Only B-Splines of degree 1 - 4 are supported" );
532 #if defined(_WIN32) && defined(MAX_MEMORY_GB)
535 SIZE_T peakMemory = 1;
538 printf(
"Limiting memory usage to %.2f GB\n" ,
float( peakMemory>>30 ) );
539 HANDLE h = CreateJobObject(
NULL ,
NULL );
540 AssignProcessToJobObject( h , GetCurrentProcess() );
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" );
554 if( Double.set ) Execute< double , PlyColorAndValueVertex< float > >( argc , argv );
555 else Execute< float , PlyColorAndValueVertex< float > >( argc , argv );
557 if( Double.set ) Execute< double , PlyValueVertex< float > >( argc , argv );
558 else Execute< float , PlyValueVertex< float > >( argc , argv );
561 if( Double.set ) Execute< double , PlyColorVertex< float > >( argc , argv );
562 else Execute< float , PlyColorVertex< float > >( argc , argv );
564 if( Double.set ) Execute< double , PlyVertex< float > >( argc , argv );
565 else Execute< float , PlyVertex< float > >( argc , argv );
567 if( Performance.set )
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 );
#define DeletePointer(...)
void cmdLineParse(int argc, char **argv, int num, cmdLineReadable **readable, int dumpError)
char * GetFileExtension(char *fileName)
filament::Texture::InternalFormat format
int omp_get_num_procs(void)
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())
#define PLY_BINARY_NATIVE
int PoissonRecon(int argc, char *argv[])
#define DEFAULT_FULL_DEPTH
cmdLineReadable * params[]
cmdLineReadable PolygonMesh("polygonMesh")
int outOfCorePointCount(void)
std::vector< Vertex > inCorePoints
static size_t Usage(void)
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
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)