Skip to content

potocpav/rust-ply

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PLY file loading library in Rust

This library (written in the Rust language) can load a PLY file and store its contents in structure(s). The serialization code is generated by a compiler plugin for simple use-cases. This ensures maximum safety (the file contents must match the structures) while avoiding the boilerplate.

About the PLY format

PLY is a computer file format known as the Polygon File Format or the Stanford Triangle Format. PLY is a simple yet powerful format designed to store three-dimensional data. It's main advantage over comparable formats (wavefront obj comes to mind) is its modularity: it can be used to store arbitrary data associated to vertices, edges or faces. This is very useful for shader attributes, skeletal animation, description of surface quality and others. PLY can be exported by blender. The full description of the format is here.

Usage

Add this to the crate root:

#![feature(plugin)]

#![plugin(ply_plugins)]
extern crate ply_plugins;
extern crate ply;

As an example, we will parse a simple file describing a cube:

ply             // These comments are not a part of a valid PLY file!
format ascii 1.0     // Header section
element vertex 8     // Each PLY file consists of elements
property float x     // Each element consists of properties  
property float y     // Each property has a type and a name
property float z
element face 6
property list uchar int vertex_index
end_header           // Data section
0 0 0                // Each line corresponds to an element
0 0 1                // The first 8 lines are the vertices
0 1 1
0 1 0
1 0 0
1 0 1
1 1 1
1 1 0
4 0 1 2 3            // These 6 lines are the faces
4 7 6 5 4
4 0 4 5 1
4 1 5 6 2
4 2 6 7 3
4 3 7 4 0

The genericity of the PLY format is now obvious: there can be any number of properties and elements of any types and names.

We create the structures that can be used to store the elements of the cube:

#[derive(Debug,Copy)]
#[ply_element]
pub struct Vertex {
	x: f32, y: f32, z: f32,
}

#[derive(Debug)]
#[ply_element]
pub struct Face {
	vertex_index: Vec<i32>,
};

The #[ply_element] lines create implementations of the ply::Element trait, so we can easily deserialize the data. These implementations check that the mapping from the PLY file to the structures is correct (types and names match), and provides a function ply::Element::parse that does the conversion from an AST to a structure.

Now, we can specify a structure that holds the whole model:

#[derive(Debug)]
#[ply_model]
struct Model {
	vertex: Vec<Vertex>,
	face: Vec<Face>,
}

The #[ply_model] line creates an implementation of the ply::Model trait, that contains the first function that we are actually going to use in this simple example:

ply::Model::new(&ply::PLY) -> Result<Self,String>

Now that the structures are specified, we are free to do some parsing:

fn main() {
	match ply::parse(PLY) { // Create an AST
		Ok(ref ply) => {
			// Fill in the structure from the AST
			let model: Result<Model,_> = ply::Model::new(ply);
			// Print the result
			println!("\nResult: {:?}", model);
		},
		Err(e) => println!("Error while parsing:\n{}", e),
	}
}

The output is (line breaks and tabs added for clarity):

Result: Ok(
	Model {
		vertex:
			[ Vertex { x: 0, y: 0, z: 0 }
			, Vertex { x: 0, y: 0, z: 1 }
			, Vertex { x: 0, y: 1, z: 1 }
			, Vertex { x: 0, y: 1, z: 0 }
			, Vertex { x: 1, y: 0, z: 0 }
			, Vertex { x: 1, y: 0, z: 1 }
			, Vertex { x: 1, y: 1, z: 1 }
			, Vertex { x: 1, y: 1, z: 0 }
			],
		face:
			[ Face { vertex_index: [0, 1, 2, 3] }
			, Face { vertex_index: [7, 6, 5, 4] }
			, Face { vertex_index: [0, 4, 5, 1] }
			, Face { vertex_index: [1, 5, 6, 2] }
			, Face { vertex_index: [2, 6, 7, 3] }
			, Face { vertex_index: [3, 7, 4, 0] }
			]
		}
	)

The whole code of this example is in the example simple.rs. For more involved examples, see the examples.

About

PLY file loader written in Rust.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages