Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debug layer and serialization #40

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ rust:
script:
- cargo build
- cargo doc
- cargo test
- cargo test --all-features
- if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then (cargo bench); fi
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
[package]
name = "plane-split"
version = "0.17.0"
version = "0.17.1"
description = "Plane splitting"
authors = ["Dzmitry Malyshau <kvark@mozilla.com>"]
license = "MPL-2.0"
repository = "https://github.com/servo/plane-split"
keywords = ["geometry", "math"]
documentation = "https://docs.rs/plane-split"

[features]
default = ["debug"]
debug = ["serde", "euclid/serde"]

[dependencies]
binary-space-partition = "0.1.2"
euclid = "0.22"
log = "0.4"
num-traits = {version = "0.2", default-features = false}
serde = { version = "1.0", features = ["serde_derive"], optional = true }
4 changes: 2 additions & 2 deletions benches/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ extern crate euclid;
extern crate plane_split;
extern crate test;

use std::sync::Arc;
use euclid::vec3;
use plane_split::{BspSplitter, Splitter, make_grid};
use plane_split::{make_grid, BspSplitter, Splitter};
use std::sync::Arc;

#[bench]
fn bench_bsp(b: &mut test::Bencher) {
Expand Down
46 changes: 27 additions & 19 deletions src/bsp.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
use {Intersection, Plane, Polygon, Splitter};
use is_zero;
use {Intersection, Plane, Polygon, Splitter};

use binary_space_partition::{BspNode, Plane as BspPlane, PlaneCut};
use euclid::{Point3D, Vector3D};
use euclid::approxeq::ApproxEq;
use euclid::{Point3D, Vector3D};
use num_traits::{Float, One, Zero};

use std::{fmt, iter, ops};


impl<T, U, A> BspPlane for Polygon<T, U, A> where
T: Copy + fmt::Debug + ApproxEq<T> +
ops::Sub<T, Output=T> + ops::Add<T, Output=T> +
ops::Mul<T, Output=T> + ops::Div<T, Output=T> +
Zero + Float,
impl<T, U, A> BspPlane for Polygon<T, U, A>
where
T: Copy
+ fmt::Debug
+ ApproxEq<T>
+ ops::Sub<T, Output = T>
+ ops::Add<T, Output = T>
+ ops::Mul<T, Output = T>
+ ops::Div<T, Output = T>
+ Zero
+ Float,
U: fmt::Debug,
A: Copy + fmt::Debug,
{
Expand Down Expand Up @@ -83,11 +88,8 @@ impl<T, U, A> BspPlane for Polygon<T, U, A> where
}
}

PlaneCut::Cut {
front,
back,
}
},
PlaneCut::Cut { front, back }
}
}
}

Expand All @@ -96,7 +98,6 @@ impl<T, U, A> BspPlane for Polygon<T, U, A> where
}
}


/// Binary Space Partitioning splitter, uses a BSP tree.
pub struct BspSplitter<T, U, A> {
tree: BspNode<Polygon<T, U, A>>,
Expand All @@ -113,11 +114,18 @@ impl<T, U, A> BspSplitter<T, U, A> {
}
}

impl<T, U, A> Splitter<T, U, A> for BspSplitter<T, U, A> where
T: Copy + fmt::Debug + ApproxEq<T> +
ops::Sub<T, Output=T> + ops::Add<T, Output=T> +
ops::Mul<T, Output=T> + ops::Div<T, Output=T> +
Zero + One + Float,
impl<T, U, A> Splitter<T, U, A> for BspSplitter<T, U, A>
where
T: Copy
+ fmt::Debug
+ ApproxEq<T>
+ ops::Sub<T, Output = T>
+ ops::Add<T, Output = T>
+ ops::Mul<T, Output = T>
+ ops::Div<T, Output = T>
+ Zero
+ One
+ Float,
U: fmt::Debug,
A: Copy + fmt::Debug + Default,
{
Expand Down
75 changes: 36 additions & 39 deletions src/clip.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use {Intersection, NegativeHemisphereError, Plane, Polygon};

use euclid::{Trig, Rect, Scale, Transform3D, Vector3D};
use euclid::approxeq::ApproxEq;
use euclid::{Rect, Scale, Transform3D, Trig, Vector3D};
use num_traits::{Float, One, Zero};

use std::{fmt, iter, mem, ops};


/// A helper object to clip polygons by a number of planes.
#[derive(Debug)]
pub struct Clipper<T, U, A> {
Expand All @@ -16,13 +15,20 @@ pub struct Clipper<T, U, A> {
}

impl<
T: Copy + fmt::Debug + ApproxEq<T> +
ops::Sub<T, Output=T> + ops::Add<T, Output=T> +
ops::Mul<T, Output=T> + ops::Div<T, Output=T> +
Zero + One + Float,
U: fmt::Debug,
A: Copy + fmt::Debug,
> Clipper<T, U, A> {
T: Copy
+ fmt::Debug
+ ApproxEq<T>
+ ops::Sub<T, Output = T>
+ ops::Add<T, Output = T>
+ ops::Mul<T, Output = T>
+ ops::Div<T, Output = T>
+ Zero
+ One
+ Float,
U: fmt::Debug,
A: Copy + fmt::Debug,
> Clipper<T, U, A>
{
/// Create a new clipper object.
pub fn new() -> Self {
Clipper {
Expand All @@ -49,33 +55,26 @@ impl<
Some(bounds) => {
let mx = Vector3D::new(t.m11, t.m21, t.m31);
let left = bounds.origin.x;
let plane_left = Plane::from_unnormalized(
mx - mw * Scale::new(left),
t.m41 - t.m44 * left,
)?;
let plane_left =
Plane::from_unnormalized(mx - mw * Scale::new(left), t.m41 - t.m44 * left)?;
let right = bounds.origin.x + bounds.size.width;
let plane_right = Plane::from_unnormalized(
mw * Scale::new(right) - mx,
t.m44 * right - t.m41,
)?;
let plane_right =
Plane::from_unnormalized(mw * Scale::new(right) - mx, t.m44 * right - t.m41)?;

let my = Vector3D::new(t.m12, t.m22, t.m32);
let top = bounds.origin.y;
let plane_top = Plane::from_unnormalized(
my - mw * Scale::new(top),
t.m42 - t.m44 * top,
)?;
let plane_top =
Plane::from_unnormalized(my - mw * Scale::new(top), t.m42 - t.m44 * top)?;
let bottom = bounds.origin.y + bounds.size.height;
let plane_bottom = Plane::from_unnormalized(
mw * Scale::new(bottom) - my,
t.m44 * bottom - t.m42,
)?;

Some(plane_left
.into_iter()
.chain(plane_right)
.chain(plane_top)
.chain(plane_bottom)
let plane_bottom =
Plane::from_unnormalized(mw * Scale::new(bottom) - my, t.m44 * bottom - t.m42)?;

Some(
plane_left
.into_iter()
.chain(plane_right)
.chain(plane_top)
.chain(plane_bottom),
)
}
None => None,
Expand All @@ -84,8 +83,7 @@ impl<
Ok(bounds_iter_maybe
.into_iter()
.flat_map(|pi| pi)
.chain(plane_positive)
)
.chain(plane_positive))
}

/// Add a clipping plane to the list. The plane will clip everything behind it,
Expand All @@ -112,17 +110,15 @@ impl<
iter::once(poly)
.chain(res1)
.chain(res2)
.filter(|p| clip.signed_distance_sum_to(p) > T::zero())
.filter(|p| clip.signed_distance_sum_to(p) > T::zero()),
);
continue
continue;
}
Intersection::Coplanar => {
let ndot = poly.plane.normal.dot(clip.normal);
clip.offset - ndot * poly.plane.offset
}
Intersection::Outside => {
clip.signed_distance_sum_to(&poly)
}
Intersection::Outside => clip.signed_distance_sum_to(&poly),
};

if dist > T::zero() {
Expand Down Expand Up @@ -157,7 +153,8 @@ impl<
self.clips.pop();
}

let polys = self.results
let polys = self
.results
.drain(..)
.flat_map(move |poly| poly.transform(transform));
Ok(polys)
Expand Down
74 changes: 74 additions & 0 deletions src/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use crate::{Polygon, Splitter};
use serde::{Serialize, Serializer};

/// Serialized work for a plane splitter.
pub struct Dump<T, U, A> {
/// input polygons
input: Vec<Polygon<T, U, A>>,
/// view used to sort
view: euclid::Vector3D<T, U>,
/// split polygons
output: Vec<Polygon<T, U, A>>,
}

impl<T: Serialize, U, A: Serialize> Serialize for Dump<T, U, A> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeStruct;
let mut me = serializer.serialize_struct("Dump", 3)?;
me.serialize_field("input", &self.input)?;
me.serialize_field("view", &self.view)?;
me.serialize_field("output", &self.output)?;
me.end()
}
}

/// Debug layer that records the interface into a dump.
pub struct DebugLayer<T, U, A, Z> {
/// Actual plane splitting implementation.
inner: Z,
/// Dump of the work.
dump: Dump<T, U, A>,
}

impl<T: Default, U, A, Z> DebugLayer<T, U, A, Z> {
/// Create a new debug layer.
pub fn new(inner: Z) -> Self {
DebugLayer {
inner,
dump: Dump {
input: Vec::new(),
view: Default::default(),
output: Vec::new(),
},
}
}

/// Get the current work dump.
pub fn dump(&self) -> &Dump<T, U, A> {
&self.dump
}
}

impl<T: Clone, U, A: Copy, Z: Splitter<T, U, A>> Splitter<T, U, A> for DebugLayer<T, U, A, Z> {
fn reset(&mut self) {
self.dump.input.clear();
self.inner.reset();
}

/// Add a new polygon and return a slice of the subdivisions
/// that avoid collision with any of the previously added polygons.
fn add(&mut self, polygon: Polygon<T, U, A>) {
self.dump.input.push(polygon.clone());
self.inner.add(polygon);
}

/// Sort the produced polygon set by the ascending distance across
/// the specified view vector. Return the sorted slice.
fn sort(&mut self, view: euclid::Vector3D<T, U>) -> &[Polygon<T, U, A>] {
self.dump.view = view.clone();
let sorted = self.inner.sort(view);
self.dump.output.clear();
self.dump.output.extend_from_slice(sorted);
sorted
}
}