Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mconvert.cc
1 /* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openmesh.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenMesh. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 * ========================================================================= */
41
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $Date$ *
46 * *
47 \*===========================================================================*/
48
49 #include <iostream>
50 #include <iterator>
51 #include <fstream>
52 #include <string>
53 //
54 #include <OpenMesh/Core/IO/MeshIO.hh>
55 #include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
56 #include <OpenMesh/Core/Mesh/Attributes.hh>
57 #include <OpenMesh/Tools/Utils/Timer.hh>
58 #include <OpenMesh/Tools/Utils/getopt.h>
59
60
61 struct MyTraits : public OpenMesh::DefaultTraits
62 {
63 VertexAttributes ( OpenMesh::Attributes::Normal |
64 OpenMesh::Attributes::Color |
65 OpenMesh::Attributes::TexCoord2D );
66 HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );
67 FaceAttributes ( OpenMesh::Attributes::Normal |
68 OpenMesh::Attributes::Color );
69 };
70
71
72 typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits> MyMesh;
73
74 void usage_and_exit(int xcode)
75 {
76 using std::cout;
77 using std::endl;
78
79 cout << "\nUsage: mconvert [option] <input> [<output>]\n\n";
80 cout << " Convert from one 3D geometry format to another.\n"
81 << " Or simply display some information about the object\n"
82 << " stored in <input>.\n"
83 << endl;
84 cout << "Options:\n"
85 << endl;
86 cout << " -b\tUse binary mode if supported by target format.\n" << endl;
87 cout << " -l\tStore least significant bit first (LSB, little endian).\n" << endl;
88 cout << " -m\tStore most significant bit first (MSB, big endian).\n" << endl;
89 cout << " -s\tSwap byte order.\n" << endl;
90 cout << " -B\tUse binary mode if supported by source format.\n" << endl;
91 cout << " -S\tSwap byte order of input data.\n" << endl;
92 cout << " -c\tCopy vertex color if provided by input.\n" << endl;
93 cout << " -d\tCopy face color if provided by input.\n" << endl;
94 cout << " -C\tTranslate object in its center-of-gravity.\n" << endl;
95 cout << " -n\tCopy vertex normals if provided by input. Else compute normals.\n" << endl;
96 cout << " -N\tReverse normal directions.\n" << endl;
97 cout << " -t\tCopy vertex texture coordinates if provided by input file.\n" << endl;
98 cout << " -T \"x y z\"\tTranslate object by vector (x, y, z)'\"\n"
99 << std::endl;
100 cout << endl;
101
102 exit(xcode);
103 }
104
105 // ----------------------------------------------------------------------------
106
107 template <typename T> struct Option : std::pair< T, bool >
108 {
109 typedef std::pair< T, bool > Base;
110
111 Option()
112 { Base::second = false; }
113
114 bool is_valid() const { return Base::second; }
115 bool is_empty() const { return !Base::second; }
116
117 operator T& () { return Base::first; }
118 operator const T& () const { return Base::first; }
119
120 Option& operator = ( const T& _rhs )
121 { Base::first = _rhs; Base::second=true; return *this; }
122
123 bool operator == ( const T& _rhs ) const
124 { return Base::first == _rhs; }
125
126 bool operator != ( const T& _rhs ) const
127 { return Base::first != _rhs; }
128 };
129
130 template <typename T>
131 std::ostream& operator << (std::ostream& _os, const Option<T>& _opt )
132 {
133 if (_opt.second) _os << _opt.first; else _os << "<null>";
134 return _os;
135 }
136
137 template <typename T>
138 std::istream& operator >> (std::istream& _is, Option<T>& _opt )
139 {
140 _is >> _opt.first; _opt.second = true;
141 return _is;
142 }
143
144 // ----------------------------------------------------------------------------
145
146 int main(int argc, char *argv[] )
147 {
148 // ------------------------------------------------------------ command line
149
150 int c;
151 std::string ifname, ofname;
152 bool rev_normals = false;
153 bool obj_center = false;
154 OpenMesh::IO::Options opt, ropt;
155
156 Option< MyMesh::Point > tvec;
157
158 while ( (c=getopt(argc, argv, "bBcdCi:hlmnNo:sStT:"))!=-1 )
159 {
160 switch(c)
161 {
162 case 'b': opt += OpenMesh::IO::Options::Binary; break;
163 case 'B': ropt += OpenMesh::IO::Options::Binary; break;
164 case 'l': opt += OpenMesh::IO::Options::LSB; break;
165 case 'm': opt += OpenMesh::IO::Options::MSB; break;
166 case 's': opt += OpenMesh::IO::Options::Swap; break;
167 case 'S': ropt += OpenMesh::IO::Options::Swap; break;
168 case 'n': opt += OpenMesh::IO::Options::VertexNormal; break;
169 case 'N': rev_normals = true; break;
170 case 'C': obj_center = true; break;
171 case 'c': opt += OpenMesh::IO::Options::VertexColor; break;
172 case 'd': opt += OpenMesh::IO::Options::FaceColor; break;
173 case 't': opt += OpenMesh::IO::Options::VertexTexCoord; break;
174 case 'T':
175 {
176 std::cout << optarg << std::endl;
177 std::stringstream str; str << optarg;
178 str >> tvec;
179 std::cout << tvec << std::endl;
180 break;
181 }
182 case 'i': ifname = optarg; break;
183 case 'o': ofname = optarg; break;
184 case 'h':
185 usage_and_exit(0);
186 case '?':
187 default:
188 usage_and_exit(1);
189 }
190 }
191
192 if (ifname.empty())
193 {
194 if (optind < argc)
195 ifname = argv[optind++];
196 else
197 usage_and_exit(1);
198 }
199
200 MyMesh mesh;
201 OpenMesh::Utils::Timer timer;
202
203 // ------------------------------------------------------------ read
204
205 std::cout << "reading.." << std::endl;
206 {
207 bool rc;
208 timer.start();
209 rc = OpenMesh::IO::read_mesh( mesh, ifname, ropt );
210 timer.stop();
211 if (rc)
212 std::cout << " read in " << timer.as_string() << std::endl;
213 else
214 {
215 std::cout << " read failed\n" << std::endl;
216 return 1;
217 }
218 timer.reset();
219 }
220
221
222 // ---------------------------------------- some information about input
223 std::cout << (ropt.check(OpenMesh::IO::Options::Binary)
224 ? " source is binary\n"
225 : " source is ascii\n");
226
227 std::cout << " #V " << mesh.n_vertices() << std::endl;
228 std::cout << " #E " << mesh.n_edges() << std::endl;
229 std::cout << " #F " << mesh.n_faces() << std::endl;
230
231 if (ropt.vertex_has_texcoord())
232 std::cout << " has texture coordinates" << std::endl;
233
234 if (ropt.vertex_has_normal())
235 std::cout << " has vertex normals" << std::endl;
236
237 if (ropt.vertex_has_color())
238 std::cout << " has vertex colors" << std::endl;
239
240 if (ropt.face_has_normal())
241 std::cout << " has face normals" << std::endl;
242
243 if (ropt.face_has_color())
244 std::cout << " has face colors" << std::endl;
245
246 //
247 if (ofname.empty())
248 {
249 if ( optind < argc )
250 ofname = argv[optind++];
251 else
252 return 0;
253 }
254
255 // ------------------------------------------------------------ features
256
257 // ---------------------------------------- compute normal feature
258 if ( opt.vertex_has_normal() && !ropt.vertex_has_normal())
259 {
260 std::cout << "compute normals" << std::endl;
261
262 timer.start();
263 mesh.update_face_normals();
264 timer.stop();
265 std::cout << " " << mesh.n_faces()
266 << " face normals in " << timer.as_string() << std::endl;
267 timer.reset();
268
269 timer.start();
270 mesh.update_vertex_normals();
271 timer.stop();
272 std::cout << " " << mesh.n_vertices()
273 << " vertex normals in " << timer.as_string() << std::endl;
274 timer.reset();
275 }
276
277
278 // ---------------------------------------- reverse normal feature
279 if ( rev_normals && ropt.vertex_has_normal() )
280 {
281 std::cout << "reverse normal directions" << std::endl;
282 timer.start();
283 MyMesh::VertexIter vit = mesh.vertices_begin();
284 for (; vit != mesh.vertices_end(); ++vit)
285 mesh.set_normal( *vit, -mesh.normal( *vit ) );
286 timer.stop();
287 std::cout << " " << mesh.n_vertices()
288 << " vertex normals in " << timer.as_string() << std::endl;
289 timer.reset();
290
291 }
292
293
294 // ---------------------------------------- centering feature
295 if ( obj_center )
296 {
297 OpenMesh::Vec3f cog(0,0,0);
298 size_t nv;
299 std::cout << "center object" << std::endl;
300 timer.start();
301 MyMesh::VertexIter vit = mesh.vertices_begin();
302 for (; vit != mesh.vertices_end(); ++vit)
303 cog += mesh.point( *vit );
304 timer.stop();
305 nv = mesh.n_vertices();
306 cog *= 1.0f/mesh.n_vertices();
307 std::cout << " cog = [" << cog << "]'" << std::endl;
308 if (cog.sqrnorm() > 0.8) // actually one should consider the size of object
309 {
310 vit = mesh.vertices_begin();
311 timer.cont();
312 for (; vit != mesh.vertices_end(); ++vit)
313 mesh.set_point( *vit , mesh.point( *vit )-cog );
314 timer.stop();
315 nv += mesh.n_vertices();
316 }
317 else
318 std::cout << " already centered!" << std::endl;
319 std::cout << " visited " << nv
320 << " vertices in " << timer.as_string() << std::endl;
321 timer.reset();
322 }
323
324
325 // ---------------------------------------- translate feature
326 if ( tvec.is_valid() )
327 {
328 std::cout << "Translate object by " << tvec << std::endl;
329
330 timer.start();
331 MyMesh::VertexIter vit = mesh.vertices_begin();
332 for (; vit != mesh.vertices_end(); ++vit)
333 mesh.set_point( *vit , mesh.point( *vit ) + tvec.first );
334 timer.stop();
335 std::cout << " moved " << mesh.n_vertices()
336 << " vertices in " << timer.as_string() << std::endl;
337 }
338
339 // ---------------------------------------- color vertices feature
340 if ( opt.check( OpenMesh::IO::Options::VertexColor ) &&
341 !ropt.check( OpenMesh::IO::Options::VertexColor ) )
342 {
343 std::cout << "Color vertices" << std::endl;
344
345 double d = 256.0/double(mesh.n_vertices());
346 double d2 = d/2.0;
347 double r = 0.0, g = 0.0, b = 255.0;
348 timer.start();
349 MyMesh::VertexIter vit = mesh.vertices_begin();
350 for (; vit != mesh.vertices_end(); ++vit)
351 {
352 mesh.set_color( *vit , MyMesh::Color( std::min((int)(r+0.5),255),
353 std::min((int)(g+0.5),255),
354 std::max((int)(b+0.5),0) ) );
355 r += d;
356 g += d2;
357 b -= d;
358 }
359 timer.stop();
360 std::cout << " colored " << mesh.n_vertices()
361 << " vertices in " << timer.as_string() << std::endl;
362 }
363
364 // ---------------------------------------- color faces feature
365 if ( opt.check( OpenMesh::IO::Options::FaceColor ) &&
366 !ropt.check( OpenMesh::IO::Options::FaceColor ) )
367 {
368 std::cout << "Color faces" << std::endl;
369
370 double d = 256.0/double(mesh.n_faces());
371 double d2 = d/2.0;
372 double r = 0.0, g = 50.0, b = 255.0;
373 timer.start();
374 MyMesh::FaceIter it = mesh.faces_begin();
375 for (; it != mesh.faces_end(); ++it)
376 {
377 mesh.set_color( *it , MyMesh::Color( std::min((int)(r+0.5),255),
378 std::min((int)(g+0.5),255),
379 std::max((int)(b+0.5),0) ) );
380 r += d2;
381 // g += d2;
382 b -= d;
383 }
384 timer.stop();
385 std::cout << " colored " << mesh.n_faces()
386 << " faces in " << timer.as_string() << std::endl;
387 }
388
389 // ------------------------------------------------------------ write
390
391 std::cout << "writing.." << std::endl;
392 {
393 bool rc;
394 timer.start();
395 rc = OpenMesh::IO::write_mesh( mesh, ofname, opt );
396 timer.stop();
397
398 if (!rc)
399 {
400 std::cerr << " error writing mesh!" << std::endl;
401 return 1;
402 }
403
404 // -------------------------------------- write output and some info
405 if ( opt.check(OpenMesh::IO::Options::Binary) )
406 {
407 std::cout << " "
408 << OpenMesh::IO::binary_size(mesh, ofname, opt)
409 << std::endl;
410 }
411 if ( opt.vertex_has_normal() )
412 std::cout << " with vertex normals" << std::endl;
413 if ( opt.vertex_has_color() )
414 std::cout << " with vertex colors" << std::endl;
415 if ( opt.vertex_has_texcoord() )
416 std::cout << " with vertex texcoord" << std::endl;
417 if ( opt.face_has_normal() )
418 std::cout << " with face normals" << std::endl;
419 if ( opt.face_has_color() )
420 std::cout << " with face colors" << std::endl;
421 std::cout << " wrote in " << timer.as_string() << std::endl;
422 timer.reset();
423 }
424
425 return 0;
426 }
OpenMesh::Attributes::Color
Add colors to mesh item (vertices/faces/edges)
Definition: Attributes.hh:88
OpenMesh::IO::read_mesh
bool read_mesh(Mesh &_mesh, const std::string &_filename)
Read a mesh from file _filename.
Definition: MeshIO.hh:104
OpenMesh::Utils::Timer::stop
void stop(void)
Stop measurement.
OpenMesh::PolyMeshT::Color
Kernel::Color Color
Color type.
Definition: PolyMeshT.hh:119
OpenMesh::IO::Options::VertexNormal
Has (r) / store (w) vertex normals.
Definition: Options.hh:109
OpenMesh::IO::binary_size
size_t binary_size(const Mesh &_mesh, const std::string &_ext, Options _opt=Options::Default)
Get binary size of data.
Definition: MeshIO.hh:260
OpenMesh::IO::Options::MSB
Assume big endian byte ordering.
Definition: Options.hh:106
OpenMesh::IO::Options::FaceColor
Has (r) / store (w) face colors.
Definition: Options.hh:114
OpenMesh::TriMesh_ArrayKernelT
Definition: TriMesh_ArrayKernelT.hh:98
OpenMesh::IO::Options::VertexTexCoord
Has (r) / store (w) texture coordinates.
Definition: Options.hh:111
OpenMesh::IO::Options
Set options for reader/writer modules.
Definition: Options.hh:95
OpenMesh::Utils::Timer::as_string
std::string as_string(Format format=Automatic)
Timer.hh
OpenMesh::Attributes::TexCoord2D
Add 2D texture coordinates (vertices, halfedges)
Definition: Attributes.hh:92
OpenMesh::VectorT< float, 3 >
OpenMesh::PolyMeshT::update_vertex_normals
void update_vertex_normals()
Update normal vectors for all vertices.
Definition: PolyMeshT.cc:448
OpenMesh::Utils::Timer::reset
void reset(void)
Reset the timer.
OpenMesh::PolyMeshT::update_face_normals
void update_face_normals()
Update normal vectors for all faces.
Definition: PolyMeshT.cc:259
OpenMesh::Attributes::PrevHalfedge
Add storage for previous halfedge (halfedges). The bit is set by default in the DefaultTraits.
Definition: Attributes.hh:89
OpenMesh::Utils::Timer::start
void start(void)
Start measurement.
Option
Definition: mconvert.cc:107
OpenMesh::Attributes::Normal
Add normals to mesh item (vertices/faces)
Definition: Attributes.hh:87
OpenMesh::IO::Options::Binary
Set binary mode for r/w.
Definition: Options.hh:105
OpenMesh::IO::Options::Swap
Swap byte order in binary mode.
Definition: Options.hh:108
OpenMesh::IO::Options::VertexColor
Has (r) / store (w) vertex colors.
Definition: Options.hh:110
MyTraits
Definition: mymesh.cc:5
OpenMesh::IO::Options::LSB
Assume little endian byte ordering.
Definition: Options.hh:107
OpenMesh::Utils::Timer::cont
void cont(void)
Continue measurement.
OpenMesh::IO::write_mesh
bool write_mesh(const Mesh &_mesh, const std::string &_filename, Options _opt=Options::Default, std::streamsize _precision=6)
Write a mesh to the file _filename.
Definition: MeshIO.hh:199
OpenMesh::DefaultTraits
Definition: Traits.hh:126
OpenMesh::Utils::Timer
Definition: Timer.hh:87
Attributes.hh