1 /*
2  *  plymc_main.cpp
3  *  filter_plymc
4  *
5  *  Created by Paolo Cignoni on 10/23/09.
6  *  Copyright 2009 ISTI - CNR. All rights reserved.
7  *
8  */
9 
10 #include <vcg/complex/algorithms/create/plymc/plymc.h>
11 #include "simplemeshprovider.h"
12 #define _PLYMC_VER "4.0"
13 
14 using namespace std;
15 using namespace vcg;
16 
17 
18 
19 string MYbasename = "plymcout";
20 string VolumeBaseName;
21 string subtag=""; // la stringa da appendere al nome di file per generare i nomi di file relativi a vari sottopezzi
22 string alnfile;
23 
24 /************ Command Line Parameters *******/
25 
26 int saveMask=vcg::tri::io::Mask::IOM_ALL;
usage()27 void usage()
28 {
29   printf(
30       "\nUsage:\n"
31       "         plymc [options] filein.ply [filein.ply...]\n"
32       "         plymc [options] filein.aln \n"
33       "Options:  (no leading space before numeric values!) \n"
34       " -oname  Set the base output name (default plymcout, without 'ply' extension)\n"
35       " -vname  Enable the saving of the final volume with the specified filename\n"
36       " -C##    Set numbers mesh that can be cached (default: 6)\n"
37       " -c##    Set numbers of k cells (default: 10000)\n"
38       " -V#     Set the required voxel size (override -c)\n"
39       " -s...   Compute only a subvolume (specify 6 integers) \n"
40       " -S...   Compute all the subvolumes of a partition (specify 3 int) \n"
41       " -X...   Compute a range of the the subvolumes of a partition (specify 9 int)\n"
42       " -M      Apply a 'safe' simplification step that removes only the unecessary triangles\n"
43       " -w#     Set distance field Expansion factor in voxel (default 3)\n"
44       " -W#     Set distance field Exp. as an absolute dist (override -w)\n"
45       " -a#     Set angle threshold for distance field expansion (default 30)\n"
46       " -f#     Set the fill threshold (default 12: all voxel having less \n"
47       "         than 12 adjacent are not automaticall filled)\n"
48       " -L#     Set Number of smoothing passes to be done after merging of all meshes\n"
49       " -R#     Set Number of Refill passes to be done after merging of all meshes\n"
50       " -l#     Make a single smoothing step after each expansion\n"
51       " -G#     Disable Geodesic Quality\n"
52       " -F#     Use per vertex quality defined in plyfile (geodesic is disabled)\n"
53       " -O#     Set an Offset (<0!) threshold and build a double surface\n"
54       " -q#     Set Quality threshold for smoothing. Only whose distance (in voxel)\n"
55       "         is lower than the specified one are smoothed (default 3 voxel)\n"
56       " -Q#     Same of above but expressed in absolute units.\n"
57       " -p       use vertex splatting instead face rasterizing\n"
58       " -d#     set <n> as verbose level (default 0)\n"
59       " -D#     save <n> debug slices during processing\n"
60 
61       "\nNotes:\n\n"
62       "The Quality threshold can be expressed in voxel unit or in absolute units.\n"
63       "It represents the geodetic distance from the mesh border.\n"
64       "I.e. -q3 means that all voxels that are within 3voxel from the mesh border\n"
65       "are smoothed.\n\n"
66 
67       "A partition in the working volume is defined using 3 integers, that \n"
68       "specify the subdivision along the three axis.\n"
69       "To automatically compute ALL subvolumes of a given subdivision use '-S' \n"
70       "-S 1 1 1 default no subdivision at all\n"
71       "-S 2 2 2 compute all the octant of a octree-like subdivision\n"
72       "-S 1 1 4 compute four Z-slices\n\n"
73 
74       "To work only on a SINGLE subvolume of the partition you have to specify \n"
75       "six integers: the first three ints specify the subdivision along the\n"
76       "three axis and the last three ones which subvolume you desire.\n"
77       "the parameter to be used is '-s' \n"
78       "-s 1 1 1 0 0 0 default no subdivision at all\n"
79       "-s 1 1 3 0 0 1 make three Z-slices and take the middle one \n"
80       "-s 2 2 2 1 1 1 the last octant in a octree-like subdivision\n\n"
81 
82       "To START FROM a specific subvolume of the partition you have to specify \n"
83       "six integers: the first three ints specify the subdivision along the\n"
84       "three axis and the last three ones which subvolume you want to start\n"
85       "the process will go on using lexicographic order. Subvolumes are ordered\n"
86       "by Z, then by Y, then by X\n"
87       "The parameter to be used is '-K' \n"
88       "-K 4 4 4 0 0 0 a partition of 64 blocks, starting from the first one\n"
89       "-K 4 4 4 1 0 3 a partition of 64 blocks, starting from block 19 (index 1 0 3)\n\n"
90 
91       "To work only on a specific subvolume range of the partition you have \n"
92       "to specify nine integers: the first three ints specify the subdivision\n"
93       "along the three axis and, the next three which is the starting subvolume\n"
94       "and the last three which is the last subvolume to be computed.\n"
95       "the process will compute all blocks with x,y,z index included in the interval\n"
96       "specified: Xstart<=X<=Xend Ystart<=Y<=Yend Zstart<=Z<=Zend\n"
97       "-X 3 3 3 0 0 0 2 2 2 three subdivision on each axis, all subvolumes\n"
98       "-X 2 2 2 1 0 0 1 1 1 three subdivision on each axis, only the 'right' part\n\n"
99       );
100   exit(-1);
101 }
102 
103 
104 
main(int argc,char * argv[])105 int main(int argc, char *argv[])
106 {
107 
108   Histogram<float> h;
109   tri::PlyMC<SMesh,SimpleMeshProvider<SMesh> > pmc;
110   tri::PlyMC<SMesh,SimpleMeshProvider<SMesh> >::Parameter &p = pmc.p;
111 
112 
113   // This line is required to be sure that the decimal separatore is ALWAYS the . and not the ,
114   // see the comment at the beginning of the file
115   setlocale(LC_ALL, "En_US");
116 
117   printf(   "\n                  PlyMC " _PLYMC_VER " (" __DATE__ ")\n"
118 	    "   Copyright 2002-2016 Visual Computing Group I.S.T.I. C.N.R.\n"
119 	    "             Paolo Cignoni (p.cignoni@isti.cnr.it)\n\n");
120   //// Parameters
121   int i=1;
122   if(argc<2) usage();
123   while(argv[i][0]=='-')
124   {
125     switch(argv[i][1])
126     {
127 	case 'o' :  p.basename=argv[i]+2;printf("Setting Basename  to %s\n",MYbasename.c_str());break;
128 	case 'C' :  pmc.MP.setCacheSize(atoi(argv[i]+2));printf("Setting MaxSize of MeshCache to %i\n",atoi(argv[i]+2)); break;
129 	case 'c' :  p.NCell   =atoi(argv[i]+2);printf("Setting NCell  to %i\n",p.NCell); break;
130 	case 'v' :  p.SaveVolumeFlag=true; VolumeBaseName=argv[i]+2; printf("Saving Volume enabled: volume Basename  to %s\n",VolumeBaseName.c_str());break;
131 	case 'V' :  p.VoxSize =atof(argv[i]+2);printf("Setting VoxSize  to %f; overridden NCell\n",p.VoxSize);p.NCell=0;break;
132 	case 'w' :  p.WideNum =atoi(argv[i]+2);printf("Setting WideNum  to %i\n",p.WideNum);break;
133 	case 'W' :  p.WideSize=atof(argv[i]+2);printf("Setting WideSize to %f;overridden WideNum\n",p.WideSize);break;
134 	case 'L' :  p.SmoothNum =atoi(argv[i]+2);printf("Setting Laplacian SmoothNum to %i\n",p.SmoothNum);break;
135 	case 'R' :  p.RefillNum =atoi(argv[i]+2);printf("Setting Refilling Num to %i\n",p.RefillNum);break;
136 	case 'q' :  p.QualitySmoothVox=atof(argv[i]+2);printf("Setting QualitySmoothThr  to %f; \n",p.QualitySmoothVox);break;
137     case 'Q' :  p.QualitySmoothAbs=atof(argv[i]+2);printf("Setting QualitySmoothAbsolute to %f; it will override the default %f voxel value\n",p.QualitySmoothAbs,p.QualitySmoothVox);break;
138 	case 'l' :  p.IntraSmoothFlag=true; printf("Setting Laplacian Smooth after expansion \n");break;
139 	case 'G' :  p.GeodesicQualityFlag=false; printf("Disabling Geodesic Quality\n");break;
140 	case 'F' :  p.PLYFileQualityFlag=true; p.GeodesicQualityFlag=false; printf("Enabling PlyFile (and disabling Geodesic) Quality\n");break;
141 	case 'f' :  p.FillThr=atoi(argv[i]+2);printf("Setting Fill Threshold to %i\n",p.FillThr);break;
142 	case 'a' :  p.ExpAngleDeg=atoi(argv[i]+2);printf("Setting Expanding Angle Threshold to %f Degree\n",p.ExpAngleDeg);break;
143 	case 'O' :  p.OffsetThr=atof(argv[i]+2);printf("Setting Offset Threshold to %f \n",p.OffsetThr);p.OffsetFlag=true;break;
144 	case 's' :
145 	  p.IDiv[0]=atoi(argv[++i]); p.IDiv[1]=atoi(argv[++i]); p.IDiv[2]=atoi(argv[++i]);
146 	  p.IPosS[0]=atoi(argv[++i]);p.IPosS[1]=atoi(argv[++i]);p.IPosS[2]=atoi(argv[++i]);
147 	  p.IPosE[0]=p.IPosS[0]; p.IPosE[1]=p.IPosS[1]; p.IPosE[2]=p.IPosS[2];
148 	  if((p.IPosS[0]>=p.IDiv[0]) || (p.IPosS[1]>=p.IDiv[1]) || (p.IPosS[2]>=p.IDiv[2]))
149 	  {
150 	    printf("the subvolume you have requested is invalid (out of bounds)");
151 	    exit(-1);
152 	  }
153 	  printf("Computing ONLY subvolume [%i,%i,%i] on a %ix%ix%i\n",p.IPosS[0],p.IPosS[1],p.IPosS[2],p.IDiv[0],p.IDiv[1],p.IDiv[2]);
154 	  break;
155 	case 'S' :
156 	  p.IDiv[0]=atoi(argv[++i]);p.IDiv[1]=atoi(argv[++i]);p.IDiv[2]=atoi(argv[++i]);
157 	  p.IPosS=Point3i(0,0,0);
158 	  p.IPosE[0]=p.IDiv[0]-1; p.IPosE[1]=p.IDiv[1]-1; p.IPosE[2]=p.IDiv[2]-1;
159 	  printf("Autocomputing ALL subvolumes on a %ix%ix%i\n",p.IDiv[0],p.IDiv[1],p.IDiv[2]);
160 	  break;
161 	case 'K' :
162 	  p.IDiv[0]=atoi(argv[++i]); p.IDiv[1]=atoi(argv[++i]);p.IDiv[2]=atoi(argv[++i]);
163 	  p.IPosB[0]=atoi(argv[++i]);p.IPosB[1]=atoi(argv[++i]);p.IPosB[2]=atoi(argv[++i]);
164 	  p.IPosS=Point3i(0,0,0);
165 	  p.IPosE[0]=p.IDiv[0]-1; p.IPosE[1]=p.IDiv[1]-1; p.IPosE[2]=p.IDiv[2]-1;
166 	  if((p.IPosB[0]>=p.IDiv[0]) || (p.IPosB[1]>=p.IDiv[1]) || (p.IPosB[2]>=p.IDiv[2]))
167 	  {
168 	    printf("the start subvolume you have requested is invalid (out of bounds)");
169 	    exit(-1);
170 	  }
171 	  printf("Autocomputing ALL subvolumes FROM [%i,%i,%i] on a %ix%ix%i\n",p.IPosB[0],p.IPosB[1],p.IPosB[2],p.IDiv[0],p.IDiv[1],p.IDiv[2]);
172 	  break;
173 	case 'X' :
174 	  p.IDiv[0]=atoi(argv[++i]); p.IDiv[1]=atoi(argv[++i]);p.IDiv[2]=atoi(argv[++i]);
175 	  p.IPosS[0]=atoi(argv[++i]);p.IPosS[1]=atoi(argv[++i]);p.IPosS[2]=atoi(argv[++i]);
176 	  p.IPosE[0]=atoi(argv[++i]);p.IPosE[1]=atoi(argv[++i]);p.IPosE[2]=atoi(argv[++i]);
177 	  // test if the interval is ok
178 	  int Istart,Iend;
179 	  Istart = p.IPosS[2] + (p.IPosS[1]*p.IDiv[2]) + (p.IPosS[0]*p.IDiv[2]*p.IDiv[1]);
180 	  Iend   = p.IPosE[2] + (p.IPosE[1]*p.IDiv[2]) + (p.IPosE[0]*p.IDiv[2]*p.IDiv[1]);
181 	  if((Iend-Istart)<=0)
182 	  {
183 	    printf("the range you have requested is invalid (reversed or empty)");
184 	    exit(-1);
185 	  }
186 	  if((p.IPosS[0]>=p.IDiv[0]) || (p.IPosS[1]>=p.IDiv[1]) || (p.IPosS[2]>=p.IDiv[2]) ||
187 	     (p.IPosE[0]>=p.IDiv[0]) || (p.IPosE[1]>=p.IDiv[1]) || (p.IPosE[2]>=p.IDiv[2]))
188 	  {
189 	    printf("the subvolume you have requested is invalid (out of bounds)");
190 	    exit(-1);
191 	  }
192 	  printf("Autocomputing subvolumes FROM [%i,%i,%i] TO [%i,%i,%i] on a %ix%ix%i\n",p.IPosS[0],p.IPosS[1],p.IPosS[2],p.IPosE[0],p.IPosE[1],p.IPosE[2],p.IDiv[0],p.IDiv[1],p.IDiv[2]);
193 	  break;
194 	  //        case 'B' :	p.SafeBorder =atoi(argv[i]+2);printf("Setting SafeBorder among blocks to %i*%i (default 1)\n",p.SafeBorder,Volume<Voxelf>::BLOCKSIDE());break;
195 	case 'p' :	p.VertSplatFlag =true; printf("Enabling VertexSplatting instead of face rasterization\n");break;
196 	case 'd' : p.VerboseLevel=atoi(argv[i]+2);printf("Enabling VerboseLevel= %i )\n",p.VerboseLevel);break;
197   case 'D' : p.VerboseLevel=1; p.SliceNum=atoi(argv[i]+2);printf("Enabling Debug Volume saving of %i slices (VerboseLevel=1)\n",p.SliceNum);break;
198 	case 'M' :	p.SimplificationFlag =true; printf("Enabling PostReconstruction simplification\n"); break;
199 		default : {printf("Error unable to parse option '%s'\n",argv[i]); exit(0);}
200     }
201     ++i;
202   }
203 
204 
205 
206   Matrix44f Identity;
207   Identity.SetIdentity();
208   string alnfile;
209   while(i<argc)
210   {
211     if(strcmp(strrchr(argv[i],'.'),".aln")==0)
212       pmc.MP.openALN(argv[i]);
213     else
214       pmc.MP.AddSingleMesh(argv[i]);
215     ++i;
216   }
217 
218   if(pmc.MP.size()==0) usage();
219   printf("End Parsing\n\n");
220   pmc.Process();
221 
222   return 0;
223 }
224