Plexus is a Rust library for generating and manipulating 3D meshes.
Streams of topological and geometric data can be generated from primitives like
cubes and spheres using iterator expressions. Primitives emit topological
structures like Triangle
s or Quad
s, which contain arbitrary geometric data
in their vertices. These can be transformed and decomposed into other
topologies and geometric data via triangulation, tesselation, and other
operations.
```rust use nalgebra::Point3; use plexus::buffer::MeshBuffer; use plexus::generate::sphere; use plexus::prelude::*;
// Example module in the local crate that provides basic rendering. use render::{self, Color, Vertex};
// Construct a buffer of index and vertex data from a sphere primitive.
let buffer = sphere::UvSphere::new(16, 16)
.polygonswithposition()
.mapvertices(|position| -> Point3
For an example of rendering, see the viewer example.
Generators produce an ephemeral stream of topology and vertex geometry. A
Mesh
, represented as a half-edge
graph, supports
arbitrary geometry for vertices, edges, and faces. The graph can also be
traversed and manipulated in ways that generators and iterator expressions
cannot, such as circulation, extrusion, merging, and joining.
```rust use nalgebra::Point3; use plexus::generate::sphere; use plexus::graph::Mesh; use plexus::prelude::*;
// Construct a mesh from a sphere primitive. The vertex geometry is convertible
// to Point3
via the FromGeometry
trait in this example.
let mut mesh = sphere::UvSphere::new(8, 8)
.polygonswithposition()
.collect::
Plexus avoids exposing very basic topological operations like inserting individual vertices, because they can easily be done incorrectly and lead to invalid topologies. Instead, meshes are manipulated with higher-level operations like extrusion and joining.
Meshes support arbitrary geometry for vertices, edges, and faces (including no
geometry at all) via optional traits. Implementing these traits enables more
operations and features, but only two basic traits are required: Geometry
and
Attribute
.
```rust use nalgebra::{Point3, Vector3}; use plexus::geometry::{Attribute, Geometry}; use plexus::geometry::convert::AsPosition;
pub struct VertexGeometry {
pub position: Point3
impl Attribute for VertexGeometry {}
impl Geometry for VertexGeometry { type Vertex = Self; type Edge = (); type Face = (); }
impl AsPosition for VertexGeometry {
type Target = Point3
fn as_position(&self) -> &Self::Target {
&self.position
}
fn as_position_mut(&mut self) -> &mut Self::Target {
&mut self.position
}
} ```
Geometric traits are optionally implemented for types in the
nalgebra and
cgmath crates so that common types can be
used right away for vertex geometry. See the geometry-cgmath
and
geometry-nalgebra
(enabled by default) crate features. Both 2D and 3D
geometry are supported by mesh operations.
When collecting an iterator expression into a graph or buffer, an indexer is
used to transform the geometry into raw buffers. HashIndexer
is fast and
reliable, and is used by collect
(which can be overridden via
collect_with_indexer
). However, geometry often contains floating point
values, which do not implement Hash
. An LruIndexer
can also be used, but
may be slower and requires a sufficient capacity to work correctly.
The decorum crate is used to ease this
problem. Hashable types like NotNan
, Finite
, R32
, etc. can be used as
geometric data and are emitted by primitive generators like UvSphere
and
Cube
. Decorum can also be used to more easily make custom geometric data
hashable.