49 #include <OpenMesh/Core/IO/MeshIO.hh> 50 #include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh> 51 #include <OpenMesh/Tools/Utils/getopt.h> 58 #include <OpenMesh/Tools/Decimater/ModIndependentSetsT.hh> 82 typedef size_t level_t;
89 max_level_(0), n_roots_(0), n_vertices_(0)
91 BaseModQ::mesh().add_property( level_ );
98 BaseModQ::mesh().remove_property( level_ );
103 static level_t calc_bits_for_roots(
size_t _n_vertices )
105 return level_t(std::ceil(std::log((
double)_n_vertices)*inv_log2_));
112 BaseModQ::initialize();
113 n_vertices_ = BaseModQ::mesh().n_vertices();
114 n_roots_ = calc_bits_for_roots(n_vertices_);
119 level_t newlevel = std::max( BaseModQ::mesh().property( level_, _ci.
v0 ),
120 BaseModQ::mesh().property( level_, _ci.
v1 ) )+1;
121 level_t newroots = calc_bits_for_roots(n_vertices_-1);
123 if ( (newroots + newlevel) < 32 )
125 double err = BaseModQ::collapse_priority( _ci );
127 if (err!=BaseModQ::ILLEGAL_COLLAPSE)
129 return float(newlevel + err/(err+1.0));
134 return BaseModQ::ILLEGAL_COLLAPSE;
140 BaseModQ::postprocess_collapse( _ci );
142 BaseModQ::mesh().property( level_, _ci.
v1 ) =
143 std::max( BaseModQ::mesh().property( level_, _ci.
v0 ),
144 BaseModQ::mesh().property( level_, _ci.
v1 ) ) + 1;
146 max_level_ = std::max( BaseModQ::mesh().property( level_, _ci.
v1 ), max_level_ );
147 n_roots_ = calc_bits_for_roots(--n_vertices_);
152 level_t max_level(
void)
const {
return max_level_; }
153 level_t bits_for_roots(
void)
const {
return n_roots_; }
166 static const double inv_log2_;
170 template <
typename D>
180 replace_extension( std::string& _s,
const std::string& _e )
182 std::string::size_type
dot = _s.rfind(
".");
183 if (dot == std::string::npos)
186 { _s = _s.substr(0,dot+1)+_e; }
192 basename(
const std::string& _f)
194 std::string::size_type
dot = _f.rfind(
"/");
195 if (dot == std::string::npos)
197 return _f.substr(dot+1, _f.length()-(dot+1));
202 void usage_and_exit(
int xcode)
207 <<
"Usage: mkbalancedpm [-n <decimation-steps>] [-o <output>] [-N <max. normal deviation>]" 210 <<
" Create a balanced progressive mesh from an input file.\n" 211 <<
" By default decimate as much as possible and write the result\n" 212 <<
" to <input>.pm\n" 216 <<
" -n <decimation-steps>\n" 217 <<
"\tDetermines the maximum number of decimation steps.\n" 218 <<
"\tDecimate as much as possible if the value is equal zero\n" 219 <<
"\tDefault value: 0\n" 222 <<
"\tWrite resulting progressive mesh to the file named <output>\n" 224 <<
" -N <max. normal Deviation>\n" 225 <<
"\tEnable Normal Flipping\n" 228 <<
"\tEnable Independent Sets\n" 235 int main(
int argc,
char **argv)
240 std::string ifname, ofname;
242 float normalDev=90.0;
243 bool enable_modNF =
false;
244 bool enable_modIS =
false;
246 while ((c=getopt(argc, argv,
"n:o:N:Ih"))!=-1)
250 case 'o': ofname = optarg;
break;
251 case 'n': { std::stringstream str; str << optarg; str >> decstep; }
break;
252 case 'N': { enable_modNF =
true;
253 std::stringstream str; str << optarg; str >> normalDev; }
break;
254 case 'I': enable_modIS =
true;
break;
266 ifname = argv[optind];
270 std::cerr <<
"Error loading mesh from file '" << ifname <<
"'!\n";
277 DecimaterProgMesh decimater(mesh);
279 ModProgMesh::Handle modPM;
280 ModBalancer::Handle modB;
281 ModNormalFlipping::Handle modNF;
282 ModIndependentSets::Handle modIS;
285 decimater.add(modPM);
286 std::cout <<
"w/ progressive mesh module\n";
288 std::cout <<
"w/ balancer module\n";
292 decimater.add(modNF);
293 decimater.module(modNF).set_max_normal_deviation(normalDev);
295 std::cout <<
"w/" << (modNF.is_valid() ?
' ' :
'o')
296 <<
" normal flipping module (max. normal deviation: " << normalDev <<
")\n";
299 decimater.add(modIS);
300 std::cout <<
"w/" << (modIS.is_valid() ?
' ' :
'o')
301 <<
" independent sets module\n";
303 std::cout <<
"Initialize decimater\n";
305 if ( !decimater.initialize() )
307 std::cerr <<
" Initialization failed!\n";
311 std::cout <<
" done [" << t.
as_string() <<
"]\n";
315 size_t nv = mesh.n_vertices();
317 std::cout <<
"Begin decimation (#V " << nv <<
")\n";
321 if (modIS.is_valid())
323 Mesh::VertexIter v_it;
326 for (f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it)
327 if ( !mesh.status(*f_it).deleted() )
328 mesh.update_normal(*f_it);
330 for (v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it)
331 if ( !mesh.status(*v_it).deleted() )
333 mesh.status(*v_it).set_locked(
false);
334 mesh.update_normal(*v_it);
339 rc = decimater.decimate(decstep);
342 << (nv-=rc) <<
" (-" << rc <<
") " << std::flush;
347 std::cout <<
"\n done [" << t.
as_string() <<
"]\n";
349 std::cout <<
"Bits for <tree-id, node-id>: <" 350 << decimater.module(modB).bits_for_roots() <<
", " 351 << decimater.module(modB).max_level() <<
">" 354 std::cout <<
"Maximum level reached: " 355 << decimater.module(modB).max_level() << std::endl;
357 if (ofname ==
"." || ofname ==
".." )
358 ofname +=
"/" + basename(ifname);
359 std::string pmfname = ofname.empty() ? ifname : ofname;
360 replace_extension(pmfname,
"pm");
362 std::cout <<
"Write progressive mesh data to file " 363 << pmfname << std::endl;
364 decimater.module(modPM).write( pmfname );
void initialize(void)
Initalize the module and prepare the mesh for decimation.
void reset(void)
Reset the timer.
#define DECIMATING_MODULE(Classname, MeshT, Name)
std::string as_string(Format format=Automatic)
void postprocess_collapse(const CollapseInfo &_ci)
post-process halfedge collapse (accumulate quadrics)
virtual float collapse_priority(const CollapseInfo &_ci)
osg::Vec3f::ValueType dot(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
ModBalancerT(D &_dec)
Constructor.
virtual ~ModBalancerT()
Destructor.
Mesh::VertexHandle v0
Vertex to be removed.
void start(void)
Start measurement.
void set_binary(bool _b)
hide this method
bool read_mesh(Mesh &_mesh, const std::string &_filename)
Read a mesh from file _filename.
void cont(void)
Continue measurement.
Mesh::VertexHandle v1
Remaining vertex.
Mesh decimation module computing collapse priority based on error quadrics.
void stop(void)
Stop measurement.