+ improve ply support
This commit is contained in:
parent
8c38e25377
commit
202b51171c
|
@ -42,8 +42,10 @@
|
|||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
|
||||
using namespace MeshCore;
|
||||
|
@ -493,6 +495,18 @@ bool MeshInput::LoadOFF (std::istream &rstrIn)
|
|||
return true;
|
||||
}
|
||||
|
||||
namespace MeshCore {
|
||||
struct MeshPly_Property : public std::binary_function<std::pair<std::string, int>,
|
||||
std::string, bool>
|
||||
{
|
||||
bool operator()(const std::pair<std::string, int>& x,
|
||||
const std::string& y) const
|
||||
{
|
||||
return x.first == y;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool MeshInput::LoadPLY (std::istream &inp)
|
||||
{
|
||||
// http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/
|
||||
|
@ -503,6 +517,11 @@ bool MeshInput::LoadPLY (std::istream &inp)
|
|||
enum {
|
||||
ascii, binary_little_endian, binary_big_endian
|
||||
} format;
|
||||
|
||||
enum Number {
|
||||
int8, uint8, int16, uint16, int32, uint32, float32, float64
|
||||
};
|
||||
|
||||
if (!inp || inp.bad() == true)
|
||||
return false;
|
||||
|
||||
|
@ -519,10 +538,10 @@ bool MeshInput::LoadPLY (std::istream &inp)
|
|||
if ((ply[0] != 'p') || (ply[1] != 'l') || (ply[2] != 'y'))
|
||||
return false; // wrong header
|
||||
|
||||
std::vector<int> face_props;
|
||||
std::vector<std::pair<std::string, Number> > vertex_props;
|
||||
std::vector<Number> face_props;
|
||||
std::string line, element;
|
||||
bool xyz_float=false,xyz_double=false;
|
||||
int xyz_coords=0;
|
||||
|
||||
MeshIO::Binding rgb_value = MeshIO::OVERALL;
|
||||
while (std::getline(inp, line)) {
|
||||
std::istringstream str(line);
|
||||
|
@ -593,37 +612,86 @@ bool MeshInput::LoadPLY (std::istream &inp)
|
|||
if (element == "vertex") {
|
||||
str >> space >> std::ws
|
||||
>> type >> space >> std::ws >> name >> std::ws;
|
||||
if (name == "x") {
|
||||
xyz_coords++;
|
||||
if (type == "float" || type == "float32")
|
||||
xyz_float = true;
|
||||
else if (type == "double" || type == "float64")
|
||||
xyz_double = true;
|
||||
|
||||
Number number;
|
||||
if (type == "char" || type == "int8") {
|
||||
number = int8;
|
||||
}
|
||||
else if (name == "y") {
|
||||
xyz_coords++;
|
||||
else if (type == "uchar" || type == "uint8") {
|
||||
number = uint8;
|
||||
}
|
||||
else if (name == "z") {
|
||||
xyz_coords++;
|
||||
else if (type == "short" || type == "int16") {
|
||||
number = int16;
|
||||
}
|
||||
else if (name == "red") {
|
||||
rgb_value = MeshIO::PER_VERTEX;
|
||||
if (_material) {
|
||||
_material->binding = MeshIO::PER_VERTEX;
|
||||
_material->diffuseColor.reserve(v_count);
|
||||
}
|
||||
else if (type == "ushort" || type == "uint16") {
|
||||
number = uint16;
|
||||
}
|
||||
else if (type == "int" || type == "int32") {
|
||||
number = int32;
|
||||
}
|
||||
else if (type == "uint" || type == "uint32") {
|
||||
number = uint32;
|
||||
}
|
||||
else if (type == "float" || type == "float32") {
|
||||
number = float32;
|
||||
}
|
||||
else if (type == "double" || type == "float64") {
|
||||
number = float64;
|
||||
}
|
||||
else {
|
||||
// no valid number type
|
||||
return false;
|
||||
}
|
||||
|
||||
// store the property name and type
|
||||
vertex_props.push_back(std::make_pair(name, number));
|
||||
}
|
||||
else if (element == "face") {
|
||||
std::string list, uchr;
|
||||
str >> space >> std::ws
|
||||
>> list >> std::ws >> uchr >> std::ws
|
||||
>> type >> std::ws >> name >> std::ws;
|
||||
if (name != "vertex_indices") {
|
||||
if (type == "float" || type == "float32")
|
||||
face_props.push_back(4);
|
||||
else if (type == "double" || type == "float64")
|
||||
face_props.push_back(8);
|
||||
>> list >> std::ws;
|
||||
if (list == "list") {
|
||||
str >> uchr >> std::ws
|
||||
>> type >> std::ws >> name >> std::ws;
|
||||
}
|
||||
else {
|
||||
// not a 'list'
|
||||
type = list;
|
||||
str >> name;
|
||||
}
|
||||
if (name != "vertex_indices" && name != "vertex_index") {
|
||||
Number number;
|
||||
if (type == "char" || type == "int8") {
|
||||
number = int8;
|
||||
}
|
||||
else if (type == "uchar" || type == "uint8") {
|
||||
number = uint8;
|
||||
}
|
||||
else if (type == "short" || type == "int16") {
|
||||
number = int16;
|
||||
}
|
||||
else if (type == "ushort" || type == "uint16") {
|
||||
number = uint16;
|
||||
}
|
||||
else if (type == "int" || type == "int32") {
|
||||
number = int32;
|
||||
}
|
||||
else if (type == "uint" || type == "uint32") {
|
||||
number = uint32;
|
||||
}
|
||||
else if (type == "float" || type == "float32") {
|
||||
number = float32;
|
||||
}
|
||||
else if (type == "double" || type == "float64") {
|
||||
number = float64;
|
||||
}
|
||||
else {
|
||||
// no valid number type
|
||||
return false;
|
||||
}
|
||||
|
||||
// store the property name and type
|
||||
face_props.push_back(number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -632,64 +700,121 @@ bool MeshInput::LoadPLY (std::istream &inp)
|
|||
}
|
||||
}
|
||||
|
||||
// not 3d points
|
||||
if (xyz_coords != 3)
|
||||
// check if valid 3d points
|
||||
MeshPly_Property property;
|
||||
std::size_t num_x = std::count_if(vertex_props.begin(), vertex_props.end(),
|
||||
std::bind2nd(property, "x"));
|
||||
if (num_x != 1)
|
||||
return false;
|
||||
|
||||
if (format == ascii) {
|
||||
boost::regex rx_p("^([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
|
||||
"\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
|
||||
"\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)\\s*$");
|
||||
boost::regex rx_c("^([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
|
||||
"\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
|
||||
"\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
|
||||
"\\s+([0-9]{1,3})\\s+([0-9]{1,3})\\s+([0-9]{1,3})\\s*$");
|
||||
boost::regex rx_f("^\\s*3\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*");
|
||||
boost::cmatch what;
|
||||
Base::Vector3f pt;
|
||||
std::size_t num_y = std::count_if(vertex_props.begin(), vertex_props.end(),
|
||||
std::bind2nd(property, "y"));
|
||||
if (num_y != 1)
|
||||
return false;
|
||||
|
||||
if (rgb_value == MeshIO::PER_VERTEX) {
|
||||
int r,g,b;
|
||||
for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) {
|
||||
if (boost::regex_match(line.c_str(), what, rx_c)) {
|
||||
pt.x = (float)std::atof(what[1].first);
|
||||
pt.y = (float)std::atof(what[4].first);
|
||||
pt.z = (float)std::atof(what[7].first);
|
||||
meshPoints.push_back(pt);
|
||||
if (_material) {
|
||||
r = std::min<int>(std::atoi(what[10].first),255);
|
||||
g = std::min<int>(std::atoi(what[11].first),255);
|
||||
b = std::min<int>(std::atoi(what[12].first),255);
|
||||
float fr = (float)r/255.0f;
|
||||
float fg = (float)g/255.0f;
|
||||
float fb = (float)b/255.0f;
|
||||
_material->diffuseColor.push_back(App::Color(fr, fg, fb));
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::size_t num_z = std::count_if(vertex_props.begin(), vertex_props.end(),
|
||||
std::bind2nd(property, "z"));
|
||||
if (num_z != 1)
|
||||
return false;
|
||||
|
||||
// check if valid colors are set
|
||||
std::size_t num_r = std::count_if(vertex_props.begin(), vertex_props.end(),
|
||||
std::bind2nd(property, "red"));
|
||||
std::size_t num_g = std::count_if(vertex_props.begin(), vertex_props.end(),
|
||||
std::bind2nd(property, "green"));
|
||||
std::size_t num_b = std::count_if(vertex_props.begin(), vertex_props.end(),
|
||||
std::bind2nd(property, "blue"));
|
||||
std::size_t rgb_colors = num_r + num_g + num_b;
|
||||
if (rgb_colors != 0 && rgb_colors != 3)
|
||||
return false;
|
||||
|
||||
// only if set per vertex
|
||||
if (rgb_colors == 3) {
|
||||
rgb_value = MeshIO::PER_VERTEX;
|
||||
if (_material) {
|
||||
_material->binding = MeshIO::PER_VERTEX;
|
||||
_material->diffuseColor.reserve(v_count);
|
||||
}
|
||||
}
|
||||
|
||||
if (format == ascii) {
|
||||
boost::regex rx_d("(([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?))\\s*");
|
||||
boost::regex rx_s("\\b([-+]?[0-9]+)\\s*");
|
||||
boost::regex rx_u("\\b([0-9]+)\\s*");
|
||||
boost::regex rx_f("^\\s*3\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*");
|
||||
boost::smatch what;
|
||||
|
||||
for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) {
|
||||
// go through the vertex properties
|
||||
std::map<std::string, float> prop_values;
|
||||
for (std::vector<std::pair<std::string, Number> >::iterator it = vertex_props.begin(); it != vertex_props.end(); ++it) {
|
||||
switch (it->second) {
|
||||
case int8:
|
||||
case int16:
|
||||
case int32:
|
||||
{
|
||||
if (boost::regex_search(line, what, rx_s)) {
|
||||
int v;
|
||||
v = boost::lexical_cast<int>(what[1]);
|
||||
prop_values[it->first] = static_cast<float>(v);
|
||||
line = line.substr(what[0].length());
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
case uint8:
|
||||
case uint16:
|
||||
case uint32:
|
||||
{
|
||||
if (boost::regex_search(line, what, rx_u)) {
|
||||
int v;
|
||||
v = boost::lexical_cast<int>(what[1]);
|
||||
prop_values[it->first] = static_cast<float>(v);
|
||||
line = line.substr(what[0].length());
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
case float32:
|
||||
case float64:
|
||||
{
|
||||
if (boost::regex_search(line, what, rx_d)) {
|
||||
double v;
|
||||
v = boost::lexical_cast<double>(what[1]);
|
||||
prop_values[it->first] = static_cast<float>(v);
|
||||
line = line.substr(what[0].length());
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) {
|
||||
if (boost::regex_match(line.c_str(), what, rx_p)) {
|
||||
pt.x = (float)std::atof(what[1].first);
|
||||
pt.y = (float)std::atof(what[4].first);
|
||||
pt.z = (float)std::atof(what[7].first);
|
||||
meshPoints.push_back(pt);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
Base::Vector3f pt;
|
||||
pt.x = (prop_values["x"]);
|
||||
pt.y = (prop_values["y"]);
|
||||
pt.z = (prop_values["z"]);
|
||||
meshPoints.push_back(pt);
|
||||
|
||||
if (_material && (rgb_value == MeshIO::PER_VERTEX)) {
|
||||
float r = (prop_values["red"]) / 255.0f;
|
||||
float g = (prop_values["green"]) / 255.0f;
|
||||
float b = (prop_values["blue"]) / 255.0f;
|
||||
_material->diffuseColor.push_back(App::Color(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
int f1, f2, f3;
|
||||
for (std::size_t i = 0; i < f_count && std::getline(inp, line); i++) {
|
||||
if (boost::regex_search(line.c_str(), what, rx_f)) {
|
||||
f1 = std::atoi(what[1].first);
|
||||
f2 = std::atoi(what[2].first);
|
||||
f3 = std::atoi(what[3].first);
|
||||
if (boost::regex_search(line, what, rx_f)) {
|
||||
f1 = boost::lexical_cast<int>(what[1]);
|
||||
f2 = boost::lexical_cast<int>(what[2]);
|
||||
f3 = boost::lexical_cast<int>(what[3]);
|
||||
meshFacets.push_back(MeshFacet(f1,f2,f3));
|
||||
}
|
||||
}
|
||||
|
@ -701,39 +826,71 @@ bool MeshInput::LoadPLY (std::istream &inp)
|
|||
is.setByteOrder(Base::Stream::LittleEndian);
|
||||
else
|
||||
is.setByteOrder(Base::Stream::BigEndian);
|
||||
int r,g,b;
|
||||
if (xyz_float) {
|
||||
|
||||
for (std::size_t i = 0; i < v_count; i++) {
|
||||
// go through the vertex properties
|
||||
std::map<std::string, float> prop_values;
|
||||
for (std::vector<std::pair<std::string, Number> >::iterator it = vertex_props.begin(); it != vertex_props.end(); ++it) {
|
||||
switch (it->second) {
|
||||
case int8:
|
||||
{
|
||||
int8_t v; is >> v;
|
||||
prop_values[it->first] = static_cast<float>(v);
|
||||
} break;
|
||||
case uint8:
|
||||
{
|
||||
uint8_t v; is >> v;
|
||||
prop_values[it->first] = static_cast<float>(v);
|
||||
} break;
|
||||
case int16:
|
||||
{
|
||||
int16_t v; is >> v;
|
||||
prop_values[it->first] = static_cast<float>(v);
|
||||
} break;
|
||||
case uint16:
|
||||
{
|
||||
uint16_t v; is >> v;
|
||||
prop_values[it->first] = static_cast<float>(v);
|
||||
} break;
|
||||
case int32:
|
||||
{
|
||||
int32_t v; is >> v;
|
||||
prop_values[it->first] = static_cast<float>(v);
|
||||
} break;
|
||||
case uint32:
|
||||
{
|
||||
uint32_t v; is >> v;
|
||||
prop_values[it->first] = static_cast<float>(v);
|
||||
} break;
|
||||
case float32:
|
||||
{
|
||||
float v; is >> v;
|
||||
prop_values[it->first] = v;
|
||||
} break;
|
||||
case float64:
|
||||
{
|
||||
double v; is >> v;
|
||||
prop_values[it->first] = static_cast<float>(v);
|
||||
} break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Base::Vector3f pt;
|
||||
for (std::size_t i = 0; i < v_count; i++) {
|
||||
is >> pt.x >> pt.y >> pt.z;
|
||||
meshPoints.push_back(pt);
|
||||
if (rgb_value == MeshIO::PER_VERTEX) {
|
||||
is >> r >> g >> b;
|
||||
if (_material) {
|
||||
float fr = (float)r/255.0f;
|
||||
float fg = (float)g/255.0f;
|
||||
float fb = (float)b/255.0f;
|
||||
_material->diffuseColor.push_back(App::Color(fr, fg, fb));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (xyz_double) {
|
||||
Base::Vector3d pt;
|
||||
for (std::size_t i = 0; i < v_count; i++) {
|
||||
is >> pt.x >> pt.y >> pt.z;
|
||||
meshPoints.push_back(Base::Vector3f((float)pt.x,(float)pt.y,(float)pt.z));
|
||||
if (rgb_value == MeshIO::PER_VERTEX) {
|
||||
is >> r >> g >> b;
|
||||
if (_material) {
|
||||
float fr = (float)r/255.0f;
|
||||
float fg = (float)g/255.0f;
|
||||
float fb = (float)b/255.0f;
|
||||
_material->diffuseColor.push_back(App::Color(fr, fg, fb));
|
||||
}
|
||||
}
|
||||
pt.x = (prop_values["x"]);
|
||||
pt.y = (prop_values["y"]);
|
||||
pt.z = (prop_values["z"]);
|
||||
meshPoints.push_back(pt);
|
||||
|
||||
if (_material && (rgb_value == MeshIO::PER_VERTEX)) {
|
||||
float r = (prop_values["red"]) / 255.0f;
|
||||
float g = (prop_values["green"]) / 255.0f;
|
||||
float b = (prop_values["blue"]) / 255.0f;
|
||||
_material->diffuseColor.push_back(App::Color(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char n;
|
||||
uint32_t f1, f2, f3;
|
||||
for (std::size_t i = 0; i < f_count; i++) {
|
||||
|
@ -742,18 +899,48 @@ bool MeshInput::LoadPLY (std::istream &inp)
|
|||
is >> f1 >> f2 >> f3;
|
||||
if (f1 < v_count && f2 < v_count && f3 < v_count)
|
||||
meshFacets.push_back(MeshFacet(f1,f2,f3));
|
||||
for (std::vector<int>::iterator it = face_props.begin(); it != face_props.end(); ++it) {
|
||||
if (*it == 4) {
|
||||
is >> n;
|
||||
float f;
|
||||
for (unsigned char j=0; j<n; j++)
|
||||
is >> f;
|
||||
}
|
||||
else if (*it == 8) {
|
||||
is >> n;
|
||||
double d;
|
||||
for (unsigned char j=0; j<n; j++)
|
||||
is >> d;
|
||||
for (std::vector<Number>::iterator it = face_props.begin(); it != face_props.end(); ++it) {
|
||||
switch (*it) {
|
||||
case int8:
|
||||
{
|
||||
int8_t v; is >> v;
|
||||
} break;
|
||||
case uint8:
|
||||
{
|
||||
uint8_t v; is >> v;
|
||||
} break;
|
||||
case int16:
|
||||
{
|
||||
int16_t v; is >> v;
|
||||
} break;
|
||||
case uint16:
|
||||
{
|
||||
uint16_t v; is >> v;
|
||||
} break;
|
||||
case int32:
|
||||
{
|
||||
int32_t v; is >> v;
|
||||
} break;
|
||||
case uint32:
|
||||
{
|
||||
uint32_t v; is >> v;
|
||||
} break;
|
||||
case float32:
|
||||
{
|
||||
is >> n;
|
||||
float v;
|
||||
for (unsigned char j=0; j<n; j++)
|
||||
is >> v;
|
||||
} break;
|
||||
case float64:
|
||||
{
|
||||
is >> n;
|
||||
double v;
|
||||
for (unsigned char j=0; j<n; j++)
|
||||
is >> v;
|
||||
} break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user