【OpenMesh】使用IO::Options

这个例子展示了:
如何控制Mesh::IO::read_mesh()行为,
如何控制Mesh::IO::write_mesh()行为。
OpenMesh::IO::Options可以用作读写网格。这个类通过开关相应的bit位实现控制读写器的行为。这个类提供接口实现开、关和修改相应的位。我们区分一下的控制位
mode bit-控制二进制读写
  • Options::Binary
  • Options::MSB
  • Options::LSB
  • Options::Swap (MSB|LSB)
property bits-控制读写属性
  • Options::VertexNormal
  • Options::VertexTexCoord
  • Options::VertexColor
  • Options::FaceNormal
  • Options::FaceColor
这些bit位对读写有不同的影响。通过文件名选择文件格式文件的格式。OpenMesh库的IO子系统支持4种格式。
程序不仅仅提供基于接口的命令行来选择读写器和请求网格属性的选项bit。因此非法的组合是有可能的也会导致程序错误。(输入文件不会导致损失,但是小心你存放输出的文件)

读取网格

当读取一个文件的时候mode bit用于给读取器建议或者提示。我们能够帮助读写器根据格式正确解释数据。首先我们可以文件包含二进制数据。
ropt += IO::Options::Binary; 
进一步我们可以让读写器两个交换字节顺序。
ropt += IO::Options::Swap; 
(两个都可以通过命令行使用选项 -b和-s实现)
默认情况下几何和拓扑保存在文件中。文件可以包含更多的信息,特别是可以提供法向量和纹理坐标。我们可以在读取之后检查属性bit发现还有什么其他的可以获得:
ropt.check(IO::Options::VertexNormal) 
如果一个属性bit设置为没有意义,它就会被复原。请求属性必须先于读取文件。
(示例程序提供命令行选项 -Xv和-Xf来请求顶点和面的属性)

写入网格

当编写网格模式位显然控制是否使用二进制变量和所需的字节顺序。例如,如果我们选择二进制模式和想交换字节顺序,我们设置
wopt += IO::Options::Binary; 
wopt += IO::Options::Swap; 
如果格式不指定字节顺序系统使用系统自身的字节顺序。如果格式不支持二进制存储,则模式位被忽略。如果格式支持存储额外的信息,这是符合标准属性的格式,我们可以使用属性bit告诉写入器我们想写入保存什么。如果我们想要顶点法向量我们只用简单的设置
wopt += IO::Options::VertexNormal; 
最终我们可以写入数据到文件。
if ( !IO::write_mesh( mesh, argv[optind+1], wopt ) )
有三种原因方法返回错误:
  1. 选中的文件格式不支持该选择项
  2. 选中的标准属性不可用
  3. 一个系统错误
    • 因为访问权限无法打开文件
    • 读写时磁盘空间用尽
    • 。。。(不详)
完整代码:
#include <iostream>
#include <iterator>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Tools/Utils/getopt.h>
// ----------------------------------------------------------------------------
using namespace OpenMesh;
// ----------------------------------------------------------------------------
typedef TriMesh_ArrayKernelT<> MyMesh;
// ----------------------------------------------------------------------------
#define CHKROPT( Option ) \
std::cout << " provides " << #Option \
<< (ropt.check(IO::Options:: Option)?": yes\n":": no\n")
#define CHKWOPT( Option ) \
std::cout << " write " << #Option \
<< (wopt.check(IO::Options:: Option)?": yes\n":": no\n")
#define MESHOPT( msg, tf ) \
std::cout << " " << msg << ": " << ((tf)?"yes\n":"no\n")
// ----------------------------------------------------------------------------
void parse_commandline( int _argc, char **_argv, MyMesh& _mesh,
IO::Options &ropt, IO::Options &wopt );
void usage_and_exit(int xcode);
// ----------------------------------------------------------------------------
int main(int argc, char **argv)
{
MyMesh mesh;
IO::Options ropt, wopt;
// -------------------- evaluate commandline
parse_commandline( argc, argv, mesh, ropt, wopt );
// -------------------- read mesh
if ( ! IO::read_mesh(mesh,argv[optind], ropt))
{
std::cerr << "Error loading mesh from file " << argv[optind] << std::endl;
return 1;
}
// -------------------- show options
std::cout << "File " << argv[optind] << std::endl;
std::cout << " is binary: " 
<< (ropt.check(IO::Options::Binary) ? " yes\n" : " no\n");
std::cout << " byte order: ";
if (ropt.check(IO::Options::Swap))
std::cout << "swapped\n";
else if (ropt.check(IO::Options::LSB))
std::cout << "little endian\n";
else if (ropt.check(IO::Options::MSB))
std::cout << "big endian\n";
else
std::cout << "don't care\n";

std::cout << " provides VertexNormal"
<< ( // strange layout for doxygen
ropt.check(IO::Options::VertexNormal) 
? ": yes\n":": no\n");
CHKROPT( VertexColor );
CHKROPT( VertexTexCoord );
CHKROPT( FaceNormal );
CHKROPT( FaceColor );
// -------------------- mesh stats
std::cout << "# Vertices: " << mesh.n_vertices() << std::endl;
std::cout << "# Edges : " << mesh.n_faces() << std::endl;
std::cout << "# Faces : " << mesh.n_faces() << std::endl;
// -------------------- show write options
std::cout << "Selected write options:\n";
std::cout << " use binary: " 
<< (wopt.check(IO::Options::Binary) ? " yes\n" : " no\n");
std::cout << " byte order: ";
if (wopt.check(IO::Options::Swap))
std::cout << "swapped\n";
else if (wopt.check(IO::Options::LSB))
std::cout << "little endian\n";
else if (wopt.check(IO::Options::MSB))
std::cout << "big endian\n";
else
std::cout << "don't care\n";

std::cout << " write VertexNormal"
<< (wopt.check(IO::Options::VertexNormal) ? ": yes\n":": no\n");
CHKWOPT( VertexColor );
CHKWOPT( VertexTexCoord );
CHKWOPT( FaceNormal );
CHKWOPT( FaceColor );
// -------------------- show mesh capabilities
std::cout << "Mesh supports\n";
MESHOPT("vertex normals", mesh.has_vertex_normals());
MESHOPT("vertex colors", mesh.has_vertex_colors());
MESHOPT("texcoords", mesh.has_vertex_texcoords2D());
MESHOPT("face normals", mesh.has_face_normals());
MESHOPT("face colors", mesh.has_face_colors());
// -------------------- write mesh
std::cout << "Write mesh to " << argv[optind+1] << "..";
if ( !IO::write_mesh( mesh, argv[optind+1], wopt ) )
{
std::cerr << "Error" << std::endl;
std::cerr << "Possible reasons:\n";
std::cerr << "1. Chosen format cannot handle an option!\n";
std::cerr << "2. Mesh does not provide necessary information!\n";
std::cerr << "3. Or simply cannot open file for writing!\n";
return 1;
}
else
std::cout << "Ok.\n";
return 0;
}
// ----------------------------------------------------------------------------
void parse_commandline( int _argc, char **_argv, MyMesh& _mesh,
IO::Options &ropt, IO::Options &wopt )
{
int c;
while ((c=getopt(_argc, _argv, "bhsBF:LMSV:X:"))!=-1)
{
switch(c) 
{
// -------------------- read options
// force binary input
case 'b': 
ropt += IO::Options::Binary; 
break;
// force swapping the byte order, when reading a binary file
case 's': 
ropt += IO::Options::Swap; 
break;
// -------------------- write options
// Write binary variant of format if possible
case 'B': 
wopt += IO::Options::Binary; 
break;
// 
case 'F':
for(size_t i=0; optarg[i]; ++i)
switch(optarg[i]) {
case 'n' : wopt += IO::Options::FaceNormal; break;
case 'c' : wopt += IO::Options::FaceColor; break;
}
break;
// Use little endian when writing binary data
case 'L': 
wopt += IO::Options::LSB; 
break;
// Use big endian when writing binary data
case 'M': 
wopt += IO::Options::MSB; 
break;
// Swap byte order when writing binary data
case 'S': 
wopt += IO::Options::Swap; 
break;
//
case 'V':
{
for(size_t i=0; optarg[i]; ++i)
switch(optarg[i]) {
case 'n' : // dont't change layout!!
wopt += IO::Options::VertexNormal; 
break;
case 't' : wopt += IO::Options::VertexTexCoord; break;
case 'c' : wopt += IO::Options::VertexColor; break;
}
break;
}
// -------------------- request mesh' standard properties
case 'X':
{ 
char entity='\0';
for(size_t i=0; optarg[i]; ++i)
switch(optarg[i]) {
case 'v': 
case 'f': entity = optarg[i]; break;
case 'n':
switch(entity) {
case 'v': _mesh.request_vertex_normals(); break;
case 'f': _mesh.request_face_normals(); break;
}
break;
case 'c':
switch(entity) {
case 'v': _mesh.request_vertex_colors(); break;
case 'f': _mesh.request_face_colors(); break;
}
break;
case 't':
switch(entity) {
case 'v': _mesh.request_vertex_texcoords2D(); break;
}
break;
}
break;
}

// -------------------- help
case 'h':
usage_and_exit(0);
default:
usage_and_exit(1);
}
}
if ( _argc-optind != 2)
usage_and_exit(1);
}
// ----------------------------------------------------------------------------
void usage_and_exit(int xcode)
{
std::ostream &os = xcode ? std::cerr : std::cout;
os << "Usage: io_options [Options] <input> <output>\n" 
<< std::endl;
os << " Read and write a mesh, using OpenMesh::IO::Options\n"
<< std::endl;
os << "Options:\n"
<< std::endl;
os << "a) read options\n"
<< std::endl
<< " -b\n"
<< "\tAssume input file is a binary file\n"
<< std::endl
<< " -s\n"
<< "\tSwap byte order when reading a binary file!\n"
<< std::endl;
os << "b) write options\n"
<< std::endl
<< " -B\n"
<< "\tWrite binary data\n"
<< std::endl
<< " -S\n"
<< "\tSwap byte order, when writing binary data\n"
<< std::endl
<< " -M/-L\n"
<< "\tUse MSB/LSB byte ordering, when writing binary data\n"
<< std::endl
<< " -V{n|t|c}\n"
<< "\tWrite vertex normals, texcoords, and/or colors\n"
<< std::endl
<< " -F{n|c}\n"
<< "\tWrite face normals, and/or colors\n"
<< std::endl;
os << "c) Mesh properties\n"
<< std::endl
<< " -Xv{n|c|t}\n"
<< "\tRequest vertex property normals|colors|texcoords\n"
<< std::endl
<< " -Xf{n|c}\n"
<< "\tRequest face property normals|colors\n"
<< std::endl;
exit(xcode);
}
// end of file
// ============================================================================

你可能感兴趣的:(【OpenMesh】使用IO::Options)