22SampleIO::read_file (std::string
const& filename,
SampleList* samples)
29 std::cout <<
"WARNING: No samples in file, skipping." << std::endl;
35 if (!mesh->has_vertex_normals())
36 throw std::invalid_argument(
"Vertex normals missing!");
39 if (!mesh->has_vertex_values())
40 throw std::invalid_argument(
"Vertex scale missing!");
43 if (!mesh->has_vertex_confidences())
45 std::cout <<
"INFO: No confidences given, setting to 1." << std::endl;
46 vconfs.resize(verts.size(), 1.0f);
49 if (!mesh->has_vertex_colors())
54 this->reset_samples_state(&state);
55 samples->reserve(verts.size());
56 for (std::size_t i = 0; i < verts.size(); i += 1)
59 sample.
pos = verts[i];
60 sample.
normal = vnormals[i];
61 sample.
scale = vvalues[i];
65 if (this->process_sample(&sample, &state))
66 samples->push_back(sample);
68 this->print_samples_state(&state);
72SampleIO::open_file (std::string
const& filename)
74 this->reset_stream_state();
75 this->reset_samples_state(&this->samples);
76 this->stream.filename = filename;
77 this->stream.stream.open(filename.c_str(), std::ios::binary);
78 if (!this->stream.stream.good())
83 std::getline(this->stream.stream, line);
86 this->reset_stream_state();
91 bool parsing_vertex_props =
false;
95 std::getline(this->stream.stream, line);
96 if (this->stream.stream.eof())
98 this->reset_stream_state();
102 if (!this->stream.stream.good())
104 this->reset_stream_state();
110 if (line ==
"end_header")
118 if (tokens.size() == 3 && tokens[0] ==
"format")
121 if (tokens[1] ==
"ascii")
123 else if (tokens[1] ==
"binary_little_endian")
125 else if (tokens[1] ==
"binary_big_endian")
130 if (tokens.size() == 3 && tokens[0] ==
"element")
132 if (tokens[1] ==
"vertex")
134 parsing_vertex_props =
true;
135 this->stream.num_vertices
136 = util::string::convert<unsigned int>(tokens[2]);
141 parsing_vertex_props =
false;
146 if (parsing_vertex_props && tokens[0] ==
"property")
148 if (tokens[1] ==
"float" && tokens[2] ==
"x")
150 else if (tokens[1] ==
"float" && tokens[2] ==
"y")
152 else if (tokens[1] ==
"float" && tokens[2] ==
"z")
154 else if (tokens[1] ==
"float" && tokens[2] ==
"nx")
156 else if (tokens[1] ==
"float" && tokens[2] ==
"ny")
158 else if (tokens[1] ==
"float" && tokens[2] ==
"nz")
160 else if (tokens[1] ==
"float" && tokens[2] ==
"confidence")
162 else if (tokens[1] ==
"float" && tokens[2] ==
"value")
164 else if (tokens[1] ==
"float" && (tokens[2] ==
"red"
165 || tokens[2] ==
"diffuse_red" || tokens[2] ==
"r"))
167 else if (tokens[1] ==
"float" && (tokens[2] ==
"green"
168 || tokens[2] ==
"diffuse_green" || tokens[2] ==
"g"))
170 else if (tokens[1] ==
"float" && (tokens[2] ==
"blue"
171 || tokens[2] ==
"diffuse_blue" || tokens[2] ==
"b"))
173 else if (tokens[1] ==
"uchar" && (tokens[2] ==
"red"
174 || tokens[2] ==
"diffuse_red" || tokens[2] ==
"r"))
176 else if (tokens[1] ==
"uchar" && (tokens[2] ==
"green"
177 || tokens[2] ==
"diffuse_green" || tokens[2] ==
"g"))
179 else if (tokens[1] ==
"uchar" && (tokens[2] ==
"blue"
180 || tokens[2] ==
"diffuse_blue" || tokens[2] ==
"b"))
182 else if (tokens[1] ==
"float")
184 else if (tokens[1] ==
"uchar")
186 else if (tokens[1] ==
"int")
190 this->reset_stream_state();
197 if (!parsing_vertex_props && tokens[0] ==
"property")
200 if (tokens[0] ==
"comment")
203 std::cerr <<
"Warning: Unrecognized PLY header: " << line << std::endl;
209 this->reset_stream_state();
214 if (this->stream.num_vertices == 0)
217 std::vector<bool> prop_table;
218 for (std::size_t i = 0; i < this->stream.props.size(); ++i)
221 if (prop_table.size() <
static_cast<std::size_t
>(prop + 1))
222 prop_table.resize(prop + 1,
false);
223 prop_table[prop] =
true;
230 this->reset_stream_state();
237 this->reset_stream_state();
242 this->reset_stream_state();
250 while (this->next_sample_intern(sample))
251 if (this->process_sample(sample, &this->samples))
257SampleIO::next_sample_intern (
Sample* sample)
259 if (this->stream.filename.empty())
260 throw std::runtime_error(
"Sample stream not initialized");
261 if (!this->stream.stream.good())
262 throw std::runtime_error(
"Sample stream broken");
263 if (this->stream.props.empty())
264 throw std::runtime_error(
"Invalid sample stream state");
269 if (this->stream.current_vertex == this->stream.num_vertices)
271 this->print_samples_state(&this->samples);
272 this->reset_samples_state(&this->samples);
273 this->reset_stream_state();
277 for (std::size_t i = 0; i < this->stream.props.size(); ++i)
283 this->ply_read(&sample->
pos[0]);
286 this->ply_read(&sample->
pos[1]);
289 this->ply_read(&sample->
pos[2]);
292 this->ply_read(&sample->
normal[0]);
295 this->ply_read(&sample->
normal[1]);
298 this->ply_read(&sample->
normal[2]);
301 this->ply_read(&sample->
color[0]);
304 this->ply_read(&sample->
color[1]);
307 this->ply_read(&sample->
color[2]);
310 this->ply_read_convert(&sample->
color[0]);
313 this->ply_read_convert(&sample->
color[1]);
316 this->ply_read_convert(&sample->
color[2]);
319 this->ply_read(&sample->
scale);
327 this->ply_read(&dummy);
333 this->ply_read(&dummy);
337 this->reset_stream_state();
338 throw std::runtime_error(
"Invalid sample attribute");
341 if (this->stream.stream.eof())
343 this->reset_stream_state();
348 this->stream.current_vertex += 1;
353SampleIO::ply_read (
float* value)
356 (this->stream.stream, this->stream.format);
360SampleIO::ply_read (uint8_t* value)
362 *value = mve::geom::ply_read_value<uint8_t>
363 (this->stream.stream, this->stream.format);
367SampleIO::ply_read_convert (
float* value)
370 this->ply_read(&temp);
371 *value =
static_cast<float>(temp) / 255.0f;
375SampleIO::reset_stream_state (
void)
377 this->stream.filename.clear();
378 this->stream.stream.close();
379 this->stream.props.clear();
381 this->stream.num_vertices = 0;
382 this->stream.current_vertex = 0;
386SampleIO::reset_samples_state (SamplesState* state)
388 state->num_skipped_zero_normal = 0;
389 state->num_skipped_invalid_confidence = 0;
390 state->num_skipped_invalid_scale = 0;
391 state->num_skipped_large_scale = 0;
392 state->num_unnormalized_normals = 0;
396SampleIO::process_sample (Sample* sample, SamplesState* state)
399 if (sample->scale <= 0.0f)
401 state->num_skipped_invalid_scale += 1;
404 if (sample->confidence <= 0.0f)
406 state->num_skipped_invalid_confidence += 1;
409 if (sample->normal.square_norm() == 0.0f)
411 state->num_skipped_zero_normal += 1;
416 if (this->opts.max_scale > 0.0f && sample->scale > this->opts.max_scale)
418 state->num_skipped_large_scale += 1;
422 if (this->opts.min_scale > 0.0f)
423 sample->scale = std::max(this->opts.min_scale, sample->scale);
424 sample->scale *= this->opts.scale_factor;
429 sample->normal.normalize();
430 state->num_unnormalized_normals += 1;
437SampleIO::print_samples_state (SamplesState* state)
439 if (state->num_skipped_invalid_scale > 0)
441 std::cout <<
"WARNING: Skipped "
442 << state->num_skipped_invalid_scale
443 <<
" samples with invalid scale." << std::endl;
445 if (state->num_skipped_invalid_confidence > 0)
447 std::cout <<
"WARNING: Skipped "
448 << state->num_skipped_invalid_confidence
449 <<
" samples with zero confidence." << std::endl;
451 if (state->num_skipped_zero_normal > 0)
453 std::cout <<
"WARNING: Skipped "
454 << state->num_skipped_zero_normal
455 <<
" samples with zero-length normal." << std::endl;
457 if (state->num_skipped_large_scale > 0)
459 std::cout <<
"WARNING: Skipped "
460 << state->num_skipped_large_scale
461 <<
" samples with too large scale." << std::endl;
463 if (state->num_unnormalized_normals > 0)
465 std::cout <<
"WARNING: Normalized "
466 << state->num_unnormalized_normals
467 <<
" normals with non-unit length." << std::endl;
Vector class for arbitrary dimensions and types.
std::vector< math::Vec3f > VertexList
std::vector< float > ConfidenceList
std::vector< math::Vec4f > ColorList
std::vector< float > ValueList
std::vector< math::Vec3f > NormalList
std::shared_ptr< TriangleMesh > Ptr
Universal, simple exception class.
Exception class for file exceptions with additional filename.
void split(std::string const &str, char delim=' ', bool keep_empty=false)
Very simple tokenziation at a given delimiter characater.
#define FSSR_NAMESPACE_END
#define FSSR_NAMESPACE_BEGIN
#define MATH_EPSILON_EQ(x, v, eps)
std::vector< Sample > SampleList
Representation of a list of samples.
TriangleMesh::Ptr load_ply_mesh(std::string const &filename)
Loads a triangle mesh from a PLY model file.
template float ply_read_value< float >(std::istream &input, PLYFormat format)
PLYVertexProperty
PLY vertex element properties.
void clip_newlines(std::string *str)
Clips newlines from the end of the string, in-place.
void clip_whitespaces(std::string *str)
Clips whitespaces from the front and end of the string, in-place.
Representation of a point sample.