54 #include <OpenMesh/Core/IO/MeshIO.hh>
55 #include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
56 #include <OpenMesh/Tools/Utils/getopt.h>
63 #include <OpenMesh/Tools/Decimater/ModIndependentSetsT.hh>
87 typedef size_t level_t;
94 max_level_(0), n_roots_(0), n_vertices_(0)
96 BaseModQ::mesh().add_property( level_ );
103 BaseModQ::mesh().remove_property( level_ );
108 static level_t calc_bits_for_roots(
size_t _n_vertices )
110 return level_t(std::ceil(std::log((
double)_n_vertices)*inv_log2_));
117 BaseModQ::initialize();
118 n_vertices_ = BaseModQ::mesh().n_vertices();
119 n_roots_ = calc_bits_for_roots(n_vertices_);
124 level_t newlevel = std::max( BaseModQ::mesh().property( level_, _ci.
v0 ),
125 BaseModQ::mesh().property( level_, _ci.
v1 ) )+1;
126 level_t newroots = calc_bits_for_roots(n_vertices_-1);
128 if ( (newroots + newlevel) < 32 )
130 double err = BaseModQ::collapse_priority( _ci );
132 if (err!=BaseModQ::ILLEGAL_COLLAPSE)
134 return float(newlevel + err/(err+1.0));
139 return BaseModQ::ILLEGAL_COLLAPSE;
145 BaseModQ::postprocess_collapse( _ci );
147 BaseModQ::mesh().property( level_, _ci.
v1 ) =
148 std::max( BaseModQ::mesh().property( level_, _ci.
v0 ),
149 BaseModQ::mesh().property( level_, _ci.
v1 ) ) + 1;
151 max_level_ = std::max( BaseModQ::mesh().property( level_, _ci.
v1 ), max_level_ );
152 n_roots_ = calc_bits_for_roots(--n_vertices_);
157 level_t max_level(
void)
const {
return max_level_; }
158 level_t bits_for_roots(
void)
const {
return n_roots_; }
171 static const double inv_log2_;
175 template <
typename D>
185 replace_extension( std::string& _s,
const std::string& _e )
187 std::string::size_type
dot = _s.rfind(
".");
188 if (dot == std::string::npos)
191 { _s = _s.substr(0,dot+1)+_e; }
197 basename(
const std::string& _f)
199 std::string::size_type dot = _f.rfind(
"/");
200 if (dot == std::string::npos)
202 return _f.substr(dot+1, _f.length()-(dot+1));
207 void usage_and_exit(
int xcode)
212 <<
"Usage: mkbalancedpm [-n <decimation-steps>] [-o <output>] [-N <max. normal deviation>]"
215 <<
" Create a balanced progressive mesh from an input file.\n"
216 <<
" By default decimate as much as possible and write the result\n"
217 <<
" to <input>.pm\n"
221 <<
" -n <decimation-steps>\n"
222 <<
"\tDetermines the maximum number of decimation steps.\n"
223 <<
"\tDecimate as much as possible if the value is equal zero\n"
224 <<
"\tDefault value: 0\n"
227 <<
"\tWrite resulting progressive mesh to the file named <output>\n"
229 <<
" -N <max. normal Deviation>\n"
230 <<
"\tEnable Normal Flipping\n"
233 <<
"\tEnable Independent Sets\n"
240 int main(
int argc,
char **argv)
245 std::string ifname, ofname;
247 float normalDev=90.0;
248 bool enable_modNF =
false;
249 bool enable_modIS =
false;
251 while ((c=getopt(argc, argv,
"n:o:N:Ih"))!=-1)
255 case 'o': ofname = optarg;
break;
256 case 'n': { std::stringstream str; str << optarg; str >> decstep; }
break;
257 case 'N': { enable_modNF =
true;
258 std::stringstream str; str << optarg; str >> normalDev; }
break;
259 case 'I': enable_modIS =
true;
break;
270 ifname = argv[optind];
274 std::cerr <<
"Error loading mesh from file '" << ifname <<
"'!\n";
281 DecimaterProgMesh decimater(mesh);
283 ModProgMesh::Handle modPM;
284 ModBalancer::Handle modB;
285 ModNormalFlipping::Handle modNF;
286 ModIndependentSets::Handle modIS;
289 decimater.add(modPM);
290 std::cout <<
"w/ progressive mesh module\n";
292 std::cout <<
"w/ balancer module\n";
296 decimater.add(modNF);
297 decimater.module(modNF).set_max_normal_deviation(normalDev);
299 std::cout <<
"w/" << (modNF.is_valid() ?
' ' :
'o')
300 <<
" normal flipping module (max. normal deviation: " << normalDev <<
")\n";
303 decimater.add(modIS);
304 std::cout <<
"w/" << (modIS.is_valid() ?
' ' :
'o')
305 <<
" independent sets module\n";
307 std::cout <<
"Initialize decimater\n";
309 if ( !decimater.initialize() )
311 std::cerr <<
" Initialization failed!\n";
315 std::cout <<
" done [" << t.
as_string() <<
"]\n";
319 size_t nv = mesh.n_vertices();
321 std::cout <<
"Begin decimation (#V " << nv <<
")\n";
325 if (modIS.is_valid())
327 Mesh::VertexIter v_it;
330 for (f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it)
331 if ( !mesh.status(*f_it).deleted() )
334 for (v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it)
335 if ( !mesh.status(*v_it).deleted() )
337 mesh.status(*v_it).set_locked(
false);
343 rc = decimater.decimate(decstep);
346 << (nv-=rc) <<
" (-" << rc <<
") " << std::flush;
351 std::cout <<
"\n done [" << t.
as_string() <<
"]\n";
353 std::cout <<
"Bits for <tree-id, node-id>: <"
354 << decimater.module(modB).bits_for_roots() <<
", "
355 << decimater.module(modB).max_level() <<
">"
358 std::cout <<
"Maximum level reached: "
359 << decimater.module(modB).max_level() << std::endl;
361 if (ofname ==
"." || ofname ==
".." )
362 ofname +=
"/" + basename(ifname);
363 std::string pmfname = ofname.empty() ? ifname : ofname;
364 replace_extension(pmfname,
"pm");
366 std::cout <<
"Write progressive mesh data to file "
367 << pmfname << std::endl;
368 decimater.module(modPM).write( pmfname );
Mesh::VertexHandle v1
Remaining vertex.
bool read_mesh(Mesh &_mesh, const std::string &_filename)
Read a mesh from file _filename.
#define DECIMATING_MODULE(Classname, MeshT, Name)
void stop(void)
Stop measurement.
Mesh::VertexHandle v0
Vertex to be removed.
void update_normal(FaceHandle _fh)
Update normal for face _fh.
Mesh decimation module computing collapse priority based on error quadrics.
void initialize(void)
Initalize the module and prepare the mesh for decimation.
virtual float collapse_priority(const CollapseInfo &_ci)
std::string as_string(Format format=Automatic)
virtual ~ModBalancerT()
Destructor.
void reset(void)
Reset the timer.
void set_binary(bool _b)
hide this method
ModBalancerT(D &_dec)
Constructor.
void start(void)
Start measurement.
osg::Vec3f::ValueType dot(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
void postprocess_collapse(const CollapseInfo &_ci)
post-process halfedge collapse (accumulate quadrics)
void cont(void)
Continue measurement.