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}