From f30b79deb3487d496f3ed1e326949fdac2136f99 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 12 Jul 2013 09:18:05 +1000 Subject: [PATCH] Add some more types to geom and improve field names --- src/geom/aabb.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++ src/geom/box.rs | 16 ++++++++++ src/geom/cylinder.rs | 17 +++++++++++ src/geom/geom.rs | 6 ++++ src/geom/plane.rs | 68 ++++++++++++++++++++++-------------------- src/geom/point.rs | 4 +++ src/geom/ray.rs | 23 ++++++++------- src/geom/sphere.rs | 30 +++++++++++++++++++ 8 files changed, 191 insertions(+), 43 deletions(-) create mode 100644 src/geom/aabb.rs create mode 100644 src/geom/box.rs create mode 100644 src/geom/cylinder.rs create mode 100644 src/geom/sphere.rs diff --git a/src/geom/aabb.rs b/src/geom/aabb.rs new file mode 100644 index 0000000..df8fbf5 --- /dev/null +++ b/src/geom/aabb.rs @@ -0,0 +1,70 @@ +// Copyright 2013 The Lmath 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. + +//! Axis-aligned bounding boxes + +use core::{Vec2, Vec3}; +use geom::{Point2, Point3}; + +#[path = "../num_macros.rs"] +mod num_macros; + +pub struct AABB2 { + center: Point2, + size: Vec2, +} + +impl AABB2 { + #[inline] + pub fn new(center: Point2, size: Vec2) -> AABB2 { + AABB2 { center: center, size: size } + } +} + +impl AABB2 { + #[inline] + pub fn from_bounds(mn: Point2, mx: Point2) -> AABB2 { + AABB2 { + center: Point2::from_vec(mn.as_vec() + .add_v(mx.as_vec()) + .div_t(two!(T))), + size: mx - mn, + } + } +} + +pub struct AABB3 { + center: Point3, + size: Vec3, +} + +impl AABB3 { + #[inline] + pub fn new(center: Point3, size: Vec3) -> AABB3 { + AABB3 { center: center, size: size } + } +} + +impl AABB3 { + #[inline] + pub fn from_bounds(mn: Point3, mx: Point3) -> AABB3 { + AABB3 { + center: Point3::from_vec(mn.as_vec() + .add_v(mx.as_vec()) + .div_t(two!(T))), + size: mx - mn, + } + } +} diff --git a/src/geom/box.rs b/src/geom/box.rs new file mode 100644 index 0000000..0bed11c --- /dev/null +++ b/src/geom/box.rs @@ -0,0 +1,16 @@ +// Copyright 2013 The Lmath 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. + +//! Bounding boxes diff --git a/src/geom/cylinder.rs b/src/geom/cylinder.rs new file mode 100644 index 0000000..a966fd6 --- /dev/null +++ b/src/geom/cylinder.rs @@ -0,0 +1,17 @@ +// Copyright 2013 The Lmath 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. + +//! Bounding cylinder + diff --git a/src/geom/geom.rs b/src/geom/geom.rs index 8067480..9d0f5fc 100644 --- a/src/geom/geom.rs +++ b/src/geom/geom.rs @@ -13,12 +13,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +pub use self::aabb::{AABB2, AABB3}; pub use self::frustum::{Frustum, FrustumPoints}; pub use self::plane::Plane3; pub use self::point::{Point, Point2, Point3}; pub use self::ray::Ray3; +pub use self::sphere::Sphere; +pub mod aabb; +pub mod box; +pub mod cylinder; pub mod frustum; pub mod plane; pub mod point; pub mod ray; +pub mod sphere; diff --git a/src/geom/plane.rs b/src/geom/plane.rs index c32d341..b8ee7d3 100644 --- a/src/geom/plane.rs +++ b/src/geom/plane.rs @@ -23,15 +23,15 @@ mod num_macros; /// /// # Fields /// -/// - `n`: the normal of the plane where: -/// - `n.x`: corresponds to `A` in the plane equation -/// - `n.y`: corresponds to `B` in the plane equation -/// - `n.z`: corresponds to `C` in the plane equation -/// - `d`: the distance value, corresponding to `D` in the plane equation +/// - `normal`: the normal of the plane where: +/// - `normal.x`: corresponds to `A` in the plane equation +/// - `normal.y`: corresponds to `B` in the plane equation +/// - `normal.z`: corresponds to `C` in the plane equation +/// - `distance`: the distance value, corresponding to `D` in the plane equation #[deriving(Clone, Eq)] pub struct Plane3 { - norm: Vec3, - dist: T, + normal: Vec3, + distance: T, } impl Plane3 { @@ -43,14 +43,14 @@ impl Plane3 { /// - `d`: the plane's distance value pub fn from_abcd(a: T, b: T, c: T, d: T) -> Plane3 { Plane3 { - norm: Vec3::new(a, b, c), - dist: d, + normal: Vec3::new(a, b, c), + distance: d, } } - /// Construct a plane from a normal vector `n` and a distance `d` - pub fn from_nd(norm: Vec3, dist: T) -> Plane3 { - Plane3 { norm: norm, dist: dist } + /// Construct a plane from a normal vector and a scalar distance + pub fn from_nd(normal: Vec3, distance: T) -> Plane3 { + Plane3 { normal: normal, distance: distance } } /// Construct a plane from the components of a four-dimensional vector @@ -60,7 +60,7 @@ impl Plane3 { /// Compute the distance from the plane to the point pub fn distance(&self, pos: &Point3) -> T { - self.norm.dot(pos.as_vec()) + self.dist + self.normal.dot(pos.as_vec()) + self.distance } /// Computes the point at which `ray` intersects the plane @@ -88,16 +88,16 @@ impl Plane3 { let v0 = (b - a); let v1 = (c - a); // find the vector that is perpendicular to v1 and v2 - let mut norm = v0.cross(&v1); + let mut normal = v0.cross(&v1); - if norm.approx_eq(&Vec3::zero()) { + if normal.approx_eq(&Vec3::zero()) { None } else { // compute the normal and the distance to the plane - norm.normalize_self(); - let dist = -a.as_vec().dot(&norm); + normal.normalize_self(); + let distance = -a.as_vec().dot(&normal); - Some(Plane3::from_nd(norm, dist)) + Some(Plane3::from_nd(normal, distance)) } } @@ -108,17 +108,17 @@ impl Plane3 { /// - `Some(r)`: The ray `r` where the planes intersect. /// - `None`: No valid intersection was found. The planes are probably parallel. pub fn intersection_2pl(&self, other: &Plane3) -> Option> { - let ray_dir = self.norm.cross(&other.norm); + let dir = self.normal.cross(&other.normal); - if ray_dir.approx_eq(&Vec3::zero::()) { + if dir.approx_eq(&Vec3::zero::()) { None // the planes are parallel } else { // The end-point of the ray is at the three-plane intersection between // `self`, `other`, and a tempory plane positioned at the origin - do Plane3::from_nd(ray_dir.clone(), zero!(T)).intersection_3pl(self, other).map |ray_pos| { + do Plane3::from_nd(dir.clone(), zero!(T)).intersection_3pl(self, other).map |origin| { Ray3 { - pos: ray_pos.clone(), - dir: ray_dir.clone(), + origin: origin.clone(), + direction: dir.clone(), } } } @@ -132,13 +132,13 @@ impl Plane3 { /// - `None`: No valid intersection was found. The normals of the three /// planes are probably coplanar. pub fn intersection_3pl(&self, other_a: &Plane3, other_b: &Plane3) -> Option> { - let mx = Mat3::new(self.norm.x.clone(), other_a.norm.x.clone(), other_b.norm.x.clone(), - self.norm.y.clone(), other_a.norm.y.clone(), other_b.norm.y.clone(), - self.norm.z.clone(), other_a.norm.z.clone(), other_b.norm.z.clone()); + let mx = Mat3::new(self.normal.x.clone(), other_a.normal.x.clone(), other_b.normal.x.clone(), + self.normal.y.clone(), other_a.normal.y.clone(), other_b.normal.y.clone(), + self.normal.z.clone(), other_a.normal.z.clone(), other_b.normal.z.clone()); do mx.inverse().map |m| { - Point3::origin() + m.mul_v(&Vec3::new(self.dist.clone(), - other_a.dist.clone(), - other_b.dist.clone())) + Point3::origin() + m.mul_v(&Vec3::new(self.distance.clone(), + other_a.distance.clone(), + other_b.distance.clone())) } } } @@ -156,14 +156,18 @@ impl> ApproxEq for Plane3 { #[inline] pub fn approx_eq_eps(&self, other: &Plane3, epsilon: &T) -> bool { - self.norm.approx_eq_eps(&other.norm, epsilon) && - self.dist.approx_eq_eps(&other.dist, epsilon) + self.normal.approx_eq_eps(&other.normal, epsilon) && + self.distance.approx_eq_eps(&other.distance, epsilon) } } impl ToStr for Plane3 { pub fn to_str(&self) -> ~str { - fmt!("%?x + %?y + %?z + %? = 0", self.norm.x, self.norm.y, self.norm.z, self.dist) + fmt!("%?x + %?y + %?z + %? = 0", + self.normal.x, + self.normal.y, + self.normal.z, + self.distance) } } diff --git a/src/geom/point.rs b/src/geom/point.rs index 83d4052..8d0b6ca 100644 --- a/src/geom/point.rs +++ b/src/geom/point.rs @@ -115,11 +115,13 @@ impl Point> for Point2 { ((*other) - (*self)).length2() } + /// Returns the scalar distance to the other point #[inline] pub fn distance(&self, other: &Point2) -> T { other.distance2(self).sqrt() } + /// Returns a normalized direction vector pointing to the other point #[inline] pub fn direction(&self, other: &Point2) -> Vec2 { ((*other) - (*self)).normalize() @@ -252,11 +254,13 @@ impl Point> for Point3 { ((*other) - (*self)).length2() } + /// Returns the scalar distance to the other point #[inline] pub fn distance(&self, other: &Point3) -> T { other.distance2(self).sqrt() } + /// Returns a normalized direction vector pointing to the other point #[inline] pub fn direction(&self, other: &Point3) -> Vec3 { ((*other) - (*self)).normalize() diff --git a/src/geom/ray.rs b/src/geom/ray.rs index d58dfa1..643ae1a 100644 --- a/src/geom/ray.rs +++ b/src/geom/ray.rs @@ -1,5 +1,5 @@ // Copyright 2013 The Lmath Developers. For a full listing of the authors, -// refer to the AUTHORS file at the top-level directory of this distribution. +// refer to the AUTHORS file at the top-level directionectory 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. @@ -16,16 +16,17 @@ use core::Vec3; use geom::Point3; -/// A three-dimensional ray -/// -/// # Fields -/// -/// - `pos`: the endpoint of the ray -/// - `dir`: the direction vector #[deriving(Clone, Eq)] pub struct Ray3 { - pos: Point3, - dir: Vec3, + origin: Point3, + direction: Vec3, +} + +impl Ray3 { + #[inline] + pub fn new(origin: Point3, direction: Vec3) -> Ray3 { + Ray3 { origin: origin, direction: direction } + } } impl> ApproxEq for Ray3 { @@ -41,7 +42,7 @@ impl> ApproxEq for Ray3 { #[inline] pub fn approx_eq_eps(&self, other: &Ray3, epsilon: &T) -> bool { - self.pos.approx_eq_eps(&other.pos, epsilon) && - self.dir.approx_eq_eps(&other.dir, epsilon) + self.origin.approx_eq_eps(&other.origin, epsilon) && + self.direction.approx_eq_eps(&other.direction, epsilon) } } diff --git a/src/geom/sphere.rs b/src/geom/sphere.rs new file mode 100644 index 0000000..862e1ca --- /dev/null +++ b/src/geom/sphere.rs @@ -0,0 +1,30 @@ +// Copyright 2013 The Lmath 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. + +//! Bounding sphere + +use geom::Point3; + +pub struct Sphere { + center: Point3, + radius: T, +} + +impl Sphere { + #[inline] + pub fn new(center: Point3, radius: T) -> Sphere { + Sphere { center: center, radius: radius } + } +}