Open
Description
bevy_gaussian_splatting/src/io/ply.rs
Line 175 in 7e0a353
// pad with empty gaussians to multiple of 32
let pad = 32 - (cloud.len() % 32);
cloud.extend(std::iter::repeat_n(Gaussian3d::default(), pad));
Ok(PlanarGaussian3d::from_interleaved(cloud))
}
impl PropertyAccess for Gaussian4d {
fn new() -> Self {
Gaussian4d::default()
}
fn set_property(&mut self, key: String, property: Property) {
match (key.as_ref(), property) {
("x", Property::Float(v)) => self.position_visibility.position[0] = v,
("y", Property::Float(v)) => self.position_visibility.position[1] = v,
("z", Property::Float(v)) => self.position_visibility.position[2] = v,
("visibility", Property::Float(v)) => self.position_visibility.visibility = v,
("t", Property::Float(v)) => self.timestamp_timescale.timestamp = v,
("st", Property::Float(v)) => self.timestamp_timescale.timescale = v,
(_, Property::Float(v)) if key.starts_with("feat_") => {
let channel = match key.chars().nth(5).unwrap() {
'r' => 0,
'g' => 1,
'b' => 2,
_ => panic!("invalid feature channel, expected r, g, or b"),
};
let i = key[7..].parse::<usize>().unwrap();
let interleaved_idx = i * SH_CHANNELS + channel;
if interleaved_idx < SH_4D_COEFF_COUNT {
self.spherindrical_harmonic.set(interleaved_idx, v);
} else {
// TODO: handle higher-degree if needed
}
}
("sx", Property::Float(v)) => self.scale_opacity.scale[0] = v,
("sy", Property::Float(v)) => self.scale_opacity.scale[1] = v,
("sz", Property::Float(v)) => self.scale_opacity.scale[2] = v,
("opacity", Property::Float(v)) => self.scale_opacity.opacity = v,
("rot_x", Property::Float(v)) => self.isotropic_rotations.rotation[0] = v,
("rot_y", Property::Float(v)) => self.isotropic_rotations.rotation[1] = v,
("rot_z", Property::Float(v)) => self.isotropic_rotations.rotation[2] = v,
("rot_w", Property::Float(v)) => self.isotropic_rotations.rotation[3] = v,
("rot_r_x", Property::Float(v)) => self.isotropic_rotations.rotation_r[0] = v,
("rot_r_y", Property::Float(v)) => self.isotropic_rotations.rotation_r[1] = v,
("rot_r_z", Property::Float(v)) => self.isotropic_rotations.rotation_r[2] = v,
("rot_r_w", Property::Float(v)) => self.isotropic_rotations.rotation_r[3] = v,
_ => {}
}
}
}
pub fn parse_ply_4d(
mut reader: &mut dyn BufRead,
) -> Result<PlanarGaussian4d, std::io::Error> {
let parser = Parser::<Gaussian4d>::new();
let header = parser.read_header(&mut reader)?;
let mut cloud = Vec::new();
let required_properties = vec![
"x", "y", "z",
"t", "st",
"sx", "sy", "sz",
"opacity",
"rot_x", "rot_y", "rot_z", "rot_w",
"rot_r_x", "rot_r_y", "rot_r_z", "rot_r_w",
];
let mut required_property_count = required_properties.len();
for (_key, element) in &header.elements {
if element.name == "vertex" {
for (key, _prop) in &element.properties {
required_property_count -= required_properties.contains(&key.as_str()) as usize;
}
if required_property_count > 0 {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "missing required properties"));
}
cloud = parser.read_payload_for_element(&mut reader, element, &header)?;
}
}
for g in &mut cloud {
let norm = g
.isotropic_rotations
.rotation
.iter()
.map(|v| v.powi(2))
.sum::<f32>()
.sqrt();
for v in &mut g.isotropic_rotations.rotation {
*v /= norm;
}
let norm = g
.isotropic_rotations
.rotation_r
.iter()
.map(|v| v.powi(2))
.sum::<f32>()
.sqrt();
for v in &mut g.isotropic_rotations.rotation_r {
*v /= norm;
}
// TODO: normalize timescale between 0 and 1
}
// pad to multiple of 32
let pad = 32 - (cloud.len() % 32);
cloud.extend(std::iter::repeat_n(Gaussian4d::default(), pad));
Ok(PlanarGaussian4d::from_interleaved(cloud))
}