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;
Handle for a face entity.
Assume big endian byte ordering.
Handle for a vertex entity.
size_t binary_size(BaseExporter &_be, Options _opt) const override
Returns expected size of file if binary format is supported else 0.
bool register_module(BaseReader *_bl)
bool persistent(void) const
Returns true if the persistent flag is enabled else false.
Default property class for any type T.
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...
virtual size_t element_size() const =0
Size of one element in bytes or UnknownSize if not known.
const std::string & name() const
Return the name of the property.
bool write(const std::string &, BaseExporter &, Options, std::streamsize _precision=6) const override
Set options for reader/writer modules.
Options & unset(const value_type _rhs)
Unset options defined in _rhs.
_IOManager_ & IOManager()
Has (r) / store (w) face normals.
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...
_PLYWriter_ __PLYWriterInstance
Declare the single entity of the PLY writer.