2017-10-02 17:03:56 -04:00
|
|
|
// pathfinder/partitioner/src/mesh_library.rs
|
|
|
|
//
|
|
|
|
// Copyright © 2017 The Pathfinder Project Developers.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2017-10-02 18:17:21 -04:00
|
|
|
use bincode::{self, Infinite};
|
|
|
|
use byteorder::{LittleEndian, WriteBytesExt};
|
2017-10-02 17:03:56 -04:00
|
|
|
use euclid::Point2D;
|
2017-10-09 17:14:24 -04:00
|
|
|
use pathfinder_path_utils::{PathCommand, PathSegment, PathSegmentStream};
|
2017-10-02 18:17:21 -04:00
|
|
|
use serde::Serialize;
|
|
|
|
use std::io::{self, ErrorKind, Seek, SeekFrom, Write};
|
2017-10-02 17:03:56 -04:00
|
|
|
use std::ops::Range;
|
2017-10-06 19:11:53 -04:00
|
|
|
use std::u32;
|
2017-10-02 17:03:56 -04:00
|
|
|
|
2017-10-27 18:12:33 -04:00
|
|
|
use normal;
|
2018-01-02 22:15:19 -05:00
|
|
|
use {BQuad, BQuadVertexPositions, BVertexLoopBlinnData};
|
2017-10-02 17:03:56 -04:00
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct MeshLibrary {
|
2017-11-02 14:14:45 -04:00
|
|
|
pub path_ranges: Vec<PathRanges>,
|
2017-10-02 17:03:56 -04:00
|
|
|
pub b_quads: Vec<BQuad>,
|
2017-12-15 16:41:27 -05:00
|
|
|
// FIXME(pcwalton): Merge with `b_vertex_positions` below.
|
2018-01-02 22:15:19 -05:00
|
|
|
pub b_quad_vertex_positions: Vec<BQuadVertexPositions>,
|
2018-01-07 14:14:24 -05:00
|
|
|
pub b_quad_vertex_interior_indices: Vec<u32>,
|
2017-10-02 17:03:56 -04:00
|
|
|
pub b_vertex_positions: Vec<Point2D<f32>>,
|
|
|
|
pub b_vertex_loop_blinn_data: Vec<BVertexLoopBlinnData>,
|
2017-10-27 18:12:33 -04:00
|
|
|
pub b_vertex_normals: Vec<f32>,
|
2017-10-09 17:14:24 -04:00
|
|
|
pub segments: MeshLibrarySegments,
|
|
|
|
pub segment_normals: MeshLibrarySegmentNormals,
|
2017-10-02 17:03:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl MeshLibrary {
|
|
|
|
#[inline]
|
|
|
|
pub fn new() -> MeshLibrary {
|
|
|
|
MeshLibrary {
|
2017-11-02 14:14:45 -04:00
|
|
|
path_ranges: vec![],
|
2017-10-02 17:03:56 -04:00
|
|
|
b_quads: vec![],
|
2017-12-15 16:41:27 -05:00
|
|
|
b_quad_vertex_positions: vec![],
|
2018-01-07 14:14:24 -05:00
|
|
|
b_quad_vertex_interior_indices: vec![],
|
2017-10-02 17:03:56 -04:00
|
|
|
b_vertex_positions: vec![],
|
|
|
|
b_vertex_loop_blinn_data: vec![],
|
2017-10-27 18:12:33 -04:00
|
|
|
b_vertex_normals: vec![],
|
2017-10-09 17:14:24 -04:00
|
|
|
segments: MeshLibrarySegments::new(),
|
|
|
|
segment_normals: MeshLibrarySegmentNormals::new(),
|
2017-10-02 17:03:56 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clear(&mut self) {
|
2017-11-02 14:14:45 -04:00
|
|
|
self.path_ranges.clear();
|
2017-10-02 17:03:56 -04:00
|
|
|
self.b_quads.clear();
|
2017-12-15 16:41:27 -05:00
|
|
|
self.b_quad_vertex_positions.clear();
|
2018-01-07 14:14:24 -05:00
|
|
|
self.b_quad_vertex_interior_indices.clear();
|
2017-10-02 17:03:56 -04:00
|
|
|
self.b_vertex_positions.clear();
|
|
|
|
self.b_vertex_loop_blinn_data.clear();
|
2017-10-27 18:12:33 -04:00
|
|
|
self.b_vertex_normals.clear();
|
2017-10-09 17:14:24 -04:00
|
|
|
self.segments.clear();
|
|
|
|
self.segment_normals.clear();
|
2017-10-06 19:11:53 -04:00
|
|
|
}
|
|
|
|
|
2017-11-02 14:14:45 -04:00
|
|
|
pub(crate) fn ensure_path_ranges(&mut self, path_id: u16) -> &mut PathRanges {
|
|
|
|
let path_index = (path_id as usize) - 1;
|
|
|
|
while path_index >= self.path_ranges.len() {
|
|
|
|
self.path_ranges.push(PathRanges::new())
|
|
|
|
}
|
|
|
|
&mut self.path_ranges[path_index]
|
|
|
|
}
|
|
|
|
|
2017-10-27 18:12:33 -04:00
|
|
|
pub(crate) fn add_b_vertex(&mut self,
|
|
|
|
position: &Point2D<f32>,
|
|
|
|
loop_blinn_data: &BVertexLoopBlinnData,
|
|
|
|
normal: f32) {
|
|
|
|
self.b_vertex_positions.push(*position);
|
|
|
|
self.b_vertex_loop_blinn_data.push(*loop_blinn_data);
|
|
|
|
self.b_vertex_normals.push(normal);
|
|
|
|
}
|
|
|
|
|
2017-10-06 19:11:53 -04:00
|
|
|
pub(crate) fn add_b_quad(&mut self, b_quad: &BQuad) {
|
|
|
|
self.b_quads.push(*b_quad);
|
|
|
|
|
|
|
|
let upper_left_position =
|
2018-01-07 14:14:24 -05:00
|
|
|
self.b_vertex_positions[b_quad.upper_left_vertex_index as usize];
|
2017-10-06 19:11:53 -04:00
|
|
|
let upper_right_position =
|
2018-01-07 14:14:24 -05:00
|
|
|
self.b_vertex_positions[b_quad.upper_right_vertex_index as usize];
|
2017-10-06 19:11:53 -04:00
|
|
|
let lower_left_position =
|
2018-01-07 14:14:24 -05:00
|
|
|
self.b_vertex_positions[b_quad.lower_left_vertex_index as usize];
|
2017-10-06 19:11:53 -04:00
|
|
|
let lower_right_position =
|
2018-01-07 14:14:24 -05:00
|
|
|
self.b_vertex_positions[b_quad.lower_right_vertex_index as usize];
|
2017-10-06 19:11:53 -04:00
|
|
|
|
2018-01-02 22:15:19 -05:00
|
|
|
let mut b_quad_vertex_positions = BQuadVertexPositions {
|
2018-01-07 14:14:24 -05:00
|
|
|
upper_left_vertex_position: upper_left_position,
|
|
|
|
upper_control_point_position: upper_left_position,
|
|
|
|
upper_right_vertex_position: upper_right_position,
|
|
|
|
lower_left_vertex_position: lower_left_position,
|
|
|
|
lower_control_point_position: lower_right_position,
|
|
|
|
lower_right_vertex_position: lower_right_position,
|
2018-01-02 22:15:19 -05:00
|
|
|
};
|
2017-12-15 16:41:27 -05:00
|
|
|
|
2018-01-07 14:14:24 -05:00
|
|
|
if b_quad.upper_control_point_vertex_index != u32::MAX {
|
2017-10-06 19:11:53 -04:00
|
|
|
let upper_control_point_position =
|
2018-01-07 14:14:24 -05:00
|
|
|
self.b_vertex_positions[b_quad.upper_control_point_vertex_index as usize];
|
|
|
|
b_quad_vertex_positions.upper_control_point_position = upper_control_point_position;
|
2017-10-06 19:11:53 -04:00
|
|
|
}
|
|
|
|
|
2018-01-07 14:14:24 -05:00
|
|
|
if b_quad.lower_control_point_vertex_index != u32::MAX {
|
2017-10-06 19:11:53 -04:00
|
|
|
let lower_control_point_position =
|
2018-01-07 14:14:24 -05:00
|
|
|
self.b_vertex_positions[b_quad.lower_control_point_vertex_index as usize];
|
|
|
|
b_quad_vertex_positions.lower_control_point_position = lower_control_point_position;
|
2017-10-06 19:11:53 -04:00
|
|
|
}
|
2018-01-02 22:15:19 -05:00
|
|
|
|
2018-01-07 14:14:24 -05:00
|
|
|
let first_b_quad_vertex_position_index = (self.b_quad_vertex_positions.len() as u32) * 6;
|
|
|
|
self.push_b_quad_vertex_position_interior_indices(first_b_quad_vertex_position_index,
|
|
|
|
&b_quad_vertex_positions);
|
|
|
|
|
2018-01-02 22:15:19 -05:00
|
|
|
self.b_quad_vertex_positions.push(b_quad_vertex_positions);
|
2017-10-02 17:03:56 -04:00
|
|
|
}
|
|
|
|
|
2018-01-07 14:14:24 -05:00
|
|
|
fn push_b_quad_vertex_position_interior_indices(&mut self,
|
|
|
|
first_vertex_index: u32,
|
|
|
|
b_quad: &BQuadVertexPositions) {
|
|
|
|
let upper_curve_is_concave =
|
|
|
|
(b_quad.upper_right_vertex_position - b_quad.upper_left_vertex_position).cross(
|
|
|
|
b_quad.upper_control_point_position - b_quad.upper_left_vertex_position) > 0.0;
|
|
|
|
let lower_curve_is_concave =
|
|
|
|
(b_quad.lower_left_vertex_position - b_quad.lower_right_vertex_position).cross(
|
|
|
|
b_quad.lower_control_point_position - b_quad.lower_right_vertex_position) > 0.0;
|
|
|
|
|
|
|
|
let indices: &'static [u32] = match (upper_curve_is_concave, lower_curve_is_concave) {
|
|
|
|
(false, false) => &[UL, UR, LL, UR, LR, LL],
|
|
|
|
(true, false) => &[UL, UC, LL, UC, LR, LL, UR, LR, UC],
|
|
|
|
(false, true) => &[UL, LC, LL, UL, UR, LC, UR, LR, LC],
|
|
|
|
(true, true) => &[UL, UC, LL, UC, LC, LL, UR, LC, UC, UR, LR, LC],
|
|
|
|
};
|
|
|
|
|
|
|
|
self.b_quad_vertex_interior_indices
|
|
|
|
.extend(indices.into_iter().map(|index| index + first_vertex_index));
|
|
|
|
|
|
|
|
const UL: u32 = 0;
|
|
|
|
const UC: u32 = 1;
|
|
|
|
const UR: u32 = 2;
|
|
|
|
const LR: u32 = 3;
|
|
|
|
const LC: u32 = 4;
|
|
|
|
const LL: u32 = 5;
|
|
|
|
}
|
|
|
|
|
2017-10-02 18:36:39 -04:00
|
|
|
/// Reverses interior indices so that they draw front-to-back.
|
|
|
|
///
|
|
|
|
/// This enables early Z optimizations.
|
|
|
|
pub fn optimize(&mut self) {
|
2018-01-07 14:14:24 -05:00
|
|
|
reverse_indices(&mut self.path_ranges,
|
|
|
|
&mut self.b_quad_vertex_interior_indices,
|
|
|
|
|path_ranges| path_ranges.b_quad_vertex_interior_indices.clone(),
|
|
|
|
|path_ranges, new_range| {
|
|
|
|
path_ranges.b_quad_vertex_interior_indices = new_range
|
|
|
|
});
|
|
|
|
|
|
|
|
fn reverse_indices<G, S>(path_ranges: &mut [PathRanges],
|
|
|
|
indices: &mut Vec<u32>,
|
|
|
|
mut getter: G,
|
|
|
|
mut setter: S)
|
|
|
|
where G: FnMut(&PathRanges) -> Range<u32>,
|
|
|
|
S: FnMut(&mut PathRanges, Range<u32>) {
|
|
|
|
let mut new_indices = Vec::with_capacity(indices.len());
|
|
|
|
for path_range in path_ranges.iter_mut().rev() {
|
|
|
|
let old_range = getter(path_range);
|
|
|
|
let old_range = (old_range.start as usize)..(old_range.end as usize);
|
|
|
|
let new_start_index = new_indices.len() as u32;
|
|
|
|
new_indices.extend_from_slice(&indices[old_range]);
|
|
|
|
let new_end_index = new_indices.len() as u32;
|
|
|
|
setter(path_range, new_start_index..new_end_index);
|
|
|
|
}
|
2017-11-02 14:14:45 -04:00
|
|
|
|
2018-01-07 14:14:24 -05:00
|
|
|
*indices = new_indices
|
|
|
|
}
|
2017-10-02 18:36:39 -04:00
|
|
|
}
|
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
pub fn push_segments<I>(&mut self, path_id: u16, stream: I)
|
|
|
|
where I: Iterator<Item = PathCommand> {
|
2017-11-02 14:14:45 -04:00
|
|
|
let first_line_index = self.segments.lines.len() as u32;
|
|
|
|
let first_curve_index = self.segments.curves.len() as u32;
|
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
let stream = PathSegmentStream::new(stream);
|
|
|
|
for (segment, _) in stream {
|
|
|
|
match segment {
|
|
|
|
PathSegment::Line(endpoint_0, endpoint_1) => {
|
|
|
|
self.segments.lines.push(LineSegment {
|
|
|
|
endpoint_0: endpoint_0,
|
|
|
|
endpoint_1: endpoint_1,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
PathSegment::Curve(endpoint_0, control_point, endpoint_1) => {
|
|
|
|
self.segments.curves.push(CurveSegment {
|
|
|
|
endpoint_0: endpoint_0,
|
|
|
|
control_point: control_point,
|
|
|
|
endpoint_1: endpoint_1,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-02 14:14:45 -04:00
|
|
|
|
|
|
|
let last_line_index = self.segments.lines.len() as u32;
|
|
|
|
let last_curve_index = self.segments.curves.len() as u32;
|
|
|
|
|
|
|
|
let path_ranges = self.ensure_path_ranges(path_id);
|
|
|
|
path_ranges.segment_curves = first_curve_index..last_curve_index;
|
|
|
|
path_ranges.segment_lines = first_line_index..last_line_index;
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Computes vertex normals necessary for emboldening and/or stem darkening.
|
|
|
|
pub fn push_normals<I>(&mut self, stream: I) where I: Iterator<Item = PathCommand> {
|
2017-10-27 18:12:33 -04:00
|
|
|
normal::push_normals(self, stream)
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-02 18:17:21 -04:00
|
|
|
/// Writes this mesh library to a RIFF file.
|
|
|
|
///
|
|
|
|
/// RIFF is a dead-simple extensible binary format documented here:
|
|
|
|
/// https://msdn.microsoft.com/en-us/library/windows/desktop/ee415713(v=vs.85).aspx
|
|
|
|
pub fn serialize_into<W>(&self, writer: &mut W) -> io::Result<()> where W: Write + Seek {
|
|
|
|
// `PFML` for "Pathfinder Mesh Library".
|
|
|
|
try!(writer.write_all(b"RIFF\0\0\0\0PFML"));
|
|
|
|
|
|
|
|
// NB: The RIFF spec requires that all chunks be padded to an even byte offset. However,
|
|
|
|
// for us, this is guaranteed by construction because each instance of all of the data that
|
|
|
|
// we're writing has a byte size that is a multiple of 4. So we don't bother with doing it
|
|
|
|
// explicitly here.
|
2017-11-02 14:14:45 -04:00
|
|
|
try!(write_chunk(writer, b"prng", |writer| write_path_ranges(writer, &self.path_ranges)));
|
|
|
|
|
|
|
|
try!(write_simple_chunk(writer, b"bqua", &self.b_quads));
|
2017-12-15 16:41:27 -05:00
|
|
|
try!(write_simple_chunk(writer, b"bqvp", &self.b_quad_vertex_positions));
|
2018-01-07 14:14:24 -05:00
|
|
|
try!(write_simple_chunk(writer, b"bqii", &self.b_quad_vertex_interior_indices));
|
2017-11-02 14:14:45 -04:00
|
|
|
try!(write_simple_chunk(writer, b"slin", &self.segments.lines));
|
|
|
|
try!(write_simple_chunk(writer, b"scur", &self.segments.curves));
|
|
|
|
try!(write_simple_chunk(writer, b"snli", &self.segment_normals.line_normals));
|
|
|
|
try!(write_simple_chunk(writer, b"sncu", &self.segment_normals.curve_normals));
|
2017-10-02 18:17:21 -04:00
|
|
|
|
|
|
|
let total_length = try!(writer.seek(SeekFrom::Current(0)));
|
|
|
|
try!(writer.seek(SeekFrom::Start(4)));
|
|
|
|
try!(writer.write_u32::<LittleEndian>((total_length - 8) as u32));
|
|
|
|
return Ok(());
|
|
|
|
|
2017-11-02 14:14:45 -04:00
|
|
|
fn write_chunk<W, F>(writer: &mut W, tag: &[u8; 4], mut closure: F) -> io::Result<()>
|
|
|
|
where W: Write + Seek, F: FnMut(&mut W) -> io::Result<()> {
|
2017-10-02 18:17:21 -04:00
|
|
|
try!(writer.write_all(tag));
|
|
|
|
try!(writer.write_all(b"\0\0\0\0"));
|
|
|
|
|
|
|
|
let start_position = try!(writer.seek(SeekFrom::Current(0)));
|
2017-11-02 14:14:45 -04:00
|
|
|
try!(closure(writer));
|
2017-10-02 18:17:21 -04:00
|
|
|
|
|
|
|
let end_position = try!(writer.seek(SeekFrom::Current(0)));
|
|
|
|
try!(writer.seek(SeekFrom::Start(start_position - 4)));
|
|
|
|
try!(writer.write_u32::<LittleEndian>((end_position - start_position) as u32));
|
|
|
|
try!(writer.seek(SeekFrom::Start(end_position)));
|
|
|
|
Ok(())
|
|
|
|
}
|
2017-11-02 14:14:45 -04:00
|
|
|
|
|
|
|
fn write_simple_chunk<W, T>(writer: &mut W, tag: &[u8; 4], data: &[T]) -> io::Result<()>
|
|
|
|
where W: Write + Seek, T: Serialize {
|
|
|
|
write_chunk(writer, tag, |writer| {
|
|
|
|
for datum in data {
|
|
|
|
try!(bincode::serialize_into(writer, datum, Infinite).map_err(|_| {
|
|
|
|
io::Error::from(ErrorKind::Other)
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_path_ranges<W>(writer: &mut W, path_ranges: &[PathRanges]) -> io::Result<()>
|
|
|
|
where W: Write + Seek {
|
|
|
|
try!(write_path_range(writer, b"bqua", path_ranges, |ranges| &ranges.b_quads));
|
2017-12-15 16:41:27 -05:00
|
|
|
try!(write_path_range(writer,
|
|
|
|
b"bqvp",
|
|
|
|
path_ranges,
|
|
|
|
|ranges| &ranges.b_quad_vertex_positions));
|
2017-11-02 14:14:45 -04:00
|
|
|
try!(write_path_range(writer,
|
2018-01-07 14:14:24 -05:00
|
|
|
b"bqii",
|
2017-11-02 14:14:45 -04:00
|
|
|
path_ranges,
|
2018-01-07 14:14:24 -05:00
|
|
|
|ranges| &ranges.b_quad_vertex_interior_indices));
|
|
|
|
try!(write_path_range(writer, b"bver", path_ranges, |ranges| &ranges.b_vertices));
|
2017-11-02 14:14:45 -04:00
|
|
|
try!(write_path_range(writer, b"slin", path_ranges, |ranges| &ranges.segment_lines));
|
|
|
|
try!(write_path_range(writer, b"scur", path_ranges, |ranges| &ranges.segment_curves));
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_path_range<W, F>(writer: &mut W,
|
|
|
|
tag: &[u8; 4],
|
|
|
|
all_path_ranges: &[PathRanges],
|
|
|
|
mut get_range: F)
|
|
|
|
-> io::Result<()>
|
|
|
|
where W: Write + Seek, F: FnMut(&PathRanges) -> &Range<u32> {
|
|
|
|
write_chunk(writer, tag, |writer| {
|
|
|
|
for path_ranges in all_path_ranges {
|
|
|
|
let range = get_range(path_ranges);
|
|
|
|
try!(writer.write_u32::<LittleEndian>(range.start));
|
|
|
|
try!(writer.write_u32::<LittleEndian>(range.end));
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
}
|
2017-10-02 18:17:21 -04:00
|
|
|
}
|
|
|
|
|
2017-10-02 17:03:56 -04:00
|
|
|
pub(crate) fn snapshot_lengths(&self) -> MeshLibraryLengths {
|
|
|
|
MeshLibraryLengths {
|
2017-11-02 14:14:45 -04:00
|
|
|
b_quads: self.b_quads.len() as u32,
|
2017-12-15 16:41:27 -05:00
|
|
|
b_quad_vertex_positions: self.b_quad_vertex_positions.len() as u32,
|
2018-01-07 14:14:24 -05:00
|
|
|
b_quad_vertex_interior_indices: self.b_quad_vertex_interior_indices.len() as u32,
|
2017-11-02 14:14:45 -04:00
|
|
|
b_vertices: self.b_vertex_positions.len() as u32,
|
2017-10-02 17:03:56 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct MeshLibraryCoverIndices {
|
|
|
|
pub interior_indices: Vec<u32>,
|
|
|
|
pub curve_indices: Vec<u32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) struct MeshLibraryLengths {
|
2018-01-07 14:14:24 -05:00
|
|
|
pub(crate) b_quads: u32,
|
2017-12-15 16:41:27 -05:00
|
|
|
b_quad_vertex_positions: u32,
|
2018-01-07 14:14:24 -05:00
|
|
|
b_quad_vertex_interior_indices: u32,
|
2017-11-02 14:14:45 -04:00
|
|
|
b_vertices: u32,
|
2017-10-02 17:03:56 -04:00
|
|
|
}
|
|
|
|
|
2017-11-02 14:14:45 -04:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct PathRanges {
|
|
|
|
pub b_quads: Range<u32>,
|
2017-12-15 16:41:27 -05:00
|
|
|
pub b_quad_vertex_positions: Range<u32>,
|
2018-01-07 14:14:24 -05:00
|
|
|
pub b_quad_vertex_interior_indices: Range<u32>,
|
2017-11-02 14:14:45 -04:00
|
|
|
pub b_vertices: Range<u32>,
|
|
|
|
pub segment_lines: Range<u32>,
|
|
|
|
pub segment_curves: Range<u32>,
|
2017-10-02 17:03:56 -04:00
|
|
|
}
|
|
|
|
|
2017-11-02 14:14:45 -04:00
|
|
|
impl PathRanges {
|
|
|
|
fn new() -> PathRanges {
|
|
|
|
PathRanges {
|
|
|
|
b_quads: 0..0,
|
2017-12-15 16:41:27 -05:00
|
|
|
b_quad_vertex_positions: 0..0,
|
2018-01-07 14:14:24 -05:00
|
|
|
b_quad_vertex_interior_indices: 0..0,
|
2017-11-02 14:14:45 -04:00
|
|
|
b_vertices: 0..0,
|
|
|
|
segment_lines: 0..0,
|
|
|
|
segment_curves: 0..0,
|
2017-10-02 17:03:56 -04:00
|
|
|
}
|
|
|
|
}
|
2017-11-02 14:14:45 -04:00
|
|
|
|
|
|
|
pub(crate) fn set_partitioning_lengths(&mut self,
|
|
|
|
start: &MeshLibraryLengths,
|
|
|
|
end: &MeshLibraryLengths) {
|
|
|
|
self.b_quads = start.b_quads..end.b_quads;
|
2017-12-15 16:41:27 -05:00
|
|
|
self.b_quad_vertex_positions = start.b_quad_vertex_positions..end.b_quad_vertex_positions;
|
2018-01-07 14:14:24 -05:00
|
|
|
self.b_quad_vertex_interior_indices =
|
|
|
|
start.b_quad_vertex_interior_indices..end.b_quad_vertex_interior_indices;
|
2017-11-02 14:14:45 -04:00
|
|
|
self.b_vertices = start.b_vertices..end.b_vertices;
|
2017-10-06 19:11:53 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct MeshLibrarySegments {
|
|
|
|
pub lines: Vec<LineSegment>,
|
|
|
|
pub curves: Vec<CurveSegment>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MeshLibrarySegments {
|
|
|
|
fn new() -> MeshLibrarySegments {
|
|
|
|
MeshLibrarySegments {
|
|
|
|
lines: vec![],
|
|
|
|
curves: vec![],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clear(&mut self) {
|
|
|
|
self.lines.clear();
|
|
|
|
self.curves.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct MeshLibrarySegmentNormals {
|
|
|
|
pub line_normals: Vec<LineSegmentNormals>,
|
|
|
|
pub curve_normals: Vec<CurveSegmentNormals>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MeshLibrarySegmentNormals {
|
|
|
|
fn new() -> MeshLibrarySegmentNormals {
|
|
|
|
MeshLibrarySegmentNormals {
|
|
|
|
line_normals: vec![],
|
|
|
|
curve_normals: vec![],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clear(&mut self) {
|
|
|
|
self.line_normals.clear();
|
|
|
|
self.curve_normals.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
|
|
pub struct LineSegment {
|
|
|
|
pub endpoint_0: Point2D<f32>,
|
|
|
|
pub endpoint_1: Point2D<f32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
|
|
pub struct CurveSegment {
|
|
|
|
pub endpoint_0: Point2D<f32>,
|
|
|
|
pub control_point: Point2D<f32>,
|
|
|
|
pub endpoint_1: Point2D<f32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
|
|
pub struct LineSegmentNormals {
|
|
|
|
pub endpoint_0: f32,
|
|
|
|
pub endpoint_1: f32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
|
|
pub struct CurveSegmentNormals {
|
|
|
|
pub endpoint_0: f32,
|
|
|
|
pub control_point: f32,
|
|
|
|
pub endpoint_1: f32,
|
|
|
|
}
|