lyon_tessellation/
geometry_builder.rs

1//! Tools to help with generating vertex and index buffers.
2//!
3//! ## Overview
4//!
5//! While it would be possible for the tessellation algorithms to manually generate vertex
6//! and index buffers with a certain layout, it would mean that most code using the tessellators
7//! have to copy and convert all generated vertices in order to have their own vertex
8//! layout, or de-interleaved vertex formats, which is a very common use-case.
9//!
10//! In order to flexibly and efficiently build geometry of various flavors, this module contains
11//! a number of builder interfaces that centered around the idea of building vertex and index
12//! buffers without having to know about the final vertex and index types.
13//!
14//! See:
15//!
16//! * [`GeometryBuilder`](trait.GeometryBuilder.html)
17//! * [`FillGeometryBuilder`](trait.FillGeometryBuilder.html)
18//! * [`StrokeGeometryBuilder`](trait.StrokeGeometryBuilder.html)
19//!
20//! The traits above are what the tessellators interface with. It is very common to push
21//! vertices and indices into a pair of vectors, so to facilitate this pattern this module
22//! also provides:
23//!
24//! * The struct [`VertexBuffers`](struct.VertexBuffers.html) is a simple pair of vectors of
25//!   indices and vertices (generic parameters).
26//! * The struct [`BuffersBuilder`](struct.BuffersBuilder.html) which writes into a
27//!   [`VertexBuffers`](struct.VertexBuffers.html) and implements the various geometry
28//!   builder traits. It takes care of filling the buffers while producing vertices is
29//!   delegated to a vertex constructor.
30//! * The traits [`FillVertexConstructor`](trait.FillVertexConstructor.html),
31//!   [`StrokeVertexConstructor`](trait.StrokeVertexConstructor.html) and
32//!   [`BuffersBuilder`](struct.BuffersBuilder.html) in order to generate any vertex type. In the
33//!   first example below, a struct `WithColor` implements the `FillVertexConstructor` trait in order to
34//!   create vertices composed of a 2d position and a color value from an input 2d position.
35//!   This separates the construction of vertex values from the assembly of the vertex buffers.
36//!   Another, simpler example of vertex constructor is the [`Positions`](struct.Positions.html)
37//!   constructor which just returns the vertex position untransformed.
38//!
39//! Geometry builders are a practical way to add one last step to the tessellation pipeline,
40//! such as applying a transform or clipping the geometry.
41//!
42//! While this is module designed to facilitate the generation of vertex buffers and index
43//! buffers, nothing prevents a given GeometryBuilder implementation to only generate a
44//! vertex buffer without indices, or write into a completely different format.
45//! These builder traits are at the end of the tessellation pipelines and are meant for
46//! users of this crate to be able to adapt the output of the tessellators to their own
47//! needs.
48//!
49//! ## Do I need to implement geometry builders or vertex constructors?
50//!
51//! If you only generate a vertex buffer and an index buffer (as a pair of standard `Vec`),
52//! then the simplest option is to work with custom vertex constructors and use
53//! `VertexBuffers` and `BuffersBuilder`.
54//!
55//! For more specific or elaborate use cases where control over where the vertices as written
56//! is needed such as building de-interleaved vertex buffers or writing directly into a mapped
57//! GPU buffer, implementing custom geometry builders is the right thing to do.
58//!
59//! Which of the vertex constructor or geometry builder traits to implement (fill/stroke/basic
60//! variants), depends on which tessellators the builder or constructor will interface with.
61//!
62//! ## Examples
63//!
64//! ### Generating custom vertices
65//!
66//! The example below implements the `FillVertexConstructor` trait in order to use a custom
67//! vertex type `MyVertex` (containing position and color), storing the tessellation in a
68//! `VertexBuffers<MyVertex, u16>`, and tessellates two shapes with different colors.
69//!
70//! ```
71//! extern crate lyon_tessellation as tess;
72//! use tess::{FillVertexConstructor, VertexBuffers, BuffersBuilder, FillOptions, FillTessellator, FillVertex};
73//! use tess::math::{Point, point};
74//!
75//! // Our custom vertex.
76//! #[derive(Copy, Clone, Debug)]
77//! pub struct MyVertex {
78//!   position: [f32; 2],
79//!   color: [f32; 4],
80//! }
81//!
82//! // The vertex constructor. This is the object that will be used to create the custom
83//! // vertices from the information provided by the tessellators.
84//! struct WithColor([f32; 4]);
85//!
86//! impl FillVertexConstructor<MyVertex> for WithColor {
87//!     fn new_vertex(&mut self, vertex: FillVertex) -> MyVertex {
88//!         MyVertex {
89//!             position: vertex.position().to_array(),
90//!             color: self.0,
91//!         }
92//!     }
93//! }
94//!
95//! fn main() {
96//!     let mut output: VertexBuffers<MyVertex, u16> = VertexBuffers::new();
97//!     let mut tessellator = FillTessellator::new();
98//!     // Tessellate a red and a green circle.
99//!     tessellator.tessellate_circle(
100//!         point(0.0, 0.0),
101//!         10.0,
102//!         &FillOptions::tolerance(0.05),
103//!         &mut BuffersBuilder::new(
104//!             &mut output,
105//!             WithColor([1.0, 0.0, 0.0, 1.0])
106//!         ),
107//!     );
108//!     tessellator.tessellate_circle(
109//!         point(10.0, 0.0),
110//!         5.0,
111//!         &FillOptions::tolerance(0.05),
112//!         &mut BuffersBuilder::new(
113//!             &mut output,
114//!             WithColor([0.0, 1.0, 0.0, 1.0])
115//!         ),
116//!     );
117//!
118//!     println!(" -- {} vertices, {} indices", output.vertices.len(), output.indices.len());
119//! }
120//! ```
121//!
122//! ### Generating a completely custom output
123//!
124//! Using `VertexBuffers<T>` is convenient and probably fits a lot of use cases, but
125//! what if we do not want to write the geometry in a pair of vectors?
126//! Perhaps we want to write the geometry in a different data structure or directly
127//! into gpu-accessible buffers mapped on the CPU?
128//!
129//! ```
130//! extern crate lyon_tessellation as tess;
131//! use tess::{StrokeTessellator, GeometryBuilder, StrokeGeometryBuilder, StrokeOptions, GeometryBuilderError, StrokeVertex, VertexId};
132//! use tess::math::{Point, point};
133//! use tess::path::polygon::Polygon;
134//! use std::fmt::Debug;
135//! use std::u32;
136//!
137//! // A geometry builder that writes the result of the tessellation to stdout instead
138//! // of filling vertex and index buffers.
139//! pub struct ToStdOut {
140//!     vertices: u32,
141//!     indices: u32,
142//! }
143//!
144//! impl ToStdOut {
145//!      pub fn new() -> Self { ToStdOut { vertices: 0, indices: 0 } }
146//! }
147//!
148//! impl GeometryBuilder for ToStdOut {
149//!     fn begin_geometry(&mut self) {
150//!         // Reset the vertex in index counters.
151//!         self.vertices = 0;
152//!         self.indices = 0;
153//!         println!(" -- begin geometry");
154//!     }
155//!
156//!     fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) {
157//!         println!("triangle ({}, {}, {})", a.offset(), b.offset(), c.offset());
158//!         self.indices += 3;
159//!     }
160//!
161//!     fn abort_geometry(&mut self) {
162//!         println!(" -- oops!");
163//!     }
164//! }
165//!
166//! impl StrokeGeometryBuilder for ToStdOut {
167//!     fn add_stroke_vertex(&mut self, vertex: StrokeVertex) -> Result<VertexId, GeometryBuilderError> {
168//!         println!("vertex {:?}", vertex.position());
169//!         if self.vertices >= u32::MAX {
170//!             return Err(GeometryBuilderError::TooManyVertices);
171//!         }
172//!         self.vertices += 1;
173//!         Ok(VertexId(self.vertices as u32 - 1))
174//!     }
175//! }
176//!
177//! fn main() {
178//!     let mut output = ToStdOut::new();
179//!     let mut tessellator = StrokeTessellator::new();
180//!     tessellator.tessellate_polygon(
181//!         Polygon {
182//!             points: &[point(0.0, 0.0), point(10.0, 0.0), point(5.0, 5.0)],
183//!             closed: true,
184//!         },
185//!         &StrokeOptions::default(),
186//!         &mut output,
187//!     );
188//! }
189//! ```
190//!
191
192pub use crate::error::GeometryBuilderError;
193use crate::math::Point;
194use crate::{FillVertex, Index, StrokeVertex, VertexId};
195
196use alloc::vec::Vec;
197use core::convert::From;
198use core::ops::Add;
199
200/// An interface separating tessellators and other geometry generation algorithms from the
201/// actual vertex construction.
202///
203/// Depending on which tessellator a geometry builder interfaces with, it also has to
204/// implement one or several of the following traits (Which contain the hooks to generate
205/// vertices):
206///  - [`FillGeometryBuilder`](trait.FillGeometryBuilder.html)
207///  - [`StrokeGeometryBuilder`](trait.StrokeGeometryBuilder.html)
208///
209/// See the [`geometry_builder`](index.html) module documentation for more detailed explanation.
210pub trait GeometryBuilder {
211    /// Called at the beginning of a generation.
212    ///
213    /// end_geometry must be called before begin_geometry is called again.
214    fn begin_geometry(&mut self) {}
215
216    /// Called at the end of a generation.
217    /// Returns the number of vertices and indices added since the last time begin_geometry was
218    /// called.
219    fn end_geometry(&mut self) {}
220
221    /// Insert a triangle made of vertices that were added after the last call to begin_geometry.
222    ///
223    /// This method can only be called between begin_geometry and end_geometry.
224    fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId);
225
226    /// abort_geometry is called instead of end_geometry if an error occurred while producing
227    /// the geometry and we won't be able to finish.
228    ///
229    /// The implementation is expected to discard the geometry that was generated since the last
230    /// time begin_geometry was called, and to remain in a usable state.
231    fn abort_geometry(&mut self) {}
232}
233
234/// A Geometry builder to interface with the [`FillTessellator`](../struct.FillTessellator.html).
235///
236/// Types implementing this trait must also implement the [`GeometryBuilder`](trait.GeometryBuilder.html) trait.
237pub trait FillGeometryBuilder: GeometryBuilder {
238    /// Inserts a vertex, providing its position, and optionally a normal.
239    /// Returns a vertex id that is only valid between begin_geometry and end_geometry.
240    ///
241    /// This method can only be called between begin_geometry and end_geometry.
242    fn add_fill_vertex(&mut self, vertex: FillVertex) -> Result<VertexId, GeometryBuilderError>;
243}
244
245/// A Geometry builder to interface with the [`StrokeTessellator`](../struct.StrokeTessellator.html).
246///
247/// Types implementing this trait must also implement the [`GeometryBuilder`](trait.GeometryBuilder.html) trait.
248pub trait StrokeGeometryBuilder: GeometryBuilder {
249    /// Inserts a vertex, providing its position, and optionally a normal.
250    /// Returns a vertex id that is only valid between begin_geometry and end_geometry.
251    ///
252    /// This method can only be called between begin_geometry and end_geometry.
253    fn add_stroke_vertex(&mut self, vertex: StrokeVertex)
254        -> Result<VertexId, GeometryBuilderError>;
255}
256
257/// Structure that holds the vertex and index data.
258///
259/// Usually written into though temporary `BuffersBuilder` objects.
260#[derive(Clone, Debug, Default)]
261#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
262pub struct VertexBuffers<OutputVertex, OutputIndex> {
263    pub vertices: Vec<OutputVertex>,
264    pub indices: Vec<OutputIndex>,
265}
266
267impl<OutputVertex, OutputIndex> VertexBuffers<OutputVertex, OutputIndex> {
268    /// Constructor
269    pub fn new() -> Self {
270        VertexBuffers::with_capacity(512, 1024)
271    }
272
273    /// Constructor
274    pub fn with_capacity(num_vertices: usize, num_indices: usize) -> Self {
275        VertexBuffers {
276            vertices: Vec::with_capacity(num_vertices),
277            indices: Vec::with_capacity(num_indices),
278        }
279    }
280
281    /// Empty the buffers without freeing memory, for reuse without reallocation.
282    pub fn clear(&mut self) {
283        self.vertices.clear();
284        self.indices.clear();
285    }
286}
287
288/// A temporary view on a `VertexBuffers` object which facilitate the population of vertex and index
289/// data.
290///
291/// `BuffersBuilders` record the vertex offset from when they are created so that algorithms using
292/// them don't need to worry about offsetting indices if some geometry was added beforehand. This
293/// means that from the point of view of a `BuffersBuilder` user, the first added vertex is at always
294/// offset at the offset 0 and `VertexBuilder` takes care of translating indices adequately.
295///
296/// Often, algorithms are built to generate vertex positions without knowledge of eventual other
297/// vertex vertex. The `VertexConstructor` does the translation from generic `Input` to `OutputVertex`.
298/// If your logic generates the actual vertex type directly, you can use the `SimpleBuffersBuilder`
299/// convenience typedef.
300pub struct BuffersBuilder<'l, OutputVertex: 'l, OutputIndex: 'l, Ctor> {
301    buffers: &'l mut VertexBuffers<OutputVertex, OutputIndex>,
302    first_vertex: Index,
303    first_index: Index,
304    vertex_offset: Index,
305    vertex_constructor: Ctor,
306}
307
308impl<'l, OutputVertex: 'l, OutputIndex: 'l, Ctor>
309    BuffersBuilder<'l, OutputVertex, OutputIndex, Ctor>
310{
311    pub fn new(buffers: &'l mut VertexBuffers<OutputVertex, OutputIndex>, ctor: Ctor) -> Self {
312        let first_vertex = buffers.vertices.len() as Index;
313        let first_index = buffers.indices.len() as Index;
314        BuffersBuilder {
315            buffers,
316            first_vertex,
317            first_index,
318            vertex_offset: 0,
319            vertex_constructor: ctor,
320        }
321    }
322
323    pub fn with_vertex_offset(mut self, offset: Index) -> Self {
324        self.vertex_offset = offset;
325
326        self
327    }
328
329    /// Consumes self and returns a builder with opposite triangle face winding.
330    pub fn with_inverted_winding(self) -> InvertWinding<Self> {
331        InvertWinding(self)
332    }
333
334    pub fn buffers<'a, 'b: 'a>(&'b self) -> &'a VertexBuffers<OutputVertex, OutputIndex> {
335        self.buffers
336    }
337}
338
339/// A wrapper for stroke and fill geometry builders that inverts the triangle face winding.
340pub struct InvertWinding<B>(B);
341
342impl<B: GeometryBuilder> GeometryBuilder for InvertWinding<B> {
343    fn begin_geometry(&mut self) {
344        self.0.begin_geometry();
345    }
346
347    fn end_geometry(&mut self) {
348        self.0.end_geometry()
349    }
350
351    fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) {
352        // Invert the triangle winding by flipping b and c.
353        self.0.add_triangle(a, c, b);
354    }
355
356    fn abort_geometry(&mut self) {
357        self.0.abort_geometry();
358    }
359}
360
361impl<B: FillGeometryBuilder> FillGeometryBuilder for InvertWinding<B> {
362    #[inline]
363    fn add_fill_vertex(&mut self, vertex: FillVertex) -> Result<VertexId, GeometryBuilderError> {
364        self.0.add_fill_vertex(vertex)
365    }
366}
367
368impl<B: StrokeGeometryBuilder> StrokeGeometryBuilder for InvertWinding<B> {
369    #[inline]
370    fn add_stroke_vertex(
371        &mut self,
372        vertex: StrokeVertex,
373    ) -> Result<VertexId, GeometryBuilderError> {
374        self.0.add_stroke_vertex(vertex)
375    }
376}
377
378/// A trait specifying how to create vertex values.
379pub trait FillVertexConstructor<OutputVertex> {
380    fn new_vertex(&mut self, vertex: FillVertex) -> OutputVertex;
381}
382
383/// A trait specifying how to create vertex values.
384pub trait StrokeVertexConstructor<OutputVertex> {
385    fn new_vertex(&mut self, vertex: StrokeVertex) -> OutputVertex;
386}
387
388/// A simple vertex constructor that just takes the position.
389pub struct Positions;
390
391impl FillVertexConstructor<Point> for Positions {
392    fn new_vertex(&mut self, vertex: FillVertex) -> Point {
393        vertex.position()
394    }
395}
396
397impl StrokeVertexConstructor<Point> for Positions {
398    fn new_vertex(&mut self, vertex: StrokeVertex) -> Point {
399        vertex.position()
400    }
401}
402
403impl<F, OutputVertex> FillVertexConstructor<OutputVertex> for F
404where
405    F: Fn(FillVertex) -> OutputVertex,
406{
407    fn new_vertex(&mut self, vertex: FillVertex) -> OutputVertex {
408        self(vertex)
409    }
410}
411
412impl<F, OutputVertex> StrokeVertexConstructor<OutputVertex> for F
413where
414    F: Fn(StrokeVertex) -> OutputVertex,
415{
416    fn new_vertex(&mut self, vertex: StrokeVertex) -> OutputVertex {
417        self(vertex)
418    }
419}
420
421/// A `BuffersBuilder` that takes the actual vertex type as input.
422pub type SimpleBuffersBuilder<'l> = BuffersBuilder<'l, Point, u16, Positions>;
423
424/// Creates a `SimpleBuffersBuilder`.
425pub fn simple_builder(buffers: &mut VertexBuffers<Point, u16>) -> SimpleBuffersBuilder {
426    let first_vertex = buffers.vertices.len() as Index;
427    let first_index = buffers.indices.len() as Index;
428    BuffersBuilder {
429        buffers,
430        first_vertex,
431        first_index,
432        vertex_offset: 0,
433        vertex_constructor: Positions,
434    }
435}
436
437impl<'l, OutputVertex, OutputIndex, Ctor> GeometryBuilder
438    for BuffersBuilder<'l, OutputVertex, OutputIndex, Ctor>
439where
440    OutputVertex: 'l,
441    OutputIndex: Add + From<VertexId> + MaxIndex,
442{
443    fn begin_geometry(&mut self) {
444        self.first_vertex = self.buffers.vertices.len() as Index;
445        self.first_index = self.buffers.indices.len() as Index;
446    }
447
448    fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) {
449        #[cfg(feature = "std")]
450        if a == b || a == c || b == c {
451            std::println!("bad triangle {a:?} {b:?} {c:?}");
452        }
453        debug_assert!(a != b);
454        debug_assert!(a != c);
455        debug_assert!(b != c);
456        debug_assert!(a != VertexId::INVALID);
457        debug_assert!(b != VertexId::INVALID);
458        debug_assert!(c != VertexId::INVALID);
459        self.buffers.indices.push((a + self.vertex_offset).into());
460        self.buffers.indices.push((b + self.vertex_offset).into());
461        self.buffers.indices.push((c + self.vertex_offset).into());
462    }
463
464    fn abort_geometry(&mut self) {
465        self.buffers.vertices.truncate(self.first_vertex as usize);
466        self.buffers.indices.truncate(self.first_index as usize);
467    }
468}
469
470impl<'l, OutputVertex, OutputIndex, Ctor> FillGeometryBuilder
471    for BuffersBuilder<'l, OutputVertex, OutputIndex, Ctor>
472where
473    OutputVertex: 'l,
474    OutputIndex: Add + From<VertexId> + MaxIndex,
475    Ctor: FillVertexConstructor<OutputVertex>,
476{
477    fn add_fill_vertex(&mut self, vertex: FillVertex) -> Result<VertexId, GeometryBuilderError> {
478        self.buffers
479            .vertices
480            .push(self.vertex_constructor.new_vertex(vertex));
481        let len = self.buffers.vertices.len();
482        if len > OutputIndex::MAX {
483            return Err(GeometryBuilderError::TooManyVertices);
484        }
485        Ok(VertexId((len - 1) as Index))
486    }
487}
488
489impl<'l, OutputVertex, OutputIndex, Ctor> StrokeGeometryBuilder
490    for BuffersBuilder<'l, OutputVertex, OutputIndex, Ctor>
491where
492    OutputVertex: 'l,
493    OutputIndex: Add + From<VertexId> + MaxIndex,
494    Ctor: StrokeVertexConstructor<OutputVertex>,
495{
496    fn add_stroke_vertex(&mut self, v: StrokeVertex) -> Result<VertexId, GeometryBuilderError> {
497        self.buffers
498            .vertices
499            .push(self.vertex_constructor.new_vertex(v));
500        let len = self.buffers.vertices.len();
501        if len > OutputIndex::MAX {
502            return Err(GeometryBuilderError::TooManyVertices);
503        }
504        Ok(VertexId((len - 1) as Index))
505    }
506}
507
508/// A geometry builder that does not output any geometry.
509///
510/// Mostly useful for testing.
511pub struct NoOutput {
512    next_vertex: u32,
513}
514
515impl NoOutput {
516    pub fn new() -> Self {
517        NoOutput { next_vertex: 0 }
518    }
519}
520
521impl Default for NoOutput {
522    fn default() -> Self {
523        Self::new()
524    }
525}
526
527impl GeometryBuilder for NoOutput {
528    fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) {
529        debug_assert!(a != b);
530        debug_assert!(a != c);
531        debug_assert!(b != c);
532    }
533}
534
535impl FillGeometryBuilder for NoOutput {
536    fn add_fill_vertex(&mut self, _vertex: FillVertex) -> Result<VertexId, GeometryBuilderError> {
537        if self.next_vertex == u32::MAX {
538            return Err(GeometryBuilderError::TooManyVertices);
539        }
540        self.next_vertex += 1;
541        Ok(VertexId(self.next_vertex - 1))
542    }
543}
544
545impl StrokeGeometryBuilder for NoOutput {
546    fn add_stroke_vertex(&mut self, _: StrokeVertex) -> Result<VertexId, GeometryBuilderError> {
547        if self.next_vertex == u32::MAX {
548            return Err(GeometryBuilderError::TooManyVertices);
549        }
550        self.next_vertex += 1;
551        Ok(VertexId(self.next_vertex - 1))
552    }
553}
554
555/// Provides the maximum value of an index.
556///
557/// This should be the maximum value representable by the index type up
558/// to u32::MAX because the tessellators can't internally represent more
559/// than u32::MAX indices.
560pub trait MaxIndex {
561    const MAX: usize;
562}
563
564impl MaxIndex for u8 {
565    const MAX: usize = u8::MAX as usize;
566}
567impl MaxIndex for i8 {
568    const MAX: usize = i8::MAX as usize;
569}
570impl MaxIndex for u16 {
571    const MAX: usize = u16::MAX as usize;
572}
573impl MaxIndex for i16 {
574    const MAX: usize = i16::MAX as usize;
575}
576impl MaxIndex for u32 {
577    const MAX: usize = u32::MAX as usize;
578}
579impl MaxIndex for i32 {
580    const MAX: usize = i32::MAX as usize;
581}
582// The tessellators internally use u32 indices so we can't have more than u32::MAX
583impl MaxIndex for u64 {
584    const MAX: usize = u32::MAX as usize;
585}
586impl MaxIndex for i64 {
587    const MAX: usize = u32::MAX as usize;
588}
589impl MaxIndex for usize {
590    const MAX: usize = u32::MAX as usize;
591}
592impl MaxIndex for isize {
593    const MAX: usize = u32::MAX as usize;
594}