Added Bound::relate_clip_space with default implementation
This commit is contained in:
parent
fa3aacafcf
commit
6691dce420
8 changed files with 47 additions and 26 deletions
|
@ -242,12 +242,12 @@ impl<S: BaseFloat> Intersect<Option<Point2<S>>> for (Ray2<S>, Aabb2<S>) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Bound<S> for Aabb3<S> {
|
||||
fn relate(&self, plane: &Plane<S>) -> Relation {
|
||||
impl<S: BaseFloat + 'static> Bound<S> for Aabb3<S> {
|
||||
fn relate_plane(&self, plane: &Plane<S>) -> Relation {
|
||||
let corners = self.to_corners();
|
||||
let first = corners[0].relate(plane);
|
||||
let first = corners[0].relate_plane(plane);
|
||||
for p in corners[1..].iter() {
|
||||
if p.relate(plane) != first {
|
||||
if p.relate_plane(plane) != first {
|
||||
return Relation::Cross;
|
||||
}
|
||||
}
|
||||
|
|
22
src/bound.rs
22
src/bound.rs
|
@ -15,22 +15,32 @@
|
|||
|
||||
//! Generic spatial bounds.
|
||||
|
||||
use matrix::Matrix4;
|
||||
use num::BaseFloat;
|
||||
use plane::Plane;
|
||||
|
||||
/// Spatial relation between two objects.
|
||||
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum Relation {
|
||||
/// Completely inside
|
||||
/// Completely inside.
|
||||
In,
|
||||
/// Crosses the boundary
|
||||
/// Crosses the boundary.
|
||||
Cross,
|
||||
/// Completely outside
|
||||
/// Completely outside.
|
||||
Out,
|
||||
}
|
||||
|
||||
/// Generic bound.
|
||||
pub trait Bound<S> {
|
||||
/// Classify the spatial relation with a plane
|
||||
fn relate(&self, &Plane<S>) -> Relation;
|
||||
pub trait Bound<S: BaseFloat + 'static>: Sized {
|
||||
/// Classify the spatial relation with a plane.
|
||||
fn relate_plane(&self, &Plane<S>) -> Relation;
|
||||
/// Classify the relation with a projection matrix.
|
||||
fn relate_clip_space(&self, projection: &Matrix4<S>) -> Relation {
|
||||
use frustum::Frustum;
|
||||
match Frustum::from_matrix4(*projection) {
|
||||
Some(f) => f.contains(self),
|
||||
None => Relation::Cross,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ Frustum<S> {
|
|||
pub fn contains<B: Bound<S>>(&self, bound: &B) -> Relation {
|
||||
[&self.left, &self.right, &self.top, &self.bottom, &self.near, &self.far]
|
||||
.iter().fold(Relation::In, |cur, p| {
|
||||
let r = bound.relate(p);
|
||||
let r = bound.relate_plane(p);
|
||||
// if we see Cross, then the result is Cross
|
||||
// if we see In, then we keep the old result
|
||||
// otherwise, take the current result
|
||||
|
|
15
src/point.rs
15
src/point.rs
|
@ -24,6 +24,7 @@ use std::ops::*;
|
|||
use approx::ApproxEq;
|
||||
use array::{Array1, FixedArray};
|
||||
use bound::*;
|
||||
use matrix::{Matrix, Matrix4};
|
||||
use num::{BaseNum, BaseFloat, one, zero};
|
||||
use plane::Plane;
|
||||
use vector::*;
|
||||
|
@ -448,8 +449,8 @@ impl<S: BaseNum> fmt::Debug for Point3<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Bound<S> for Point3<S> {
|
||||
fn relate(&self, plane: &Plane<S>) -> Relation {
|
||||
impl<S: BaseFloat + 'static> Bound<S> for Point3<S> {
|
||||
fn relate_plane(&self, plane: &Plane<S>) -> Relation {
|
||||
let dist = self.dot(&plane.n);
|
||||
if dist > plane.d {
|
||||
Relation::In
|
||||
|
@ -459,4 +460,14 @@ impl<S: BaseNum> Bound<S> for Point3<S> {
|
|||
Relation::Cross
|
||||
}
|
||||
}
|
||||
|
||||
fn relate_clip_space(&self, projection: &Matrix4<S>) -> Relation {
|
||||
use std::cmp::Ordering::*;
|
||||
let p = projection.mul_v(&self.to_homogeneous());
|
||||
match (p.x.abs().partial_cmp(&p.w), p.y.abs().partial_cmp(&p.w), p.z.abs().partial_cmp(&p.w)) {
|
||||
(Some(Less), Some(Less), Some(Less)) => Relation::In,
|
||||
(Some(Greater), _, _) | (_, Some(Greater), _) | (_, _, Some(Greater)) => Relation::Out,
|
||||
_ => Relation::Cross,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
use bound::*;
|
||||
use intersect::Intersect;
|
||||
use num::{BaseNum, BaseFloat, zero};
|
||||
use num::{BaseFloat, zero};
|
||||
use point::{Point, Point3};
|
||||
use plane::Plane;
|
||||
use ray::Ray3;
|
||||
|
@ -45,8 +45,8 @@ impl<S: BaseFloat> Intersect<Option<Point3<S>>> for (Sphere<S>, Ray3<S>) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: BaseNum> Bound<S> for Sphere<S> {
|
||||
fn relate(&self, plane: &Plane<S>) -> Relation {
|
||||
impl<S: BaseFloat + 'static> Bound<S> for Sphere<S> {
|
||||
fn relate_plane(&self, plane: &Plane<S>) -> Relation {
|
||||
let dist = self.center.dot(&plane.n) - plane.d;
|
||||
if dist > self.radius {
|
||||
Relation::In
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// 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" BASisize,
|
||||
// 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.
|
||||
|
@ -99,7 +99,7 @@ fn test_bound() {
|
|||
let plane1 = Plane::from_point_normal(Point3::new(0f32, 0.0, 0.0), Vector3::new(0f32, 0.0, 1.0));
|
||||
let plane2 = Plane::from_point_normal(Point3::new(-5.0f32, 4.0, 0.0), Vector3::new(0f32, 1.0, 0.0));
|
||||
let plane3 = Plane::from_point_normal(Point3::new(6.0f32, 0.0, 0.0), Vector3::new(1f32, 0.0, 0.0));
|
||||
assert_eq!(aabb.relate(&plane1), Relation::Cross);
|
||||
assert_eq!(aabb.relate(&plane2), Relation::In);
|
||||
assert_eq!(aabb.relate(&plane3), Relation::Out);
|
||||
assert_eq!(aabb.relate_plane(&plane1), Relation::Cross);
|
||||
assert_eq!(aabb.relate_plane(&plane2), Relation::In);
|
||||
assert_eq!(aabb.relate_plane(&plane3), Relation::Out);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ fn test_bound() {
|
|||
let normal = Vector3::new(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);
|
||||
assert_eq!(point.relate_plane(&plane), Relation::Cross);
|
||||
assert_eq!(point.add_v(&normal).relate_plane(&plane), Relation::In);
|
||||
assert_eq!(point.add_v(&normal.mul_s(-1.0)).relate_plane(&plane), Relation::Out);
|
||||
}
|
||||
|
|
|
@ -38,13 +38,13 @@ fn test_bound() {
|
|||
let sphere = Sphere { center: point, radius: 1.0 };
|
||||
let normal = vec3(0f32, 0.0, 1.0);
|
||||
|
||||
assert_eq!(sphere.relate(
|
||||
assert_eq!(sphere.relate_plane(
|
||||
&Plane::from_point_normal(point, normal)
|
||||
), Relation::Cross);
|
||||
assert_eq!(sphere.relate(
|
||||
assert_eq!(sphere.relate_plane(
|
||||
&Plane::from_point_normal(point.add_v(&normal.mul_s(-3.0)), normal),
|
||||
), Relation::In);
|
||||
assert_eq!(sphere.relate(
|
||||
assert_eq!(sphere.relate_plane(
|
||||
&Plane::from_point_normal(point.add_v(&normal.mul_s(3.0)), normal),
|
||||
), Relation::Out);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue