use crate::math::Point;
use crate::{FillVertex, Index, StrokeVertex, VertexId};
pub use crate::error::GeometryBuilderError;
use core::convert::From;
use core::ops::Add;
use alloc::vec::Vec;
pub trait GeometryBuilder {
fn begin_geometry(&mut self) {}
fn end_geometry(&mut self) {}
fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId);
fn abort_geometry(&mut self) {}
}
pub trait FillGeometryBuilder: GeometryBuilder {
fn add_fill_vertex(&mut self, vertex: FillVertex) -> Result<VertexId, GeometryBuilderError>;
}
pub trait StrokeGeometryBuilder: GeometryBuilder {
fn add_stroke_vertex(&mut self, vertex: StrokeVertex)
-> Result<VertexId, GeometryBuilderError>;
}
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct VertexBuffers<OutputVertex, OutputIndex> {
pub vertices: Vec<OutputVertex>,
pub indices: Vec<OutputIndex>,
}
impl<OutputVertex, OutputIndex> VertexBuffers<OutputVertex, OutputIndex> {
pub fn new() -> Self {
VertexBuffers::with_capacity(512, 1024)
}
pub fn with_capacity(num_vertices: usize, num_indices: usize) -> Self {
VertexBuffers {
vertices: Vec::with_capacity(num_vertices),
indices: Vec::with_capacity(num_indices),
}
}
}
pub struct BuffersBuilder<'l, OutputVertex: 'l, OutputIndex: 'l, Ctor> {
buffers: &'l mut VertexBuffers<OutputVertex, OutputIndex>,
first_vertex: Index,
first_index: Index,
vertex_offset: Index,
vertex_constructor: Ctor,
}
impl<'l, OutputVertex: 'l, OutputIndex: 'l, Ctor>
BuffersBuilder<'l, OutputVertex, OutputIndex, Ctor>
{
pub fn new(buffers: &'l mut VertexBuffers<OutputVertex, OutputIndex>, ctor: Ctor) -> Self {
let first_vertex = buffers.vertices.len() as Index;
let first_index = buffers.indices.len() as Index;
BuffersBuilder {
buffers,
first_vertex,
first_index,
vertex_offset: 0,
vertex_constructor: ctor,
}
}
pub fn with_vertex_offset(mut self, offset: Index) -> Self {
self.vertex_offset = offset;
self
}
pub fn with_inverted_winding(self) -> InvertWinding<Self> {
InvertWinding(self)
}
pub fn buffers<'a, 'b: 'a>(&'b self) -> &'a VertexBuffers<OutputVertex, OutputIndex> {
self.buffers
}
}
pub struct InvertWinding<B>(B);
impl<B: GeometryBuilder> GeometryBuilder for InvertWinding<B> {
fn begin_geometry(&mut self) {
self.0.begin_geometry();
}
fn end_geometry(&mut self) {
self.0.end_geometry()
}
fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) {
self.0.add_triangle(a, c, b);
}
fn abort_geometry(&mut self) {
self.0.abort_geometry();
}
}
impl<B: FillGeometryBuilder> FillGeometryBuilder for InvertWinding<B> {
#[inline]
fn add_fill_vertex(&mut self, vertex: FillVertex) -> Result<VertexId, GeometryBuilderError> {
self.0.add_fill_vertex(vertex)
}
}
impl<B: StrokeGeometryBuilder> StrokeGeometryBuilder for InvertWinding<B> {
#[inline]
fn add_stroke_vertex(
&mut self,
vertex: StrokeVertex,
) -> Result<VertexId, GeometryBuilderError> {
self.0.add_stroke_vertex(vertex)
}
}
pub trait FillVertexConstructor<OutputVertex> {
fn new_vertex(&mut self, vertex: FillVertex) -> OutputVertex;
}
pub trait StrokeVertexConstructor<OutputVertex> {
fn new_vertex(&mut self, vertex: StrokeVertex) -> OutputVertex;
}
pub struct Positions;
impl FillVertexConstructor<Point> for Positions {
fn new_vertex(&mut self, vertex: FillVertex) -> Point {
vertex.position()
}
}
impl StrokeVertexConstructor<Point> for Positions {
fn new_vertex(&mut self, vertex: StrokeVertex) -> Point {
vertex.position()
}
}
impl<F, OutputVertex> FillVertexConstructor<OutputVertex> for F
where
F: Fn(FillVertex) -> OutputVertex,
{
fn new_vertex(&mut self, vertex: FillVertex) -> OutputVertex {
self(vertex)
}
}
impl<F, OutputVertex> StrokeVertexConstructor<OutputVertex> for F
where
F: Fn(StrokeVertex) -> OutputVertex,
{
fn new_vertex(&mut self, vertex: StrokeVertex) -> OutputVertex {
self(vertex)
}
}
pub type SimpleBuffersBuilder<'l> = BuffersBuilder<'l, Point, u16, Positions>;
pub fn simple_builder(buffers: &mut VertexBuffers<Point, u16>) -> SimpleBuffersBuilder {
let first_vertex = buffers.vertices.len() as Index;
let first_index = buffers.indices.len() as Index;
BuffersBuilder {
buffers,
first_vertex,
first_index,
vertex_offset: 0,
vertex_constructor: Positions,
}
}
impl<'l, OutputVertex, OutputIndex, Ctor> GeometryBuilder
for BuffersBuilder<'l, OutputVertex, OutputIndex, Ctor>
where
OutputVertex: 'l,
OutputIndex: Add + From<VertexId> + MaxIndex,
{
fn begin_geometry(&mut self) {
self.first_vertex = self.buffers.vertices.len() as Index;
self.first_index = self.buffers.indices.len() as Index;
}
fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) {
#[cfg(feature = "std")]
if a == b || a == c || b == c {
std::println!("bad triangle {a:?} {b:?} {c:?}");
}
debug_assert!(a != b);
debug_assert!(a != c);
debug_assert!(b != c);
debug_assert!(a != VertexId::INVALID);
debug_assert!(b != VertexId::INVALID);
debug_assert!(c != VertexId::INVALID);
self.buffers.indices.push((a + self.vertex_offset).into());
self.buffers.indices.push((b + self.vertex_offset).into());
self.buffers.indices.push((c + self.vertex_offset).into());
}
fn abort_geometry(&mut self) {
self.buffers.vertices.truncate(self.first_vertex as usize);
self.buffers.indices.truncate(self.first_index as usize);
}
}
impl<'l, OutputVertex, OutputIndex, Ctor> FillGeometryBuilder
for BuffersBuilder<'l, OutputVertex, OutputIndex, Ctor>
where
OutputVertex: 'l,
OutputIndex: Add + From<VertexId> + MaxIndex,
Ctor: FillVertexConstructor<OutputVertex>,
{
fn add_fill_vertex(&mut self, vertex: FillVertex) -> Result<VertexId, GeometryBuilderError> {
self.buffers
.vertices
.push(self.vertex_constructor.new_vertex(vertex));
let len = self.buffers.vertices.len();
if len > OutputIndex::MAX {
return Err(GeometryBuilderError::TooManyVertices);
}
Ok(VertexId((len - 1) as Index))
}
}
impl<'l, OutputVertex, OutputIndex, Ctor> StrokeGeometryBuilder
for BuffersBuilder<'l, OutputVertex, OutputIndex, Ctor>
where
OutputVertex: 'l,
OutputIndex: Add + From<VertexId> + MaxIndex,
Ctor: StrokeVertexConstructor<OutputVertex>,
{
fn add_stroke_vertex(&mut self, v: StrokeVertex) -> Result<VertexId, GeometryBuilderError> {
self.buffers
.vertices
.push(self.vertex_constructor.new_vertex(v));
let len = self.buffers.vertices.len();
if len > OutputIndex::MAX {
return Err(GeometryBuilderError::TooManyVertices);
}
Ok(VertexId((len - 1) as Index))
}
}
pub struct NoOutput {
next_vertex: u32,
}
impl NoOutput {
pub fn new() -> Self {
NoOutput { next_vertex: 0 }
}
}
impl Default for NoOutput {
fn default() -> Self {
Self::new()
}
}
impl GeometryBuilder for NoOutput {
fn add_triangle(&mut self, a: VertexId, b: VertexId, c: VertexId) {
debug_assert!(a != b);
debug_assert!(a != c);
debug_assert!(b != c);
}
}
impl FillGeometryBuilder for NoOutput {
fn add_fill_vertex(&mut self, _vertex: FillVertex) -> Result<VertexId, GeometryBuilderError> {
if self.next_vertex == u32::MAX {
return Err(GeometryBuilderError::TooManyVertices);
}
self.next_vertex += 1;
Ok(VertexId(self.next_vertex - 1))
}
}
impl StrokeGeometryBuilder for NoOutput {
fn add_stroke_vertex(&mut self, _: StrokeVertex) -> Result<VertexId, GeometryBuilderError> {
if self.next_vertex == u32::MAX {
return Err(GeometryBuilderError::TooManyVertices);
}
self.next_vertex += 1;
Ok(VertexId(self.next_vertex - 1))
}
}
pub trait MaxIndex {
const MAX: usize;
}
impl MaxIndex for u8 {
const MAX: usize = u8::MAX as usize;
}
impl MaxIndex for i8 {
const MAX: usize = i8::MAX as usize;
}
impl MaxIndex for u16 {
const MAX: usize = u16::MAX as usize;
}
impl MaxIndex for i16 {
const MAX: usize = i16::MAX as usize;
}
impl MaxIndex for u32 {
const MAX: usize = u32::MAX as usize;
}
impl MaxIndex for i32 {
const MAX: usize = i32::MAX as usize;
}
impl MaxIndex for u64 {
const MAX: usize = u32::MAX as usize;
}
impl MaxIndex for i64 {
const MAX: usize = u32::MAX as usize;
}
impl MaxIndex for usize {
const MAX: usize = u32::MAX as usize;
}
impl MaxIndex for isize {
const MAX: usize = u32::MAX as usize;
}