Module lyon_tessellation::geometry_builder
[−]
[src]
Geometry builder
Tools to help with generating geometry to send to the GPU.
Overview
While it would be possible for the tessellation algorithms to manually generate vertex and index buffers with a certain layout, it would mean that most code using the tessellators would need to copy and convert all generated vertices in order to have their own vertex layout, or even several vertex layouts, which is a very common use-case.
In order to provide flexibility with the generation of geometry, this module provides with
the GeometryBuilder
and its extension the
BezierGeometryBuilder
trait. The former exposes
the methods to facilitate adding vertices and triangles. The latter adds a method to
specifically handle quadratic bezier curves. Quadratic bezier curves have interesting
properties that make them a lot easier to render than most types of curves and we want
to have the option to handle them separately in the renderer.
See the Rendering curves section in the project's wiki for more details about the advantages of handling quadratic bezier curves separately in the tessellator and the renderer.
This modules provides with a basic implementation of these traits through the following types:
- The struct
VertexBuffers<T>
is a simple pair of vectors of u16 indices and T (generic parameter) vertices. - The struct
BuffersBuilder
which implementsBezierGeometryBuilder
and writes into aVertexBuffers
. - The trait
VertexConstructor
used byBuffersBuilder
in order to generate any vertex type. In the example below, a structWithColor
implements theVertexConstructor
trait in order to create vertices composed of a 2d position and a color value from an input 2d position. This separates the construction of vertex values from the assembly of the vertex buffers. Another, simpler example of vertex constructor is theIdentity
constructor which just returns its input, untransformed.
Geometry builders are a practical way to add one last step to the tessellation pipeline, such as applying a transform or clipping the geometry.
While this is module designed to facilitate the generation of vertex buffers and index buffers, nothing prevents a given GeometryBuilder implementation to only generate a vertex buffer without indices, or write into a completely different format. These builder traits are at the end of the tessellation pipelines and are meant for users of this crate to be able to adapt the output of the tessellators to their own needs.
Examples
Generating custom vertices
The exampe below implements the VertexConstructor
trait in order to use a custom
vertex type MyVertex
(containing position and color), storing the tessellation in a
VertexBuffers<MyVertex>
, and tessellates two shapes with different colors.
extern crate lyon_tessellation; use lyon_tessellation::{VertexConstructor, VertexBuffers, BuffersBuilder, FillVertex}; use lyon_tessellation::basic_shapes::fill_circle; use lyon_tessellation::math::point; // Our custom vertex. #[derive(Copy, Clone, Debug)] pub struct MyVertex { position: [f32; 2], color: [f32; 4], } // The vertex constructor. This is the object that will be used to create the custom // verticex from the information provided by the tessellators. struct WithColor([f32; 4]); impl VertexConstructor<FillVertex, MyVertex> for WithColor { fn new_vertex(&mut self, vertex: FillVertex) -> MyVertex { // FillVertex also provides normals but we don't need it here. MyVertex { position: [ vertex.position.x, vertex.position.y, ], color: self.0, } } } fn main() { let mut output = VertexBuffers::new(); // Tessellate a red and a green circle. fill_circle( point(0.0, 0.0), 10.0, 0.05, &mut BuffersBuilder::new( &mut output, WithColor([1.0, 0.0, 0.0, 1.0]) ), ); fill_circle( point(10.0, 0.0), 5.0, 0.05, &mut BuffersBuilder::new( &mut output, WithColor([0.0, 1.0, 0.0, 1.0]) ), ); println!(" -- {} vertices, {} indices", output.vertices.len(), output.indices.len()); }
Generating a completely custom output
Using VertexBuffers<T>
is convenient and probably fits a lot of use cases, but
what if we do not want to write the geometry in a pair of vectors?
Perhaps we want to write the geometry in a different data structure or directly
into gpu-accessible buffers mapped on the CPU?
extern crate lyon_tessellation; use lyon_tessellation::{GeometryBuilder, Count}; use lyon_tessellation::geometry_builder::VertexId; use lyon_tessellation::basic_shapes::stroke_polyline; use lyon_tessellation::math::point; use std::fmt::Debug; // A geometry builder that writes the result of the tessellation to stdout instead // of filling vertex and index buffers. pub struct ToStdOut { vertices: u32, indices: u32, } impl ToStdOut { pub fn new() -> Self { ToStdOut { vertices: 0, indices: 0 } } } // This one takes any vertex type that implements Debug, so it will work with both // FillVertex and StrokeVertex. impl<Vertex: Debug> GeometryBuilder<Vertex> for ToStdOut { fn begin_geometry(&mut self) { // Reset the vertex in index counters. self.vertices = 0; self.indices = 0; println!(" -- begin geometry"); } fn end_geometry(&mut self) -> Count { println!(" -- end geometry, {} vertices, {} indices", self.vertices, self.indices); Count { vertices: self.vertices, indices: self.indices, } } fn add_vertex(&mut self, vertex: Vertex) -> VertexId { println!("vertex {:?}", vertex); self.vertices += 1; VertexId(self.vertices as u16 - 1) } fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) { println!("triangle ({}, {}, {})", a.offset(), b.offset(), c.offset()); self.indices += 3; } fn abort_geometry(&mut self) { println!(" -- oops!"); } } fn main() { let mut output = ToStdOut::new(); stroke_polyline( [point(0.0, 0.0), point(10.0, 0.0), point(5.0, 5.0)].iter().cloned(), true, &mut output, ); }
Writing a tessellator
The example below is the implementation of basic_shapes::fill_rectangle
.
use lyon_tessellation::geometry_builder::*; use lyon_tessellation::FillVertex; use lyon_tessellation::math::{Rect, vec2}; // A tessellator that generates an axis-aligned quad. // Returns a structure containing the number of vertices and number of indices allocated // during the execution of this method. pub fn fill_rectangle<Output>(rect: &Rect, output: &mut Output) -> Count where Output: GeometryBuilder<FillVertex> { output.begin_geometry(); // Create the vertices... let a = output.add_vertex( FillVertex { position: rect.origin, normal: vec2(-1.0, -1.0) } ); let b = output.add_vertex( FillVertex { position: rect.top_right(), normal: vec2(1.0, -1.0) } ); let c = output.add_vertex( FillVertex { position: rect.bottom_right(), normal: vec2(1.0, 1.0) } ); let d = output.add_vertex( FillVertex { position: rect.bottom_left(), normal: vec2(-1.0, 1.0) } ); // ...and create triangle form these points. a, b, c, and d are relative offsets in the // vertex buffer. output.add_triangle(a, b, c); output.add_triangle(a, c, d); return output.end_geometry(); }
Structs
BuffersBuilder |
A temporary view on a |
Count |
Number of vertices and indices added during the tessellation. |
Identity |
A dummy vertex constructor that just forwards its inputs. |
VertexBuffers |
Structure that holds the vertex and index data. |
VertexId |
A virtual vertex offset in a geometry. |
Traits
BezierGeometryBuilder |
An extension to GeometryBuilder that can handle quadratic bézier segments. |
GeometryBuilder |
An interface separating tessellators and other geometry generation algorithms from the actual vertex construction. |
VertexConstructor |
A trait specifying how to create vertex values. |
Functions
simple_builder |
Creates a |
vertex_builder |
Creates a |
Type Definitions
Index | |
SimpleBuffersBuilder |
A |