Skip to content

Commit

Permalink
When loading a .ply file, warn about ignored fields (#4934)
Browse files Browse the repository at this point in the history
### What
A `.ply` file can contain a lot of stuff, but we only support some of
it.

This PR adds warning to the user about everything that was in the `.ply`
file but couldn't be loaded (e.g. triangle faces, point normals, etc).

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using newly built examples:
[app.rerun.io](https://app.rerun.io/pr/4934/index.html)
* Using examples from latest `main` build:
[app.rerun.io](https://app.rerun.io/pr/4934/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[app.rerun.io](https://app.rerun.io/pr/4934/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG

- [PR Build Summary](https://build.rerun.io/pr/4934)
- [Docs
preview](https://rerun.io/preview/388b23b7a12c0af119e103bdbb534745fb336a1a/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/388b23b7a12c0af119e103bdbb534745fb336a1a/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)
  • Loading branch information
emilk authored Jan 29, 2024
1 parent 896ffcc commit ce1a096
Showing 1 changed file with 65 additions and 19 deletions.
84 changes: 65 additions & 19 deletions crates/re_types/src/archetypes/points3d_ext.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::BTreeSet;

use super::Points3D;

impl Points3D {
Expand All @@ -14,30 +16,38 @@ impl Points3D {
/// The media type will be inferred from the path (extension), or the contents if that fails.
#[cfg(not(target_arch = "wasm32"))]
pub fn from_file_path(filepath: &std::path::Path) -> anyhow::Result<Self> {
re_tracing::profile_function!(filepath.to_string_lossy());
use anyhow::Context as _;

let file = std::fs::File::open(filepath)
.with_context(|| format!("Failed to open file {filepath:?}"))?;
let mut file = std::io::BufReader::new(file);

let parser = ply_rs::parser::Parser::<ply_rs::ply::DefaultElement>::new();
let ply = parser.read_ply(&mut file)?;
let ply = {
re_tracing::profile_scope!("read_ply");
parser.read_ply(&mut file)?
};

Ok(from_ply(&ply))
Ok(from_ply(ply))
}

/// Creates a new [`Points3D`] from the contents of a `.ply` file.
///
/// If unspecified, he media type will be inferred from the contents.
pub fn from_file_contents(contents: &[u8]) -> anyhow::Result<Self> {
re_tracing::profile_function!();
let parser = ply_rs::parser::Parser::<ply_rs::ply::DefaultElement>::new();
let mut contents = std::io::Cursor::new(contents);
let ply = parser.read_ply(&mut contents)?;
Ok(from_ply(&ply))
let ply = {
re_tracing::profile_scope!("read_ply");
parser.read_ply(&mut contents)?
};
Ok(from_ply(ply))
}
}

fn from_ply(ply: &ply_rs::ply::Ply<ply_rs::ply::DefaultElement>) -> Points3D {
fn from_ply(ply: ply_rs::ply::Ply<ply_rs::ply::DefaultElement>) -> Points3D {
re_tracing::profile_function!();

use std::borrow::Cow;
Expand Down Expand Up @@ -119,7 +129,10 @@ fn from_ply(ply: &ply_rs::ply::Ply<ply_rs::ply::DefaultElement>) -> Points3D {

// TODO(cmc): This could be optimized by using custom property accessors.
impl Vertex {
fn from_props(props: &LinkedHashMap<String, Property>) -> Option<Vertex> {
fn from_props(
mut props: LinkedHashMap<String, Property>,
ignored_props: &mut BTreeSet<String>,
) -> Option<Vertex> {
// NOTE: Empirical evidence points to these being de-facto standard…
const PROP_X: &str = "x";
const PROP_Y: &str = "y";
Expand All @@ -136,9 +149,18 @@ fn from_ply(ply: &ply_rs::ply::Ply<ply_rs::ply::DefaultElement>) -> Points3D {
props.get(PROP_Y).and_then(f32),
props.get(PROP_Z).and_then(f32),
) else {
// All points much have positions.
for (key, _value) in props {
ignored_props.insert(key);
}
return None;
};

// We remove properties as they are read so we can warn about the ones we don't recognize.
props.remove(PROP_X);
props.remove(PROP_Y);
props.remove(PROP_Z);

let mut this = Self {
position: Position3D::new(x, y, z),
color: None,
Expand All @@ -152,15 +174,27 @@ fn from_ply(ply: &ply_rs::ply::Ply<ply_rs::ply::DefaultElement>) -> Points3D {
props.get(PROP_BLUE).and_then(u8),
) {
let a = props.get(PROP_ALPHA).and_then(u8).unwrap_or(255);

props.remove(PROP_RED);
props.remove(PROP_GREEN);
props.remove(PROP_BLUE);
props.remove(PROP_ALPHA);

this.color = Some(Color::new((r, g, b, a)));
};

if let Some(radius) = props.get(PROP_RADIUS).and_then(f32) {
props.remove(PROP_RADIUS);
this.radius = Some(Radius(radius));
}

if let Some(label) = props.get(PROP_LABEL).and_then(string) {
this.label = Some(Text(label.to_string().into()));
props.remove(PROP_LABEL);
}

for (key, _value) in props {
ignored_props.insert(key);
}

Some(this)
Expand All @@ -172,23 +206,35 @@ fn from_ply(ply: &ply_rs::ply::Ply<ply_rs::ply::DefaultElement>) -> Points3D {
let mut radii = Vec::new();
let mut labels = Vec::new();

for all_props in ply.payload.values() {
for props in all_props {
if let Some(vertex) = Vertex::from_props(props) {
let Vertex {
position,
color,
radius,
label,
} = vertex;
positions.push(position);
colors.push(color); // opt
radii.push(radius); // opt
labels.push(label); // opt
let mut ignored_props = BTreeSet::new();

for (key, all_props) in ply.payload {
if key == "vertex" {
for props in all_props {
if let Some(vertex) = Vertex::from_props(props, &mut ignored_props) {
let Vertex {
position,
color,
radius,
label,
} = vertex;
positions.push(position);
colors.push(color); // opt
radii.push(radius); // opt
labels.push(label); // opt
}
}
} else {
re_log::warn!("Ignoring {key:?} in .ply file");
}
}

if !ignored_props.is_empty() {
re_log::warn!("Ignored properties of .ply file: {ignored_props:?}");
}

re_tracing::profile_scope!("fill-in");

colors.truncate(positions.len());
radii.truncate(positions.len());
labels.truncate(positions.len());
Expand Down

0 comments on commit ce1a096

Please sign in to comment.