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> {
|
impl<S: BaseFloat + 'static> Bound<S> for Aabb3<S> {
|
||||||
fn relate(&self, plane: &Plane<S>) -> Relation {
|
fn relate_plane(&self, plane: &Plane<S>) -> Relation {
|
||||||
let corners = self.to_corners();
|
let corners = self.to_corners();
|
||||||
let first = corners[0].relate(plane);
|
let first = corners[0].relate_plane(plane);
|
||||||
for p in corners[1..].iter() {
|
for p in corners[1..].iter() {
|
||||||
if p.relate(plane) != first {
|
if p.relate_plane(plane) != first {
|
||||||
return Relation::Cross;
|
return Relation::Cross;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
src/bound.rs
22
src/bound.rs
|
@ -15,22 +15,32 @@
|
||||||
|
|
||||||
//! Generic spatial bounds.
|
//! Generic spatial bounds.
|
||||||
|
|
||||||
|
use matrix::Matrix4;
|
||||||
|
use num::BaseFloat;
|
||||||
use plane::Plane;
|
use plane::Plane;
|
||||||
|
|
||||||
/// Spatial relation between two objects.
|
/// Spatial relation between two objects.
|
||||||
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Relation {
|
pub enum Relation {
|
||||||
/// Completely inside
|
/// Completely inside.
|
||||||
In,
|
In,
|
||||||
/// Crosses the boundary
|
/// Crosses the boundary.
|
||||||
Cross,
|
Cross,
|
||||||
/// Completely outside
|
/// Completely outside.
|
||||||
Out,
|
Out,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generic bound.
|
/// Generic bound.
|
||||||
pub trait Bound<S> {
|
pub trait Bound<S: BaseFloat + 'static>: Sized {
|
||||||
/// Classify the spatial relation with a plane
|
/// Classify the spatial relation with a plane.
|
||||||
fn relate(&self, &Plane<S>) -> Relation;
|
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 {
|
pub fn contains<B: Bound<S>>(&self, bound: &B) -> Relation {
|
||||||
[&self.left, &self.right, &self.top, &self.bottom, &self.near, &self.far]
|
[&self.left, &self.right, &self.top, &self.bottom, &self.near, &self.far]
|
||||||
.iter().fold(Relation::In, |cur, p| {
|
.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 Cross, then the result is Cross
|
||||||
// if we see In, then we keep the old result
|
// if we see In, then we keep the old result
|
||||||
// otherwise, take the current 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 approx::ApproxEq;
|
||||||
use array::{Array1, FixedArray};
|
use array::{Array1, FixedArray};
|
||||||
use bound::*;
|
use bound::*;
|
||||||
|
use matrix::{Matrix, Matrix4};
|
||||||
use num::{BaseNum, BaseFloat, one, zero};
|
use num::{BaseNum, BaseFloat, one, zero};
|
||||||
use plane::Plane;
|
use plane::Plane;
|
||||||
use vector::*;
|
use vector::*;
|
||||||
|
@ -448,8 +449,8 @@ impl<S: BaseNum> fmt::Debug for Point3<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseNum> Bound<S> for Point3<S> {
|
impl<S: BaseFloat + 'static> Bound<S> for Point3<S> {
|
||||||
fn relate(&self, plane: &Plane<S>) -> Relation {
|
fn relate_plane(&self, plane: &Plane<S>) -> Relation {
|
||||||
let dist = self.dot(&plane.n);
|
let dist = self.dot(&plane.n);
|
||||||
if dist > plane.d {
|
if dist > plane.d {
|
||||||
Relation::In
|
Relation::In
|
||||||
|
@ -459,4 +460,14 @@ impl<S: BaseNum> Bound<S> for Point3<S> {
|
||||||
Relation::Cross
|
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 bound::*;
|
||||||
use intersect::Intersect;
|
use intersect::Intersect;
|
||||||
use num::{BaseNum, BaseFloat, zero};
|
use num::{BaseFloat, zero};
|
||||||
use point::{Point, Point3};
|
use point::{Point, Point3};
|
||||||
use plane::Plane;
|
use plane::Plane;
|
||||||
use ray::Ray3;
|
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> {
|
impl<S: BaseFloat + 'static> Bound<S> for Sphere<S> {
|
||||||
fn relate(&self, plane: &Plane<S>) -> Relation {
|
fn relate_plane(&self, plane: &Plane<S>) -> Relation {
|
||||||
let dist = self.center.dot(&plane.n) - plane.d;
|
let dist = self.center.dot(&plane.n) - plane.d;
|
||||||
if dist > self.radius {
|
if dist > self.radius {
|
||||||
Relation::In
|
Relation::In
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
//
|
//
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
// 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.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// 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 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 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));
|
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_plane(&plane1), Relation::Cross);
|
||||||
assert_eq!(aabb.relate(&plane2), Relation::In);
|
assert_eq!(aabb.relate_plane(&plane2), Relation::In);
|
||||||
assert_eq!(aabb.relate(&plane3), Relation::Out);
|
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 normal = Vector3::new(0f32, -0.8, -0.36);
|
||||||
let plane = Plane::from_point_normal(point, normal);
|
let plane = Plane::from_point_normal(point, normal);
|
||||||
|
|
||||||
assert_eq!(point.relate(&plane), Relation::Cross);
|
assert_eq!(point.relate_plane(&plane), Relation::Cross);
|
||||||
assert_eq!(point.add_v(&normal).relate(&plane), Relation::In);
|
assert_eq!(point.add_v(&normal).relate_plane(&plane), Relation::In);
|
||||||
assert_eq!(point.add_v(&normal.mul_s(-1.0)).relate(&plane), Relation::Out);
|
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 sphere = Sphere { center: point, radius: 1.0 };
|
||||||
let normal = vec3(0f32, 0.0, 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)
|
&Plane::from_point_normal(point, normal)
|
||||||
), Relation::Cross);
|
), Relation::Cross);
|
||||||
assert_eq!(sphere.relate(
|
assert_eq!(sphere.relate_plane(
|
||||||
&Plane::from_point_normal(point.add_v(&normal.mul_s(-3.0)), normal),
|
&Plane::from_point_normal(point.add_v(&normal.mul_s(-3.0)), normal),
|
||||||
), Relation::In);
|
), Relation::In);
|
||||||
assert_eq!(sphere.relate(
|
assert_eq!(sphere.relate_plane(
|
||||||
&Plane::from_point_normal(point.add_v(&normal.mul_s(3.0)), normal),
|
&Plane::from_point_normal(point.add_v(&normal.mul_s(3.0)), normal),
|
||||||
), Relation::Out);
|
), Relation::Out);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue