From d3d7241c86e89d0c3de8bf9b0580da79858ac484 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 13 Mar 2015 11:32:23 +0300 Subject: [PATCH] Moved bound implementations into the corresponding modules --- src/aabb.rs | 13 +++++++++++ src/bound.rs | 58 +++++++++----------------------------------------- src/point.rs | 15 +++++++++++++ src/sphere.rs | 17 ++++++++++++++- tests/bound.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 49 deletions(-) create mode 100644 tests/bound.rs diff --git a/src/aabb.rs b/src/aabb.rs index 5cb8620..aab695a 100644 --- a/src/aabb.rs +++ b/src/aabb.rs @@ -20,11 +20,13 @@ //! dimension) where the slope of every line is either 0 or undefined. These //! are useful for very cheap collision detection. +use bound::*; use point::{Point, Point2, Point3}; use vector::{Vector, Vector2, Vector3}; use ray::{Ray2}; use intersect::Intersect; use num::{zero, one, BaseNum, BaseFloat}; +use plane::Plane; use std::fmt; use std::num::Float; @@ -217,3 +219,14 @@ impl Intersect>> for (Ray2, Aabb2) { } } } + +impl Bound for Aabb3 { + fn relate(&self, plane: &Plane) -> Relation { + //TODO: match all 8 corners + match (self.min.relate(plane), self.max.relate(plane)) { + (Relation::In, Relation::In) => Relation::In, + (Relation::Out, Relation::Out) => Relation::Out, + (_, _) => Relation::Cross, + } + } +} diff --git a/src/bound.rs b/src/bound.rs index 753ae1a..cc5ff56 100644 --- a/src/bound.rs +++ b/src/bound.rs @@ -15,60 +15,22 @@ //! Generic spatial bounds. -use aabb::{Aabb, Aabb3}; -use num::BaseNum; use plane::Plane; -use point::{Point, Point3}; -use sphere::Sphere; /// Spatial relation between two objects. +#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] +#[repr(u8)] pub enum Relation { - /// Completely inside - In, - /// Crosses the boundary - Cross, - /// Completely outside - Out, + /// Completely inside + In, + /// Crosses the boundary + Cross, + /// Completely outside + Out, } /// Generic bound. pub trait Bound { - /// Classify the spatial relation with a plane - fn relate(&self, &Plane) -> Relation; -} - -impl Bound for Point3 { - fn relate(&self, plane: &Plane) -> Relation { - let dist = self.dot(&plane.n); - if dist > plane.d { - Relation::In - }else if dist < plane.d { - Relation::Out - }else { - Relation::Cross - } - } -} - -impl Bound for Aabb3 { - fn relate(&self, plane: &Plane) -> Relation { - match (self.min.relate(plane), self.max.relate(plane)) { - (Relation::In, Relation::In) => Relation::In, - (Relation::Out, Relation::Out) => Relation::Out, - (_, _) => Relation::Cross, - } - } -} - -impl Bound for Sphere { - fn relate(&self, plane: &Plane) -> Relation { - let dist = self.center.dot(&plane.n) - plane.d; - if dist > self.radius { - Relation::In - }else if dist < - self.radius { - Relation::Out - }else { - Relation::Cross - } - } + /// Classify the spatial relation with a plane + fn relate(&self, &Plane) -> Relation; } diff --git a/src/point.rs b/src/point.rs index 4b8d6e3..6e2bf0d 100644 --- a/src/point.rs +++ b/src/point.rs @@ -23,7 +23,9 @@ use std::ops::*; use approx::ApproxEq; use array::{Array1, FixedArray}; +use bound::*; use num::{BaseNum, BaseFloat, one, zero}; +use plane::Plane; use vector::*; /// A point in 2-dimensional space. @@ -445,3 +447,16 @@ impl fmt::Debug for Point3 { write!(f, "[{:?}, {:?}, {:?}]", self.x, self.y, self.z) } } + +impl Bound for Point3 { + fn relate(&self, plane: &Plane) -> Relation { + let dist = self.dot(&plane.n); + if dist > plane.d { + Relation::In + }else if dist < plane.d { + Relation::Out + }else { + Relation::Cross + } + } +} diff --git a/src/sphere.rs b/src/sphere.rs index 46474e9..519be4f 100644 --- a/src/sphere.rs +++ b/src/sphere.rs @@ -15,9 +15,11 @@ //! Bounding sphere +use bound::*; use intersect::Intersect; -use num::{BaseFloat, zero}; +use num::{BaseNum, BaseFloat, zero}; use point::{Point, Point3}; +use plane::Plane; use ray::Ray3; use vector::Vector; @@ -42,3 +44,16 @@ impl Intersect>> for (Sphere, Ray3) { } } } + +impl Bound for Sphere { + fn relate(&self, plane: &Plane) -> Relation { + let dist = self.center.dot(&plane.n) - plane.d; + if dist > self.radius { + Relation::In + }else if dist < - self.radius { + Relation::Out + }else { + Relation::Cross + } + } +} diff --git a/tests/bound.rs b/tests/bound.rs new file mode 100644 index 0000000..2716a5c --- /dev/null +++ b/tests/bound.rs @@ -0,0 +1,51 @@ +// Copyright 2013-2015 The CGMath Developers. For a full listing of the authors, +// refer to the AUTHORS file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +extern crate cgmath; + +use cgmath::{Aabb3, Bound, Plane, Point, Point3, Relation, Sphere, Vector, vec3}; + +#[test] +fn point() { + let point = Point3::new(1f32, 2.0, 3.0); + let normal = vec3(0f32, -0.8, -0.36); + let plane = Plane::from_point_normal(point, normal); + + assert_eq!(point.relate(&plane), Relation::Cross); + assert_eq!(point.add_v(&normal).relate(&plane), Relation::In); + assert_eq!(point.add_v(&normal.mul_s(-1.0)).relate(&plane), Relation::Out); +} + +#[test] +fn sphere() { + let point = Point3::new(1f32, 2.0, 3.0); + let sphere = Sphere { center: point, radius: 1.0 }; + let normal = vec3(0f32, 0.0, 1.0); + + assert_eq!(sphere.relate( + &Plane::from_point_normal(point, normal) + ), Relation::Cross); + assert_eq!(sphere.relate( + &Plane::from_point_normal(point.add_v(&normal.mul_s(-3.0)), normal), + ), Relation::In); + assert_eq!(sphere.relate( + &Plane::from_point_normal(point.add_v(&normal.mul_s(3.0)), normal), + ), Relation::Out); +} + +#[test] +fn aabb() { + //TODO +}