- PLY Reader/Writer: Support for face colors (Thanks to Steve and Barb Demlow for the patch)

This commit is contained in:
Jan Möbius
2019-02-21 12:49:56 +01:00
parent a63cbdb10e
commit 3fbc166201
7 changed files with 362 additions and 30 deletions

View File

@@ -335,14 +335,14 @@ public:
Vec3f colorf(FaceHandle _fh) const override
{
return (mesh_.has_vertex_colors()
return (mesh_.has_face_colors()
? color_cast<Vec3f>(mesh_.color(_fh))
: Vec3f(0, 0, 0));
}
Vec4f colorAf(FaceHandle _fh) const override
{
return (mesh_.has_vertex_colors()
return (mesh_.has_face_colors()
? color_cast<Vec4f>(mesh_.color(_fh))
: Vec4f(0, 0, 0, 0));
}

View File

@@ -425,6 +425,12 @@ bool _PLYReader_::read_ascii(std::istream& _in, BaseImporter& _bi, const Options
// 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) {
@@ -456,6 +462,38 @@ bool _PLYReader_::read_ascii(std::istream& _in, BaseImporter& _bi, const Options
++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);
@@ -468,7 +506,8 @@ bool _PLYReader_::read_ascii(std::istream& _in, BaseImporter& _bi, const Options
break;
}
}
if (_opt.face_has_color())
_bi.set_color(fh, Vec4uc(c));
}
}
else
@@ -568,29 +607,26 @@ bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap
readValue(prop.value, _in, t[1]);
break;
case COLORRED:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
readValue(prop.value, _in, tmp);
if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
readValue(prop.value, _in, tmp);
c[0] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
c[0] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
}
else
readInteger(prop.value, _in, c[0]);
readInteger(prop.value, _in, c[0]);
break;
case COLORGREEN:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
readValue(prop.value, _in, tmp);
c[1] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
}
else
readInteger(prop.value, _in, c[1]);
if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
readValue(prop.value, _in, tmp);
c[1] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
}
else
readInteger(prop.value, _in, c[1]);
break;
case COLORBLUE:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
readValue(prop.value, _in, tmp);
c[2] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
}
@@ -599,8 +635,7 @@ bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap
break;
case COLORALPHA:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
if (prop.value == ValueTypeFLOAT32 || prop.value == ValueTypeFLOAT) {
readValue(prop.value, _in, tmp);
c[3] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
}
@@ -634,6 +669,12 @@ bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap
else if (e_it->element_ == FACE) {
for (unsigned i = 0; i < e_it->count_ && !_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];
@@ -668,7 +709,38 @@ bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap
if (!fh.is_valid())
++complex_faces;
break;
case COLORRED:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
readValue(prop.value, _in, tmp);
c[0] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
} else
readInteger(prop.value, _in, c[0]);
break;
case COLORGREEN:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
readValue(prop.value, _in, tmp);
c[1] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
} else
readInteger(prop.value, _in, c[1]);
break;
case COLORBLUE:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
readValue(prop.value, _in, tmp);
c[2] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
} else
readInteger(prop.value, _in, c[2]);
break;
case COLORALPHA:
if (prop.value == ValueTypeFLOAT32 ||
prop.value == ValueTypeFLOAT) {
readValue(prop.value, _in, tmp);
c[3] = static_cast<OpenMesh::Vec4i::value_type> (tmp * 255.0f);
} else
readInteger(prop.value, _in, c[3]);
break;
case CUSTOM_PROP:
if (_opt.check(Options::Custom) && fh.is_valid())
readCustomProperty<true>(_in, _bi, fh, prop.name, prop.value, prop.listIndexType);
@@ -681,6 +753,8 @@ bool _PLYReader_::read_binary(std::istream& _in, BaseImporter& _bi, bool /*_swap
break;
}
}
if (_opt.face_has_color())
_bi.set_color(fh, Vec4uc(c));
}
}
else {
@@ -1347,6 +1421,30 @@ bool _PLYReader_::can_u_read(std::istream& _is) const {
options_ += Options::ColorFloat;
}
}
else if (elementName == "face") {
if (propertyName == "red") {
entry = PropertyInfo(COLORRED, valueType);
options_ += Options::FaceColor;
if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
options_ += Options::ColorFloat;
} else if (propertyName == "green") {
entry = PropertyInfo(COLORGREEN, valueType);
options_ += Options::FaceColor;
if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
options_ += Options::ColorFloat;
} else if (propertyName == "blue") {
entry = PropertyInfo(COLORBLUE, valueType);
options_ += Options::FaceColor;
if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
options_ += Options::ColorFloat;
} else if (propertyName == "alpha") {
entry = PropertyInfo(COLORALPHA, valueType);
options_ += Options::FaceColor;
options_ += Options::ColorAlpha;
if (valueType == ValueTypeFLOAT || valueType == ValueTypeFLOAT32)
options_ += Options::ColorFloat;
}
}
//not a special property, load as custom
if (entry.value == Unsupported){

View File

@@ -122,14 +122,6 @@ write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize _preci
omerr() << "[PLYWriter] : Warning: Face normals are not supported and thus not exported! " << std::endl;
}
if ( _opt.check(Options::FaceColor) ) {
// Face normals are not supported
// Uncheck these options and output message that
// they are not written out even though they were requested
_opt.unset(Options::FaceColor);
omerr() << "[PLYWriter] : Warning: Face colors are not supported and thus not exported! " << std::endl;
}
options_ = _opt;
@@ -313,6 +305,24 @@ void _PLYWriter_::write_header(std::ostream& _out, BaseExporter& _be, Options& _
_out << "element face " << _be.n_faces() << '\n';
_out << "property list uchar int vertex_indices" << '\n';
if ( _opt.face_has_color() ){
if ( _opt.color_is_float() ) {
_out << "property float red" << '\n';
_out << "property float green" << '\n';
_out << "property float blue" << '\n';
if ( _opt.color_has_alpha() )
_out << "property float alpha" << '\n';
} else {
_out << "property uchar red" << '\n';
_out << "property uchar green" << '\n';
_out << "property uchar blue" << '\n';
if ( _opt.color_has_alpha() )
_out << "property uchar alpha" << '\n';
}
}
_ofProps = writeCustomTypeHeader(_out, _be.kernel()->fprops_begin(), _be.kernel()->fprops_end());
_out << "end_header" << '\n';
@@ -335,6 +345,7 @@ write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
OpenMesh::Vec4f cAf;
OpenMesh::Vec2f t;
VertexHandle vh;
FaceHandle fh;
std::vector<VertexHandle> vhandles;
std::vector<CustomProperty> vProps;
@@ -400,12 +411,37 @@ write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
// faces (indices starting at 0)
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
{
fh = FaceHandle(i);
// write vertex indices per face
nV = _be.get_vhandles(FaceHandle(i), vhandles);
nV = _be.get_vhandles(fh, vhandles);
_out << nV;
for (size_t j=0; j<vhandles.size(); ++j)
_out << " " << vhandles[j].idx();
// FaceColor
if ( _opt.face_has_color() ) {
//with alpha
if ( _opt.color_has_alpha() ){
if (_opt.color_is_float()) {
cAf = _be.colorAf(fh);
_out << " " << cAf;
} else {
cA = _be.colorAi(fh);
_out << " " << cA;
}
}else{
//without alpha
if (_opt.color_is_float()) {
cf = _be.colorf(fh);
_out << " " << cf;
} else {
c = _be.colori(fh);
_out << " " << c;
}
}
}
// write custom props
for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
write_customProp<false>(_out,*iter,i);
@@ -562,6 +598,7 @@ write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const
OpenMesh::Vec4uc c;
OpenMesh::Vec4f cf;
VertexHandle vh;
FaceHandle fh;
std::vector<VertexHandle> vhandles;
// vProps and fProps will be empty, until custom properties are supported by the binary writer
@@ -624,12 +661,35 @@ write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
{
fh = FaceHandle(i);
//face
nV = _be.get_vhandles(FaceHandle(i), vhandles);
nV = _be.get_vhandles(fh, vhandles);
writeValue(ValueTypeUINT8, _out, nV);
for (size_t j=0; j<vhandles.size(); ++j)
writeValue(ValueTypeINT32, _out, vhandles[j].idx() );
// face color
if ( _opt.face_has_color() ) {
if ( _opt.color_is_float() ) {
cf = _be.colorAf(fh);
writeValue(ValueTypeFLOAT, _out, cf[0]);
writeValue(ValueTypeFLOAT, _out, cf[1]);
writeValue(ValueTypeFLOAT, _out, cf[2]);
if ( _opt.color_has_alpha() )
writeValue(ValueTypeFLOAT, _out, cf[3]);
} else {
c = _be.colorA(fh);
writeValue(ValueTypeUCHAR, _out, (int)c[0]);
writeValue(ValueTypeUCHAR, _out, (int)c[1]);
writeValue(ValueTypeUCHAR, _out, (int)c[2]);
if ( _opt.color_has_alpha() )
writeValue(ValueTypeUCHAR, _out, (int)c[3]);
}
}
for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
write_customProp<true>(_out,*iter,i);
}

View File

@@ -82,6 +82,7 @@ namespace IO {
currently supported options:
- VertexColors
- FaceColors
- Binary
- Binary -> MSB
*/