/// <summary>Expands 'lhs' to include 'rhs'. Returns **rhs**</summary> public static BBox Grow(ref BBox lhs, BBox rhs) { // Const version returns lhs, non-const returns rhs! // Don't treat !rhs.IsValid as an error, it's the only way to grow an empty bbox if (!rhs.IsValid) { return(rhs); } lhs = Union(lhs, rhs.Centre + rhs.Radius); lhs = Union(lhs, rhs.Centre - rhs.Radius); return(rhs); }
/// <summary> /// Clip a line segment to a bounding box returning the parametric values of the intersection. /// Returns false if the line does not intersect with the bounding box. /// Assumes initial values of 't0' and 't1' have been set.</summary> public static bool Clip(BBox bbox, v4 point_, v4 direction_, ref float t0, ref float t1) { // Convert v4's to float arrays for efficient indexing var lower = (float[])bbox.Lower(); var upper = (float[])bbox.Upper(); var point = (float[])point_; var direction = (float[])direction_; // For all three slabs for (int i = 0; i != 3; ++i) { if (Math.Abs(direction[i]) < Math_.TinyF) { // Ray is parallel to slab. No hit if origin not within slab if (point[i] < lower[i] || point[i] > upper[i]) { return(false); } } else { // Compute intersection t value of ray with near and far plane of slab float u0 = (lower[i] - point[i]) / direction[i]; float u1 = (upper[i] - point[i]) / direction[i]; // Make u0 be intersection with near plane, u1 with far plane if (u0 > u1) { Math_.Swap(ref u0, ref u1); } // Record the tightest bounds on the line segment if (u0 > t0) { t0 = u0; } if (u1 < t1) { t1 = u1; } // Exit with no collision as soon as slab intersection becomes empty if (t0 > t1) { return(false); } } } // Ray intersects all 3 slabs return(true); }
public static BBox operator *(m4x4 m, BBox rhs) { Debug.Assert(rhs.IsValid, "Transforming an invalid bounding box"); var bb = new BBox(m.pos, v4.Zero); var mat = Math_.Transpose3x3(m); bb.Centre.x += Math_.Dot(mat.x, rhs.Centre); bb.Radius.x += Math_.Dot(Math_.Abs(mat.x), rhs.Radius); bb.Centre.y += Math_.Dot(mat.y, rhs.Centre); bb.Radius.y += Math_.Dot(Math_.Abs(mat.y), rhs.Radius); bb.Centre.z += Math_.Dot(mat.z, rhs.Centre); bb.Radius.z += Math_.Dot(Math_.Abs(mat.z), rhs.Radius); return(bb); }
/// <summary>Returns a bbox that encloses 'lhs' and 'rhs'</summary> public static BBox Union(BBox lhs, BBox rhs) { // Const version returns lhs, non-const returns rhs! // Don't treat !rhs.IsValid as an error, it's the only way to grow an empty bbox var bb = lhs; if (!rhs.IsValid) { return(bb); } bb = Union(bb, rhs.Centre + rhs.Radius); bb = Union(bb, rhs.Centre - rhs.Radius); return(bb); }
/// <summary>Expands 'lhs' to include 'rhs'. Returns **rhs**</summary> public static v4 Grow(ref BBox bbox, v4 point) { // Const version returns lhs, non-const returns rhs! bbox = Union(bbox, point); return(point); }