First checkin for OpenMesh 2.0
git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@2 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
378
Apps/mconvert/mconvert.cc
Normal file
378
Apps/mconvert/mconvert.cc
Normal file
@@ -0,0 +1,378 @@
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
//
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Core/Mesh/Attributes.hh>
|
||||
#include <OpenMesh/Tools/Utils/Timer.hh>
|
||||
#include <OpenMesh/Tools/Utils/getopt.h>
|
||||
|
||||
|
||||
struct MyTraits : public OpenMesh::DefaultTraits
|
||||
{
|
||||
VertexAttributes ( OpenMesh::Attributes::Normal |
|
||||
OpenMesh::Attributes::Color |
|
||||
OpenMesh::Attributes::TexCoord2D );
|
||||
HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge );
|
||||
FaceAttributes ( OpenMesh::Attributes::Normal |
|
||||
OpenMesh::Attributes::Color );
|
||||
};
|
||||
|
||||
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits> MyMesh;
|
||||
|
||||
void usage_and_exit(int xcode)
|
||||
{
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
cout << "\nUsage: mconvert [option] <input> [<output>]\n\n";
|
||||
cout << " Convert from one 3D geometry format to another.\n"
|
||||
<< " Or simply display some information about the object\n"
|
||||
<< " stored in <input>.\n"
|
||||
<< endl;
|
||||
cout << "Options:\n"
|
||||
<< endl;
|
||||
cout << " -b\tUse binary mode if supported by target format.\n" << endl;
|
||||
cout << " -l\tStore least significant bit first (LSB, little endian).\n" << endl;
|
||||
cout << " -m\tStore most significant bit first (MSB, big endian).\n" << endl;
|
||||
cout << " -s\tSwap byte order.\n" << endl;
|
||||
cout << " -B\tUse binary mode if supported by source format.\n" << endl;
|
||||
cout << " -S\tSwap byte order of input data.\n" << endl;
|
||||
cout << " -c\tCopy vertex color if provided by input.\n" << endl;
|
||||
cout << " -d\tCopy face color if provided by input.\n" << endl;
|
||||
cout << " -C\tTranslate object in its center-of-gravity.\n" << endl;
|
||||
cout << " -n\tCopy vertex normals if provided by input. Else compute normals.\n" << endl;
|
||||
cout << " -N\tReverse normal directions.\n" << endl;
|
||||
cout << " -t\tCopy vertex texture coordinates if provided by input file.\n" << endl;
|
||||
cout << " -T \"x y z\"\tTranslate object by vector (x, y, z)'\"\n"
|
||||
<< std::endl;
|
||||
cout << endl;
|
||||
|
||||
exit(xcode);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
template <typename T> struct Option : std::pair< T, bool >
|
||||
{
|
||||
typedef std::pair< T, bool > Base;
|
||||
|
||||
Option()
|
||||
{ Base::second = false; }
|
||||
|
||||
bool is_valid() const { return Base::second; }
|
||||
bool is_empty() const { return !Base::second; }
|
||||
|
||||
operator T& () { return Base::first; }
|
||||
operator const T& () const { return Base::first; }
|
||||
|
||||
Option& operator = ( const T& _rhs )
|
||||
{ Base::first = _rhs; Base::second=true; return *this; }
|
||||
|
||||
bool operator == ( const T& _rhs ) const
|
||||
{ return Base::first == _rhs; }
|
||||
|
||||
bool operator != ( const T& _rhs ) const
|
||||
{ return Base::first != _rhs; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
std::ostream& operator << (std::ostream& _os, const Option<T>& _opt )
|
||||
{
|
||||
if (_opt.second) _os << _opt.first; else _os << "<null>";
|
||||
return _os;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::istream& operator >> (std::istream& _is, Option<T>& _opt )
|
||||
{
|
||||
_is >> _opt.first; _opt.second = true;
|
||||
return _is;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
// ------------------------------------------------------------ command line
|
||||
|
||||
int c;
|
||||
std::string ifname, ofname;
|
||||
bool rev_normals = false;
|
||||
bool obj_center = false;
|
||||
OpenMesh::IO::Options opt, ropt;
|
||||
|
||||
Option< MyMesh::Point > tvec;
|
||||
|
||||
while ( (c=getopt(argc, argv, "bBcdCi:hlmnNo:sStT:"))!=-1 )
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case 'b': opt += OpenMesh::IO::Options::Binary; break;
|
||||
case 'B': ropt += OpenMesh::IO::Options::Binary; break;
|
||||
case 'l': opt += OpenMesh::IO::Options::LSB; break;
|
||||
case 'm': opt += OpenMesh::IO::Options::MSB; break;
|
||||
case 's': opt += OpenMesh::IO::Options::Swap; break;
|
||||
case 'S': ropt += OpenMesh::IO::Options::Swap; break;
|
||||
case 'n': opt += OpenMesh::IO::Options::VertexNormal; break;
|
||||
case 'N': rev_normals = true; break;
|
||||
case 'C': obj_center = true; break;
|
||||
case 'c': opt += OpenMesh::IO::Options::VertexColor; break;
|
||||
case 'd': opt += OpenMesh::IO::Options::FaceColor; break;
|
||||
case 't': opt += OpenMesh::IO::Options::VertexTexCoord; break;
|
||||
case 'T':
|
||||
{
|
||||
std::cout << optarg << std::endl;
|
||||
std::stringstream str; str << optarg;
|
||||
str >> tvec;
|
||||
std::cout << tvec << std::endl;
|
||||
break;
|
||||
}
|
||||
case 'i': ifname = optarg; break;
|
||||
case 'o': ofname = optarg; break;
|
||||
case 'h':
|
||||
usage_and_exit(0);
|
||||
case '?':
|
||||
default:
|
||||
usage_and_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ifname.empty())
|
||||
{
|
||||
if (optind < argc)
|
||||
ifname = argv[optind++];
|
||||
else
|
||||
usage_and_exit(1);
|
||||
}
|
||||
|
||||
MyMesh mesh;
|
||||
OpenMesh::Utils::Timer timer;
|
||||
|
||||
// ------------------------------------------------------------ read
|
||||
|
||||
std::cout << "reading.." << std::endl;
|
||||
{
|
||||
bool rc;
|
||||
timer.start();
|
||||
rc = OpenMesh::IO::read_mesh( mesh, ifname, ropt );
|
||||
timer.stop();
|
||||
if (rc)
|
||||
std::cout << " read in " << timer.as_string() << std::endl;
|
||||
else
|
||||
{
|
||||
std::cout << " read failed\n" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
timer.reset();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------- some information about input
|
||||
std::cout << (ropt.check(OpenMesh::IO::Options::Binary)
|
||||
? " source is binary\n"
|
||||
: " source is ascii\n");
|
||||
|
||||
std::cout << " #V " << mesh.n_vertices() << std::endl;
|
||||
std::cout << " #E " << mesh.n_edges() << std::endl;
|
||||
std::cout << " #F " << mesh.n_faces() << std::endl;
|
||||
|
||||
if (ropt.vertex_has_texcoord())
|
||||
std::cout << " has texture coordinates" << std::endl;
|
||||
|
||||
if (ropt.vertex_has_normal())
|
||||
std::cout << " has vertex normals" << std::endl;
|
||||
|
||||
if (ropt.vertex_has_color())
|
||||
std::cout << " has vertex colors" << std::endl;
|
||||
|
||||
if (ropt.face_has_normal())
|
||||
std::cout << " has face normals" << std::endl;
|
||||
|
||||
if (ropt.face_has_color())
|
||||
std::cout << " has face colors" << std::endl;
|
||||
|
||||
//
|
||||
if (ofname.empty())
|
||||
{
|
||||
if ( optind < argc )
|
||||
ofname = argv[optind++];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ features
|
||||
|
||||
// ---------------------------------------- compute normal feature
|
||||
if ( opt.vertex_has_normal() && !ropt.vertex_has_normal())
|
||||
{
|
||||
std::cout << "compute normals" << std::endl;
|
||||
|
||||
timer.start();
|
||||
mesh.update_face_normals();
|
||||
timer.stop();
|
||||
std::cout << " " << mesh.n_faces()
|
||||
<< " face normals in " << timer.as_string() << std::endl;
|
||||
timer.reset();
|
||||
|
||||
timer.start();
|
||||
mesh.update_vertex_normals();
|
||||
timer.stop();
|
||||
std::cout << " " << mesh.n_vertices()
|
||||
<< " vertex normals in " << timer.as_string() << std::endl;
|
||||
timer.reset();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------- reverse normal feature
|
||||
if ( rev_normals && ropt.vertex_has_normal() )
|
||||
{
|
||||
std::cout << "reverse normal directions" << std::endl;
|
||||
timer.start();
|
||||
MyMesh::VertexIter vit = mesh.vertices_begin();
|
||||
for (; vit != mesh.vertices_end(); ++vit)
|
||||
mesh.set_normal( vit.handle(), -mesh.normal( vit.handle() ) );
|
||||
timer.stop();
|
||||
std::cout << " " << mesh.n_vertices()
|
||||
<< " vertex normals in " << timer.as_string() << std::endl;
|
||||
timer.reset();
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------- centering feature
|
||||
if ( obj_center )
|
||||
{
|
||||
OpenMesh::Vec3f cog(0,0,0);
|
||||
size_t nv;
|
||||
std::cout << "center object" << std::endl;
|
||||
timer.start();
|
||||
MyMesh::VertexIter vit = mesh.vertices_begin();
|
||||
for (; vit != mesh.vertices_end(); ++vit)
|
||||
cog += mesh.point( vit );
|
||||
timer.stop();
|
||||
nv = mesh.n_vertices();
|
||||
cog *= 1.0f/mesh.n_vertices();
|
||||
std::cout << " cog = [" << cog << "]'" << std::endl;
|
||||
if (cog.sqrnorm() > 0.8) // actually one should consider the size of object
|
||||
{
|
||||
vit = mesh.vertices_begin();
|
||||
timer.cont();
|
||||
for (; vit != mesh.vertices_end(); ++vit)
|
||||
mesh.set_point( vit , mesh.point( vit )-cog );
|
||||
timer.stop();
|
||||
nv += mesh.n_vertices();
|
||||
}
|
||||
else
|
||||
std::cout << " already centered!" << std::endl;
|
||||
std::cout << " visited " << nv
|
||||
<< " vertices in " << timer.as_string() << std::endl;
|
||||
timer.reset();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------- translate feature
|
||||
if ( tvec.is_valid() )
|
||||
{
|
||||
std::cout << "Translate object by " << tvec << std::endl;
|
||||
|
||||
timer.start();
|
||||
MyMesh::VertexIter vit = mesh.vertices_begin();
|
||||
for (; vit != mesh.vertices_end(); ++vit)
|
||||
mesh.set_point( vit , mesh.point( vit ) + tvec.first );
|
||||
timer.stop();
|
||||
std::cout << " moved " << mesh.n_vertices()
|
||||
<< " vertices in " << timer.as_string() << std::endl;
|
||||
}
|
||||
|
||||
// ---------------------------------------- color vertices feature
|
||||
if ( opt.check( OpenMesh::IO::Options::VertexColor ) &&
|
||||
!ropt.check( OpenMesh::IO::Options::VertexColor ) )
|
||||
{
|
||||
std::cout << "Color vertices" << std::endl;
|
||||
|
||||
double d = 256.0/double(mesh.n_vertices());
|
||||
double d2 = d/2.0;
|
||||
double r = 0.0, g = 0.0, b = 255.0;
|
||||
timer.start();
|
||||
MyMesh::VertexIter vit = mesh.vertices_begin();
|
||||
for (; vit != mesh.vertices_end(); ++vit)
|
||||
{
|
||||
mesh.set_color( vit , MyMesh::Color( std::min((int)(r+0.5),255),
|
||||
std::min((int)(g+0.5),255),
|
||||
std::max((int)(b+0.5),0) ) );
|
||||
r += d;
|
||||
g += d2;
|
||||
b -= d;
|
||||
}
|
||||
timer.stop();
|
||||
std::cout << " colored " << mesh.n_vertices()
|
||||
<< " vertices in " << timer.as_string() << std::endl;
|
||||
}
|
||||
|
||||
// ---------------------------------------- color faces feature
|
||||
if ( opt.check( OpenMesh::IO::Options::FaceColor ) &&
|
||||
!ropt.check( OpenMesh::IO::Options::FaceColor ) )
|
||||
{
|
||||
std::cout << "Color faces" << std::endl;
|
||||
|
||||
double d = 256.0/double(mesh.n_faces());
|
||||
double d2 = d/2.0;
|
||||
double r = 0.0, g = 50.0, b = 255.0;
|
||||
timer.start();
|
||||
MyMesh::FaceIter it = mesh.faces_begin();
|
||||
for (; it != mesh.faces_end(); ++it)
|
||||
{
|
||||
mesh.set_color( it , MyMesh::Color( std::min((int)(r+0.5),255),
|
||||
std::min((int)(g+0.5),255),
|
||||
std::max((int)(b+0.5),0) ) );
|
||||
r += d2;
|
||||
// g += d2;
|
||||
b -= d;
|
||||
}
|
||||
timer.stop();
|
||||
std::cout << " colored " << mesh.n_faces()
|
||||
<< " faces in " << timer.as_string() << std::endl;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ write
|
||||
|
||||
std::cout << "writing.." << std::endl;
|
||||
{
|
||||
bool rc;
|
||||
timer.start();
|
||||
rc = OpenMesh::IO::write_mesh( mesh, ofname, opt );
|
||||
timer.stop();
|
||||
|
||||
if (!rc)
|
||||
{
|
||||
std::cerr << " error writing mesh!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// -------------------------------------- write output and some info
|
||||
if ( opt.check(OpenMesh::IO::Options::Binary) )
|
||||
{
|
||||
std::cout << " "
|
||||
<< OpenMesh::IO::binary_size(mesh, ofname, opt)
|
||||
<< std::endl;
|
||||
}
|
||||
if ( opt.vertex_has_normal() )
|
||||
std::cout << " with vertex normals" << std::endl;
|
||||
if ( opt.vertex_has_color() )
|
||||
std::cout << " with vertex colors" << std::endl;
|
||||
if ( opt.vertex_has_texcoord() )
|
||||
std::cout << " with vertex texcoord" << std::endl;
|
||||
if ( opt.face_has_normal() )
|
||||
std::cout << " with face normals" << std::endl;
|
||||
if ( opt.face_has_color() )
|
||||
std::cout << " with face colors" << std::endl;
|
||||
std::cout << " wrote in " << timer.as_string() << std::endl;
|
||||
timer.reset();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
25
Apps/mconvert/mconvert.pro
Normal file
25
Apps/mconvert/mconvert.pro
Normal file
@@ -0,0 +1,25 @@
|
||||
################################################################################
|
||||
#
|
||||
################################################################################
|
||||
|
||||
contains( OPENFLIPPER , OpenFlipper ){
|
||||
include( $$TOPDIR/qmake/all.include )
|
||||
} else {
|
||||
include( $$TOPDIR/OpenMesh/qmake/all.include )
|
||||
}
|
||||
|
||||
INCLUDEPATH += ../../..
|
||||
|
||||
Application()
|
||||
glew()
|
||||
glut()
|
||||
openmesh()
|
||||
|
||||
DIRECTORIES = .
|
||||
|
||||
# Input
|
||||
HEADERS += $$getFilesFromDir($$DIRECTORIES,*.hh)
|
||||
SOURCES += $$getFilesFromDir($$DIRECTORIES,*.cc)
|
||||
FORMS += $$getFilesFromDir($$DIRECTORIES,*.ui)
|
||||
|
||||
################################################################################
|
||||
Reference in New Issue
Block a user