Commit d28df7ed authored by Jan Möbius's avatar Jan Möbius
Browse files

PLY: convert readInteger into a template

parent d91986fc
......@@ -971,8 +971,10 @@ void _PLYReader_::readValue(ValueType _type, std::istream& _in, int& _value) con
//-----------------------------------------------------------------------------
template<typename T>
void _PLYReader_::readInteger(ValueType _type, std::istream& _in, T& _value) const {
void _PLYReader_::readInteger(ValueType _type, std::istream& _in, int& _value) const {
static_assert(std::is_integral<T>::value, "Integral required.");
int32_t tmp_int32_t;
uint32_t tmp_uint32_t;
......@@ -1020,71 +1022,12 @@ void _PLYReader_::readInteger(ValueType _type, std::istream& _in, int& _value) c
default:
_value = 0;
std::cerr << "unsupported conversion type to int: " << _type << std::endl;
break;
}
}
//-----------------------------------------------------------------------------
void _PLYReader_::readInteger(ValueType _type, std::istream& _in, unsigned int& _value) const {
int32_t tmp_int32_t;
uint32_t tmp_uint32_t;
int8_t tmp_char;
uint8_t tmp_uchar;
switch (_type) {
case ValueTypeUINT:
case ValueTypeUINT32:
restore(_in, tmp_uint32_t, options_.check(Options::MSB));
_value = tmp_uint32_t;
break;
case ValueTypeINT:
case ValueTypeINT32:
restore(_in, tmp_int32_t, options_.check(Options::MSB));
_value = tmp_int32_t;
break;
case ValueTypeUCHAR:
case ValueTypeUINT8:
restore(_in, tmp_uchar, options_.check(Options::MSB));
_value = tmp_uchar;
break;
case ValueTypeCHAR:
case ValueTypeINT8:
restore(_in, tmp_char, options_.check(Options::MSB));
_value = tmp_char;
break;
default:
_value = 0;
std::cerr << "unsupported conversion type to unsigned int: " << _type << std::endl;
std::cerr << "unsupported conversion type to integral: " << _type << std::endl;
break;
}
}
//------------------------------------------------------------------------------
......
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
#define LINE_LEN 4096
//== INCLUDES =================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/reader/PLYReader.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
//STL
#include <fstream>
#include <iostream>
#include <memory>
#ifndef WIN32
#endif
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
//=== INSTANCIATE =============================================================
_PLYReader_ __PLYReaderInstance;
_PLYReader_& PLYReader() {
return __PLYReaderInstance;
}
//=== IMPLEMENTATION ==========================================================
_PLYReader_::_PLYReader_() {
IOManager().register_module(this);
// Store sizes in byte of each property type
scalar_size_[ValueTypeINT8] = 1;
scalar_size_[ValueTypeUINT8] = 1;
scalar_size_[ValueTypeINT16] = 2;
scalar_size_[ValueTypeUINT16] = 2;
scalar_size_[ValueTypeINT32] = 4;
scalar_size_[ValueTypeUINT32] = 4;
scalar_size_[ValueTypeFLOAT32] = 4;
scalar_size_[ValueTypeFLOAT64] = 8;
scalar_size_[ValueTypeCHAR] = 1;
scalar_size_[ValueTypeUCHAR] = 1;
scalar_size_[ValueTypeSHORT] = 2;
scalar_size_[ValueTypeUSHORT] = 2;
scalar_size_[ValueTypeINT] = 4;
scalar_size_[ValueTypeUINT] = 4;
scalar_size_[ValueTypeFLOAT] = 4;
scalar_size_[ValueTypeDOUBLE] = 8;
}
//-----------------------------------------------------------------------------
bool _PLYReader_::read(const std::string& _filename, BaseImporter& _bi, Options& _opt) {
std::fstream in(_filename.c_str(), (std::ios_base::binary | std::ios_base::in) );
if (!in.is_open() || !in.good()) {
omerr() << "[PLYReader] : cannot not open file " << _filename << std::endl;
return false;
}
bool result = read(in, _bi, _opt);
in.close();
return result;
}
//-----------------------------------------------------------------------------
bool _PLYReader_::read(std::istream& _in, BaseImporter& _bi, Options& _opt) {
if (!_in.good()) {
omerr() << "[PLYReader] : cannot not use stream" << std::endl;
return false;
}
// Reparse the header
if (!can_u_read(_in)) {
omerr() << "[PLYReader] : Unable to parse header\n";
return false;
}
// filter relevant options for reading
bool swap = _opt.check(Options::Swap);
userOptions_ = _opt;
// build options to be returned
_opt.clear();
if (options_.vertex_has_normal() && userOptions_.vertex_has_normal()) {
_opt += Options::VertexNormal;
}
if (options_.vertex_has_texcoord() && userOptions_.vertex_has_texcoord()) {
_opt += Options::VertexTexCoord;
}
if (options_.vertex_has_color() && userOptions_.vertex_has_color()) {
_opt += Options::VertexColor;
}
if (options_.face_has_color() && userOptions_.face_has_color()) {
_opt += Options::FaceColor;
}
if (options_.is_binary()) {
_opt += Options::Binary;
}
if (options_.color_is_float()) {
_opt += Options::ColorFloat;
}
if (options_.check(Options::Custom) && userOptions_.check(Options::Custom)) {
_opt += Options::Custom;
}
// //force user-choice for the alpha value when reading binary
// if ( options_.is_binary() && userOptions_.color_has_alpha() )
// options_ += Options::ColorAlpha;
return (options_.is_binary() ? read_binary(_in, _bi, swap, _opt) : read_ascii(_in, _bi, _opt));
}
template<typename T, typename Handle>
struct Handle2Prop;
template<typename T>
struct Handle2Prop<T,VertexHandle>
{
typedef OpenMesh::VPropHandleT<T> PropT;
};
template<typename T>
struct Handle2Prop<T,FaceHandle>
{
typedef OpenMesh::FPropHandleT<T> PropT;
};
//read and assign custom properties with the given type. Also creates property, if not exist
template<bool binary, typename T, typename Handle>
void _PLYReader_::readCreateCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const _PLYReader_::ValueType _valueType, const _PLYReader_::ValueType _listType) const
{
if (_listType == Unsupported) //no list type defined -> property is not a list
{
//get/add property
typename Handle2Prop<T,Handle>::PropT prop;
if (!_bi.kernel()->get_property_handle(prop,_propName))
{
_bi.kernel()->add_property(prop,_propName);
_bi.kernel()->property(prop).set_persistent(true);
}
//read and assign
T in;
read(_valueType, _in, in, OpenMesh::GenProg::Bool2Type<binary>());
_bi.kernel()->property(prop,_h) = in;
}
else
{
//get/add property
typename Handle2Prop<std::vector<T>,Handle>::PropT prop;
if (!_bi.kernel()->get_property_handle(prop,_propName))
{
_bi.kernel()->add_property(prop,_propName);
_bi.kernel()->property(prop).set_persistent(true);
}
//init vector
unsigned int numberOfValues;
readInteger(_listType, _in, numberOfValues, OpenMesh::GenProg::Bool2Type<binary>());
std::vector<T> vec(numberOfValues);
//read and assign
for (unsigned int i = 0; i < numberOfValues; ++i)
{
read(_valueType, _in, vec[i], OpenMesh::GenProg::Bool2Type<binary>());
}
_bi.kernel()->property(prop,_h) = vec;
}
}
template<bool binary, typename Handle>
void _PLYReader_::readCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const _PLYReader_::ValueType _valueType, const _PLYReader_::ValueType _listIndexType) const
{
switch (_valueType)
{
case ValueTypeINT8:
case ValueTypeCHAR:
readCreateCustomProperty<binary,signed char>(_in,_bi,_h,_propName,_valueType,_listIndexType);
break;
case ValueTypeUINT8:
case ValueTypeUCHAR:
readCreateCustomProperty<binary,unsigned char>(_in,_bi,_h,_propName,_valueType,_listIndexType);
break;
case ValueTypeINT16:
case ValueTypeSHORT:
readCreateCustomProperty<binary,short>(_in,_bi,_h,_propName,_valueType,_listIndexType);
break;
case ValueTypeUINT16:
case ValueTypeUSHORT:
readCreateCustomProperty<binary,unsigned short>(_in,_bi,_h,_propName,_valueType,_listIndexType);
break;
case ValueTypeINT32:
case ValueTypeINT:
readCreateCustomProperty<binary,int>(_in,_bi,_h,_propName,_valueType,_listIndexType);
break;
case ValueTypeUINT32:
case ValueTypeUINT:
readCreateCustomProperty<binary,unsigned int>(_in,_bi,_h,_propName,_valueType,_listIndexType);
break;
case ValueTypeFLOAT32:
case ValueTypeFLOAT:
readCreateCustomProperty<binary,float>(_in,_bi,_h,_propName,_valueType,_listIndexType);
break;
case ValueTypeFLOAT64:
case ValueTypeDOUBLE:
readCreateCustomProperty<binary,double>(_in,_bi,_h,_propName,_valueType,_listIndexType);
break;
default:
std::cerr << "unsupported type" << std::endl;
break;
}
}
//-----------------------------------------------------------------------------
bool _PLYReader_::read_ascii(std::istream& _in, BaseImporter& _bi, const Options& _opt) const {
unsigned int i, j, k, l, idx;
unsigned int nV;
OpenMesh::Vec3f v, n;
std::string trash;
OpenMesh::Vec2f t;
OpenMesh::Vec4i c;
float tmp;
BaseImporter::VHandles vhandles;
VertexHandle vh;
_bi.reserve(vertexCount_, 3* vertexCount_ , faceCount_);
if (vertexDimension_ != 3) {
omerr() << "[PLYReader] : Only vertex dimension 3 is supported." << std::endl;
return false;
}
const bool err_enabled = omerr().is_enabled();
size_t complex_faces = 0;
if (err_enabled)
omerr().disable();
for (std::vector<ElementInfo>::iterator e_it = elements_.begin(); e_it != elements_.end(); ++e_it)
{
if (_in.eof()) {
if (err_enabled)
omerr().enable();
omerr() << "Unexpected end of file while reading." << std::endl;
return false;
}
if (e_it->element_== VERTEX)
{
// read vertices:
for (i = 0; i < e_it->count_ && !_in.eof(); ++i) {
vh = _bi.add_vertex();
v[0] = 0.0;
v[1] = 0.0;
v[2] = 0.0;
n[0] = 0.0;
n[1] = 0.0;
n[2] = 0.0;
t[0] = 0.0;
t[1] = 0.0;
c[0] = 0;
c[1] = 0;
c[2] = 0;
c[3] = 255;
for (size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex) {
PropertyInfo prop = e_it->properties_[propertyIndex];
switch (prop.property) {
case XCOORD:
_in >> v[0];
break;
case YCOORD:
_in >> v[1];
break;
case ZCOORD:
_in >> v[2];
break;
case XNORM:
_in >> n[0];
break;
case YNORM:
_in >> n[1];
break;
case ZNORM:
_in >> n[2];
break;
case TEXX:
_in >> t[0];
break;
case TEXY:
_in >> t[1];
break;
case COLORRED:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
_in >> tmp;
c[0] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
}
else
_in >> c[0];
break;
case COLORGREEN:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
_in >> tmp;
c[1] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
}
else
_in >> c[1];
break;
case COLORBLUE:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
_in >> tmp;
c[2] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
}
else
_in >> c[2];
break;
case COLORALPHA:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
_in >> tmp;
c[3] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
}
else
_in >> c[3];
break;
case CUSTOM_PROP:
if (_opt.check(Options::Custom))
readCustomProperty<false>(_in, _bi, vh, prop.name, prop.value, prop.listIndexType);
else
_in >> trash;
break;
default:
_in >> trash;
break;
}
}
_bi.set_point(vh, v);
if (_opt.vertex_has_normal())
_bi.set_normal(vh, n);
if (_opt.vertex_has_texcoord())
_bi.set_texcoord(vh, t);
if (_opt.vertex_has_color())
_bi.set_color(vh, Vec4uc(c));
}
}
else if (e_it->element_ == FACE)
{
// faces
for (i = 0; i < faceCount_ && !_in.eof(); ++i) {
FaceHandle fh;
c[0] = 0;
c[1] = 0;
c[2] = 0;
c[3] = 255;
for (size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex) {
PropertyInfo prop = e_it->properties_[propertyIndex];
switch (prop.property) {
case VERTEX_INDICES:
// nV = number of Vertices for current face
_in >> nV;
if (nV == 3) {
vhandles.resize(3);
_in >> j;
_in >> k;
_in >> l;
vhandles[0] = VertexHandle(j);
vhandles[1] = VertexHandle(k);
vhandles[2] = VertexHandle(l);
}
else {
vhandles.clear();
for (j = 0; j < nV; ++j) {
_in >> idx;
vhandles.push_back(VertexHandle(idx));
}
}
fh = _bi.add_face(vhandles);
if (!fh.is_valid())
++complex_faces;
break;
case COLORRED:
if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
_in >> tmp;
c[0] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
} else
_in >> c[0];
break;
case COLORGREEN:
if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
_in >> tmp;
c[1] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
} else
_in >> c[1];
break;
case COLORBLUE:
if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
_in >> tmp;
c[2] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
} else
_in >> c[2];
break;
case COLORALPHA:
if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
_in >> tmp;
c[3] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
} else
_in >> c[3];
break;
case CUSTOM_PROP:
if (_opt.check(Options::Custom) && fh.is_valid())
readCustomProperty<false>(_in, _bi, fh, prop.name, prop.value, prop.listIndexType);
else
_in >> trash;
break;
default:
_in >> trash;
break;
}
}
if (_opt.face_has_color())
_bi.set_color(fh, Vec4uc(c));
}
}
else
{
// other elements
for (i = 0; i < e_it->count_ && !_in.eof(); ++i) {
for (size_t propertyIndex = 0; propertyIndex < e_it->properties_.size(); ++propertyIndex)
{
// just skip the values
_in >> trash;
}
}
}
if(e_it->element_== FACE)
// stop reading after the faces since additional elements are not preserved anyway
break;
}
if (err_enabled)
omerr().enable();
if (complex_faces)
omerr() << complex_faces << "The reader encountered invalid faces, that could not be added.\n";
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap*/, const Options& _opt) const {
OpenMesh::Vec3f v, n; // Vertex
OpenMesh::Vec2f t; // TexCoords
BaseImporter::VHandles vhandles;
VertexHandle vh;
OpenMesh::Vec4i c; // Color
float tmp;