49 #include <OpenMesh/Core/Utils/Endian.hh> 50 #include <OpenMesh/Core/IO/IOManager.hh> 51 #include <OpenMesh/Core/IO/BinaryHelper.hh> 52 #include <OpenMesh/Core/IO/writer/PLYWriter.hh> 74 _PLYWriter_::_PLYWriter_()
78 nameOfType_[Unsupported] =
"";
79 nameOfType_[ValueTypeCHAR] =
"char";
80 nameOfType_[ValueTypeUCHAR] = nameOfType_[ValueTypeUINT8] =
"uchar";
81 nameOfType_[ValueTypeUSHORT] =
"ushort";
82 nameOfType_[ValueTypeSHORT] =
"short";
83 nameOfType_[ValueTypeUINT] =
"uint";
84 nameOfType_[ValueTypeINT] =
"int";
85 nameOfType_[ValueTypeFLOAT32] = nameOfType_[ValueTypeFLOAT] =
"float";
86 nameOfType_[ValueTypeDOUBLE] =
"double";
99 std::ofstream out(_filename.c_str(), (_opt.check(
Options::Binary) ? std::ios_base::binary | std::ios_base::out
100 : std::ios_base::out) );
101 return write(out, _be, _opt, _precision);
112 if ( !check( _be, _opt ) )
122 omerr() <<
"[PLYWriter] : Warning: Face normals are not supported and thus not exported! " << std::endl;
130 omerr() <<
"[PLYWriter] : cannot write to stream " 136 _os.precision(_precision);
140 write_binary(_os, _be, _opt) :
141 write_ascii(_os, _be, _opt));
158 std::vector<CustomProperty> customProps;
159 for (;_begin != _end; ++_begin)
176 assert_compile(
sizeof(
char) == 1);
179 if (castProperty<signed char>(prop) != 0 || castProperty<char>(prop) != 0)
180 cProp.type = ValueTypeCHAR;
181 else if (castProperty<unsigned char>(prop) != 0)
182 cProp.type = ValueTypeUCHAR;
187 assert_compile (
sizeof(
short) == 2);
188 if (castProperty<signed short>(prop) != 0)
189 cProp.type = ValueTypeSHORT;
190 else if (castProperty<unsigned short>(prop) != 0)
191 cProp.type = ValueTypeUSHORT;
196 assert_compile (
sizeof(
int) == 4);
197 assert_compile (
sizeof(
float) == 4);
198 if (castProperty<signed int>(prop) != 0)
199 cProp.type = ValueTypeINT;
200 else if (castProperty<unsigned int>(prop) != 0)
201 cProp.type = ValueTypeUINT;
202 else if (castProperty<float>(prop) != 0)
203 cProp.type = ValueTypeFLOAT;
208 assert_compile (
sizeof(
double) == 8);
209 if (castProperty<double>(prop) != 0)
210 cProp.type = ValueTypeDOUBLE;
216 if (cProp.type != Unsupported)
219 customProps.push_back(cProp);
220 _out <<
"property " << nameOfType_[cProp.type] <<
" " << cProp.property->
name() <<
"\n";
228 template<
bool binary>
229 void _PLYWriter_::write_customProp(std::ostream& _out,
const CustomProperty& _prop,
size_t _index)
const 231 if (_prop.type == ValueTypeCHAR)
232 writeProxy(_prop.type,_out, castProperty<signed char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
233 else if (_prop.type == ValueTypeUCHAR || _prop.type == ValueTypeUINT8)
234 writeProxy(_prop.type,_out, castProperty<unsigned char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
235 else if (_prop.type == ValueTypeSHORT)
236 writeProxy(_prop.type,_out, castProperty<signed short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
237 else if (_prop.type == ValueTypeUSHORT)
238 writeProxy(_prop.type,_out, castProperty<unsigned short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
239 else if (_prop.type == ValueTypeUINT)
240 writeProxy(_prop.type,_out, castProperty<unsigned int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
241 else if (_prop.type == ValueTypeINT || _prop.type == ValueTypeINT32)
242 writeProxy(_prop.type,_out, castProperty<signed int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
243 else if (_prop.type == ValueTypeFLOAT || _prop.type == ValueTypeFLOAT32)
244 writeProxy(_prop.type,_out, castProperty<float>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
245 else if (_prop.type == ValueTypeDOUBLE)
246 writeProxy(_prop.type,_out, castProperty<double>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
256 _out <<
"ply" <<
'\n';
258 if (_opt.is_binary()) {
261 _out <<
"binary_big_endian ";
263 _out <<
"binary_little_endian ";
264 _out <<
"1.0" <<
'\n';
266 _out <<
"format ascii 1.0" <<
'\n';
268 _out <<
"element vertex " << _be.n_vertices() <<
'\n';
270 _out <<
"property float x" <<
'\n';
271 _out <<
"property float y" <<
'\n';
272 _out <<
"property float z" <<
'\n';
274 if ( _opt.vertex_has_normal() ){
275 _out <<
"property float nx" <<
'\n';
276 _out <<
"property float ny" <<
'\n';
277 _out <<
"property float nz" <<
'\n';
280 if ( _opt.vertex_has_texcoord() ){
281 _out <<
"property float u" <<
'\n';
282 _out <<
"property float v" <<
'\n';
285 if ( _opt.vertex_has_color() ){
286 if ( _opt.color_is_float() ) {
287 _out <<
"property float red" <<
'\n';
288 _out <<
"property float green" <<
'\n';
289 _out <<
"property float blue" <<
'\n';
291 if ( _opt.color_has_alpha() )
292 _out <<
"property float alpha" <<
'\n';
294 _out <<
"property uchar red" <<
'\n';
295 _out <<
"property uchar green" <<
'\n';
296 _out <<
"property uchar blue" <<
'\n';
298 if ( _opt.color_has_alpha() )
299 _out <<
"property uchar alpha" <<
'\n';
305 _out <<
"element face " << _be.n_faces() <<
'\n';
306 _out <<
"property list uchar int vertex_indices" <<
'\n';
308 if ( _opt.face_has_color() ){
309 if ( _opt.color_is_float() ) {
310 _out <<
"property float red" <<
'\n';
311 _out <<
"property float green" <<
'\n';
312 _out <<
"property float blue" <<
'\n';
314 if ( _opt.color_has_alpha() )
315 _out <<
"property float alpha" <<
'\n';
317 _out <<
"property uchar red" <<
'\n';
318 _out <<
"property uchar green" <<
'\n';
319 _out <<
"property uchar blue" <<
'\n';
321 if ( _opt.color_has_alpha() )
322 _out <<
"property uchar alpha" <<
'\n';
328 _out <<
"end_header" <<
'\n';
340 unsigned int i, nV, nF;
349 std::vector<VertexHandle> vhandles;
351 std::vector<CustomProperty> vProps;
352 std::vector<CustomProperty> fProps;
356 if (_opt.color_is_float())
360 for (i=0, nV=
int(_be.n_vertices()); i<nV; ++i)
366 _out << v[0] <<
" " << v[1] <<
" " << v[2];
369 if ( _opt.vertex_has_normal() ){
371 _out <<
" " << n[0] <<
" " << n[1] <<
" " << n[2];
375 if ( _opt.vertex_has_texcoord() ) {
376 t = _be.texcoord(vh);
377 _out <<
" " << t[0] <<
" " << t[1];
381 if ( _opt.vertex_has_color() ) {
383 if ( _opt.color_has_alpha() ){
384 if (_opt.color_is_float()) {
385 cAf = _be.colorAf(vh);
388 cA = _be.colorAi(vh);
393 if (_opt.color_is_float()) {
405 for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
406 write_customProp<false>(_out,*iter,i);
412 for (i=0, nF=
int(_be.n_faces()); i<nF; ++i)
417 nV = _be.get_vhandles(fh, vhandles);
419 for (
size_t j=0; j<vhandles.size(); ++j)
420 _out <<
" " << vhandles[j].idx();
423 if ( _opt.face_has_color() ) {
425 if ( _opt.color_has_alpha() ){
426 if (_opt.color_is_float()) {
427 cAf = _be.colorAf(fh);
430 cA = _be.colorAi(fh);
435 if (_opt.color_is_float()) {
446 for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
447 write_customProp<false>(_out,*iter,i);
458 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
int value)
const {
480 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
unsigned int value)
const {
502 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
float value)
const {
507 case ValueTypeFLOAT32:
513 std::cerr <<
"unsupported conversion type to float: " << _type << std::endl;
518 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
double value)
const {
523 case ValueTypeDOUBLE:
528 std::cerr <<
"unsupported conversion type to float: " << _type << std::endl;
533 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
signed char value)
const{
543 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
547 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
unsigned char value)
const{
557 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
561 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
short value)
const{
571 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
575 void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out,
unsigned short value)
const{
580 case ValueTypeUSHORT:
585 std::cerr <<
"unsupported conversion type to int: " << _type << std::endl;
595 unsigned int i, nV, nF;
602 std::vector<VertexHandle> vhandles;
605 std::vector<CustomProperty> vProps;
606 std::vector<CustomProperty> fProps;
611 for (i=0, nV=
int(_be.n_vertices()); i<nV; ++i)
617 writeValue(ValueTypeFLOAT, _out, v[0]);
618 writeValue(ValueTypeFLOAT, _out, v[1]);
619 writeValue(ValueTypeFLOAT, _out, v[2]);
622 if ( _opt.vertex_has_normal() ){
624 writeValue(ValueTypeFLOAT, _out, n[0]);
625 writeValue(ValueTypeFLOAT, _out, n[1]);
626 writeValue(ValueTypeFLOAT, _out, n[2]);
630 if ( _opt.vertex_has_texcoord() ) {
631 t = _be.texcoord(vh);
632 writeValue(ValueTypeFLOAT, _out, t[0]);
633 writeValue(ValueTypeFLOAT, _out, t[1]);
637 if ( _opt.vertex_has_color() ) {
638 if ( _opt.color_is_float() ) {
639 cf = _be.colorAf(vh);
640 writeValue(ValueTypeFLOAT, _out, cf[0]);
641 writeValue(ValueTypeFLOAT, _out, cf[1]);
642 writeValue(ValueTypeFLOAT, _out, cf[2]);
644 if ( _opt.color_has_alpha() )
645 writeValue(ValueTypeFLOAT, _out, cf[3]);
648 writeValue(ValueTypeUCHAR, _out, (
int)c[0]);
649 writeValue(ValueTypeUCHAR, _out, (
int)c[1]);
650 writeValue(ValueTypeUCHAR, _out, (
int)c[2]);
652 if ( _opt.color_has_alpha() )
653 writeValue(ValueTypeUCHAR, _out, (
int)c[3]);
657 for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
658 write_customProp<true>(_out,*iter,i);
662 for (i=0, nF=
int(_be.n_faces()); i<nF; ++i)
667 nV = _be.get_vhandles(fh, vhandles);
668 writeValue(ValueTypeUINT8, _out, nV);
669 for (
size_t j=0; j<vhandles.size(); ++j)
670 writeValue(ValueTypeINT32, _out, vhandles[j].idx() );
673 if ( _opt.face_has_color() ) {
674 if ( _opt.color_is_float() ) {
675 cf = _be.colorAf(fh);
676 writeValue(ValueTypeFLOAT, _out, cf[0]);
677 writeValue(ValueTypeFLOAT, _out, cf[1]);
678 writeValue(ValueTypeFLOAT, _out, cf[2]);
680 if ( _opt.color_has_alpha() )
681 writeValue(ValueTypeFLOAT, _out, cf[3]);
684 writeValue(ValueTypeUCHAR, _out, (
int)c[0]);
685 writeValue(ValueTypeUCHAR, _out, (
int)c[1]);
686 writeValue(ValueTypeUCHAR, _out, (
int)c[2]);
688 if ( _opt.color_has_alpha() )
689 writeValue(ValueTypeUCHAR, _out, (
int)c[3]);
693 for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
694 write_customProp<true>(_out,*iter,i);
709 size_t _3floats(3*
sizeof(
float));
710 size_t _3ui(3*
sizeof(
unsigned int));
711 size_t _4ui(4*
sizeof(
unsigned int));
713 if ( !_opt.is_binary() )
718 size_t _3longs(3*
sizeof(
long));
722 data += _be.n_vertices() * _3floats;
725 if ( _opt.vertex_has_normal() && _be.has_vertex_normals() )
728 data += _be.n_vertices() * _3floats;
731 if ( _opt.vertex_has_color() && _be.has_vertex_colors() )
734 data += _be.n_vertices() * _3floats;
737 if ( _opt.vertex_has_texcoord() && _be.has_vertex_texcoords() )
739 size_t _2floats(2*
sizeof(
float));
741 data += _be.n_vertices() * _2floats;
745 if (_be.is_triangle_mesh())
747 data += _be.n_faces() * _4ui;
752 std::vector<VertexHandle> vhandles;
754 for (i=0, nF=
int(_be.n_faces()); i<nF; ++i)
756 data += _be.get_vhandles(
FaceHandle(i), vhandles) *
sizeof(
unsigned int);
762 if ( _opt.face_has_color() && _be.has_face_colors() ){
763 if ( _opt.color_has_alpha() )
764 data += _be.n_faces() * _4ui;
766 data += _be.n_faces() * _3ui;
void write_header(std::ostream &_out, BaseExporter &_be, Options &_opt, std::vector< CustomProperty > &_ovProps, std::vector< CustomProperty > &_ofProps) const
write header into the stream _out. Returns custom properties (vertex and face) which are written into...
Handle for a vertex entity.
bool register_module(BaseReader *_bl)
Has (r) / store (w) face normals.
_IOManager_ & IOManager()
const std::string & name() const
Return the name of the property.
Options & unset(const value_type _rhs)
Unset options defined in _rhs.
_PLYWriter_ __PLYWriterInstance
Declare the single entity of the PLY writer.
Handle for a face entity.
Default property class for any type T.
Set options for reader/writer modules.
virtual size_t element_size() const =0
Size of one element in bytes or UnknownSize if not known.
size_t binary_size(BaseExporter &_be, Options _opt) const
Returns expected size of file if binary format is supported else 0.
Assume big endian byte ordering.
bool persistent(void) const
Returns true if the persistent flag is enabled else false.
bool write(const std::string &, BaseExporter &, Options, std::streamsize _precision=6) const
std::vector< CustomProperty > writeCustomTypeHeader(std::ostream &_out, BaseKernel::const_prop_iterator _begin, BaseKernel::const_prop_iterator _end) const
write custom persistant properties into the header for the current element, returns all properties...