separate render logic
This commit is contained in:
parent
50a30b74b5
commit
206f30f3af
3 changed files with 170 additions and 153 deletions
153
src/curve.rs
153
src/curve.rs
|
|
@ -1,6 +1,4 @@
|
||||||
use cgmath::InnerSpace;
|
pub mod renderer;
|
||||||
|
|
||||||
use crate::{vertex::RenderData, Vertex};
|
|
||||||
|
|
||||||
type Vector2 = cgmath::Vector2<f64>;
|
type Vector2 = cgmath::Vector2<f64>;
|
||||||
|
|
||||||
|
|
@ -46,153 +44,4 @@ impl PolyLine {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self { points: Vec::new() }
|
Self { points: Vec::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_render_data(&self, width: f64) -> RenderData {
|
|
||||||
let mut result = RenderData::new();
|
|
||||||
|
|
||||||
for i in 1..self.points.len() {
|
|
||||||
result = result.merge(self.get_segment_render_data(i, width));
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 1..self.points.len() - 1 {
|
|
||||||
result = result.merge(self.get_connection_render_data(i, width));
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_segment_render_data(&self, i: usize, width: f64) -> RenderData {
|
|
||||||
let start_points = self.get_adjusted_start_points(i - 1, width);
|
|
||||||
let end_points = self.get_adjusted_end_points(i, width);
|
|
||||||
let vertices: Vec<Vertex> = [start_points.0, start_points.1, end_points.0, end_points.1]
|
|
||||||
.map(Vector2::into)
|
|
||||||
.map(Vertex::new_f64)
|
|
||||||
.into_iter()
|
|
||||||
.collect();
|
|
||||||
let indices: Vec<_> = vec![0, 2, 3, 0, 3, 1];
|
|
||||||
RenderData { vertices, indices }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_connection_render_data(&self, i: usize, width: f64) -> RenderData {
|
|
||||||
let vertices: Vec<_> = match self.get_connection(i, width) {
|
|
||||||
Some((intersection, false)) => {
|
|
||||||
vec![
|
|
||||||
self.get_end_points(i, width).1,
|
|
||||||
intersection,
|
|
||||||
self.get_start_points(i, width).1,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Some((intersection, true)) => {
|
|
||||||
vec![
|
|
||||||
self.get_end_points(i, width).0,
|
|
||||||
intersection,
|
|
||||||
self.get_start_points(i, width).0,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
None => vec![],
|
|
||||||
}
|
|
||||||
.into_iter()
|
|
||||||
.map(Vector2::into)
|
|
||||||
.map(Vertex::new_f64)
|
|
||||||
.collect();
|
|
||||||
let indices = if vertices.is_empty() {
|
|
||||||
vec![]
|
|
||||||
} else {
|
|
||||||
vec![0, 1, 2]
|
|
||||||
};
|
|
||||||
RenderData { vertices, indices }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_adjusted_start_points(&self, i: usize, width: f64) -> (Vector2, Vector2) {
|
|
||||||
let start_points = self.get_start_points(i, width);
|
|
||||||
if i == 0 {
|
|
||||||
return start_points;
|
|
||||||
}
|
|
||||||
match self.get_connection(i, width) {
|
|
||||||
Some((intersection, false)) => (intersection, start_points.1),
|
|
||||||
Some((intersection, true)) => (start_points.0, intersection),
|
|
||||||
None => start_points,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_adjusted_end_points(&self, i: usize, width: f64) -> (Vector2, Vector2) {
|
|
||||||
let end_points = self.get_end_points(i, width);
|
|
||||||
if i + 1 == self.points.len() {
|
|
||||||
return end_points;
|
|
||||||
}
|
|
||||||
match self.get_connection(i, width) {
|
|
||||||
Some((intersection, false)) => (intersection, end_points.1),
|
|
||||||
Some((intersection, true)) => (end_points.0, intersection),
|
|
||||||
None => end_points,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_connection(&self, i: usize, width: f64) -> Option<(Vector2, bool)> {
|
|
||||||
let start_points = self.get_start_points(i - 1, width);
|
|
||||||
let end_points = self.get_end_points(i, width);
|
|
||||||
let next_start_points = self.get_start_points(i, width);
|
|
||||||
let next_end_points = self.get_end_points(i + 1, width);
|
|
||||||
let lines = (
|
|
||||||
Self::line(start_points.0, end_points.0),
|
|
||||||
Self::line(start_points.1, end_points.1),
|
|
||||||
);
|
|
||||||
let next_lines = (
|
|
||||||
Self::line(next_start_points.0, next_end_points.0),
|
|
||||||
Self::line(next_start_points.1, next_end_points.1),
|
|
||||||
);
|
|
||||||
|
|
||||||
use geo::algorithm::line_intersection::{line_intersection, LineIntersection};
|
|
||||||
|
|
||||||
let intersections = (
|
|
||||||
line_intersection(lines.0, next_lines.0),
|
|
||||||
line_intersection(lines.1, next_lines.1),
|
|
||||||
);
|
|
||||||
|
|
||||||
match intersections {
|
|
||||||
(Some(LineIntersection::SinglePoint { intersection, .. }), None) => {
|
|
||||||
Some((Vector2::new(intersection.x, intersection.y), false))
|
|
||||||
}
|
|
||||||
(None, Some(LineIntersection::SinglePoint { intersection, .. })) => {
|
|
||||||
Some((Vector2::new(intersection.x, intersection.y), true))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_start_points(&self, i: usize, width: f64) -> (Vector2, Vector2) {
|
|
||||||
if i + 1 == self.points.len() {
|
|
||||||
panic!();
|
|
||||||
}
|
|
||||||
Self::offset_by_direction(
|
|
||||||
self.points[i],
|
|
||||||
(self.points[i + 1] - self.points[i]).normalize() * width,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_end_points(&self, i: usize, width: f64) -> (Vector2, Vector2) {
|
|
||||||
if i == 0 {
|
|
||||||
panic!();
|
|
||||||
}
|
|
||||||
Self::offset_by_direction(
|
|
||||||
self.points[i],
|
|
||||||
(self.points[i] - self.points[i - 1]).normalize() * width,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn line(start: Vector2, end: Vector2) -> geo::Line<f64> {
|
|
||||||
geo::Line {
|
|
||||||
start: geo::Coord {
|
|
||||||
x: start.x,
|
|
||||||
y: start.y,
|
|
||||||
},
|
|
||||||
end: geo::Coord { x: end.x, y: end.y },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn offset_by_direction(point: Vector2, direction: Vector2) -> (Vector2, Vector2) {
|
|
||||||
(
|
|
||||||
point + vec2(direction.y, -direction.x),
|
|
||||||
point + vec2(-direction.y, direction.x),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
167
src/curve/renderer.rs
Normal file
167
src/curve/renderer.rs
Normal file
|
|
@ -0,0 +1,167 @@
|
||||||
|
use cgmath::InnerSpace;
|
||||||
|
|
||||||
|
use super::vec2;
|
||||||
|
use super::PolyLine;
|
||||||
|
use super::Vector2;
|
||||||
|
|
||||||
|
use crate::{vertex::RenderData, Vertex};
|
||||||
|
|
||||||
|
|
||||||
|
pub struct ConnectionRenderer {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConnectionRenderer {
|
||||||
|
pub fn new() -> ConnectionRenderer {
|
||||||
|
ConnectionRenderer {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(&self, line: &PolyLine, width: f64) -> RenderData {
|
||||||
|
let mut result = RenderData::new();
|
||||||
|
|
||||||
|
for i in 1..line.points.len() {
|
||||||
|
result = result.merge(Self::get_segment_render_data(line, i, width));
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 1..line.points.len() - 1 {
|
||||||
|
result = result.merge(Self::get_connection_render_data(line, i, width));
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_segment_render_data(line: &PolyLine, i: usize, width: f64) -> RenderData {
|
||||||
|
let start_points = Self::get_adjusted_start_points(line, i - 1, width);
|
||||||
|
let end_points = Self::get_adjusted_end_points(line, i, width);
|
||||||
|
let vertices: Vec<Vertex> = [start_points.0, start_points.1, end_points.0, end_points.1]
|
||||||
|
.map(Vector2::into)
|
||||||
|
.map(Vertex::new_f64)
|
||||||
|
.into_iter()
|
||||||
|
.collect();
|
||||||
|
let indices: Vec<_> = vec![0, 2, 3, 0, 3, 1];
|
||||||
|
RenderData { vertices, indices }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_connection_render_data(line: &PolyLine, i: usize, width: f64) -> RenderData {
|
||||||
|
let vertices: Vec<_> = match Self::get_connection(line, i, width) {
|
||||||
|
Some((intersection, false)) => {
|
||||||
|
vec![
|
||||||
|
Self::get_end_points(line, i, width).1,
|
||||||
|
intersection,
|
||||||
|
Self::get_start_points(line, i, width).1,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
Some((intersection, true)) => {
|
||||||
|
vec![
|
||||||
|
Self::get_end_points(line, i, width).0,
|
||||||
|
intersection,
|
||||||
|
Self::get_start_points(line, i, width).0,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
None => vec![],
|
||||||
|
}
|
||||||
|
.into_iter()
|
||||||
|
.map(Vector2::into)
|
||||||
|
.map(Vertex::new_f64)
|
||||||
|
.collect();
|
||||||
|
let indices = if vertices.is_empty() {
|
||||||
|
vec![]
|
||||||
|
} else {
|
||||||
|
vec![0, 1, 2]
|
||||||
|
};
|
||||||
|
RenderData { vertices, indices }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_adjusted_start_points(line: &PolyLine, i: usize, width: f64) -> (Vector2, Vector2) {
|
||||||
|
let start_points = Self::get_start_points(line, i, width);
|
||||||
|
if i == 0 {
|
||||||
|
return start_points;
|
||||||
|
}
|
||||||
|
match Self::get_connection(line, i, width) {
|
||||||
|
Some((intersection, false)) => (intersection, start_points.1),
|
||||||
|
Some((intersection, true)) => (start_points.0, intersection),
|
||||||
|
None => start_points,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_adjusted_end_points(line: &PolyLine, i: usize, width: f64) -> (Vector2, Vector2) {
|
||||||
|
let end_points = Self::get_end_points(line, i, width);
|
||||||
|
if i + 1 == line.points.len() {
|
||||||
|
return end_points;
|
||||||
|
}
|
||||||
|
match Self::get_connection(line, i, width) {
|
||||||
|
Some((intersection, false)) => (intersection, end_points.1),
|
||||||
|
Some((intersection, true)) => (end_points.0, intersection),
|
||||||
|
None => end_points,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_connection(line: &PolyLine, i: usize, width: f64) -> Option<(Vector2, bool)> {
|
||||||
|
let start_points = Self::get_start_points(line, i - 1, width);
|
||||||
|
let end_points = Self::get_end_points(line, i, width);
|
||||||
|
let next_start_points = Self::get_start_points(line, i, width);
|
||||||
|
let next_end_points = Self::get_end_points(line, i + 1, width);
|
||||||
|
let lines = (
|
||||||
|
make_line(start_points.0, end_points.0),
|
||||||
|
make_line(start_points.1, end_points.1),
|
||||||
|
);
|
||||||
|
let next_lines = (
|
||||||
|
make_line(next_start_points.0, next_end_points.0),
|
||||||
|
make_line(next_start_points.1, next_end_points.1),
|
||||||
|
);
|
||||||
|
|
||||||
|
use geo::algorithm::line_intersection::{line_intersection, LineIntersection};
|
||||||
|
|
||||||
|
let intersections = (
|
||||||
|
line_intersection(lines.0, next_lines.0),
|
||||||
|
line_intersection(lines.1, next_lines.1),
|
||||||
|
);
|
||||||
|
|
||||||
|
match intersections {
|
||||||
|
(Some(LineIntersection::SinglePoint { intersection, .. }), None) => {
|
||||||
|
Some((Vector2::new(intersection.x, intersection.y), false))
|
||||||
|
}
|
||||||
|
(None, Some(LineIntersection::SinglePoint { intersection, .. })) => {
|
||||||
|
Some((Vector2::new(intersection.x, intersection.y), true))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_start_points(line: &PolyLine, i: usize, width: f64) -> (Vector2, Vector2) {
|
||||||
|
if i + 1 == line.points.len() {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
Self::offset_by_direction(
|
||||||
|
line.points[i],
|
||||||
|
(line.points[i + 1] - line.points[i]).normalize() * width,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_end_points(line: &PolyLine, i: usize, width: f64) -> (Vector2, Vector2) {
|
||||||
|
if i == 0 {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
Self::offset_by_direction(
|
||||||
|
line.points[i],
|
||||||
|
(line.points[i] - line.points[i - 1]).normalize() * width,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn offset_by_direction(point: Vector2, direction: Vector2) -> (Vector2, Vector2) {
|
||||||
|
(
|
||||||
|
point + vec2(direction.y, -direction.x),
|
||||||
|
point + vec2(-direction.y, direction.x),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_line(start: Vector2, end: Vector2) -> geo::Line<f64> {
|
||||||
|
geo::Line {
|
||||||
|
start: geo::Coord {
|
||||||
|
x: start.x,
|
||||||
|
y: start.y,
|
||||||
|
},
|
||||||
|
end: geo::Coord { x: end.x, y: end.y },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -194,7 +194,8 @@ impl<'window> State<'window> {
|
||||||
)
|
)
|
||||||
.subdivide(count);
|
.subdivide(count);
|
||||||
|
|
||||||
let data = poly_line.get_render_data(width);
|
let renderer = crate::curve::renderer::ConnectionRenderer::new();
|
||||||
|
let data = renderer.render(&poly_line, width);
|
||||||
|
|
||||||
self.queue
|
self.queue
|
||||||
.write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(&data.vertices));
|
.write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(&data.vertices));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue