public static AxisAlignedBox3D Union(AxisAlignedBox3D b, AxisAlignedBox3D b2) { AxisAlignedBox3D ret; ret.Min.X = CheckedMin(b.Min.X, b2.Min.X); ret.Min.Y = CheckedMin(b.Min.Y, b2.Min.Y); ret.Min.Z = CheckedMin(b.Min.Z, b2.Min.Z); ret.Max.X = CheckedMax(b.Max.X, b2.Max.X); ret.Max.Y = CheckedMax(b.Max.Y, b2.Max.Y); ret.Max.Z = CheckedMax(b.Max.Z, b2.Max.Z); return(ret); }
public static AxisAlignedBox3D Union(AxisAlignedBox3D b, Point3D p) { AxisAlignedBox3D ret = b; ret.Min.X = CheckedMin(b.Min.X, p.X); ret.Min.Y = CheckedMin(b.Min.Y, p.Y); ret.Min.Z = CheckedMin(b.Min.Z, p.Z); ret.Max.X = CheckedMax(b.Max.X, p.X); ret.Max.Y = CheckedMax(b.Max.Y, p.Y); ret.Max.Z = CheckedMax(b.Max.Z, p.Z); return(ret); }
public AxisAlignedBox3D Transform(Matrix3D matrix) { AxisAlignedBox3D result = new AxisAlignedBox3D(matrix.Transform(new Point3D(Min.X, Min.Y, Min.Z))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Max.X, Min.Y, Min.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Min.X, Max.Y, Min.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Min.X, Min.Y, Max.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Min.X, Max.Y, Max.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Max.X, Max.Y, Min.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Max.X, Min.Y, Max.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Max.X, Max.Y, Max.Z)))); return(result); }
public ContainmentType Contains(AxisAlignedBox3D box) { // FIXME: Is this a bug? // If the bounding box is of W * D * H = 0, then return disjoint if (box.Min == box.Max) { return(ContainmentType.Disjoint); } int i; ContainmentType contained; Point3D[] corners = box.GetCorners(); // First we assume completely disjoint. So if we find a point that is contained, we break out of this loop for (i = 0; i < corners.Length; i++) { if (Contains(corners[i]) != ContainmentType.Disjoint) { break; } } if (i == corners.Length) // This means we checked all the corners and they were all disjoint { return(ContainmentType.Disjoint); } if (i != 0) // if i is not equal to zero, we can fastpath and say that this box intersects { // because we know at least one point is outside and one is inside. return(ContainmentType.Intersects); } // If we get here, it means the first (and only) point we checked was actually contained in the frustum. // So we assume that all other points will also be contained. If one of the points is disjoint, we can // exit immediately saying that the result is Intersects i++; for (; i < corners.Length; i++) { if (Contains(corners[i]) != ContainmentType.Contains) { return(ContainmentType.Intersects); } } // If we get here, then we know all the points were actually contained, therefore result is Contains return(ContainmentType.Contains); }
public static AxisAlignedBox3D Union(AxisAlignedBox3D b, Point3D p) { AxisAlignedBox3D ret = b; ret.Min.X = CheckedMin(b.Min.X, p.X); ret.Min.Y = CheckedMin(b.Min.Y, p.Y); ret.Min.Z = CheckedMin(b.Min.Z, p.Z); ret.Max.X = CheckedMax(b.Max.X, p.X); ret.Max.Y = CheckedMax(b.Max.Y, p.Y); ret.Max.Z = CheckedMax(b.Max.Z, p.Z); return ret; }
public AxisAlignedBox3D Transform(Matrix3D matrix) { AxisAlignedBox3D result = new AxisAlignedBox3D(matrix.Transform(new Point3D(Min.X, Min.Y, Min.Z))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Max.X, Min.Y, Min.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Min.X, Max.Y, Min.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Min.X, Min.Y, Max.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Min.X, Max.Y, Max.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Max.X, Max.Y, Min.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Max.X, Min.Y, Max.Z)))); result = Union(result, new AxisAlignedBox3D(matrix.Transform(new Point3D(Max.X, Max.Y, Max.Z)))); return result; }
public AxisAlignedBox3D CreateTransformedBoundingVolume(Matrix3D transform) { AxisAlignedBox3D result = new AxisAlignedBox3D(); // For all three axes. for (int i = 0; i < 3; ++i) { // Start by adding in translation. result.Min[i] = result.Max[i] = transform[i, 3]; // Form extent by summing smaller and larger terms respectively. for (int j = 0; j < 3; ++j) { float e = transform[i, j] * Min[j]; float f = transform[i, j] * Max[j]; if (e < f) { result.Min[i] += e; result.Max[i] += f; } else { result.Min[i] += f; result.Max[i] += e; } } } return result; }
public static AxisAlignedBox3D Union(AxisAlignedBox3D b, AxisAlignedBox3D b2) { AxisAlignedBox3D ret; ret.Min.X = CheckedMin(b.Min.X, b2.Min.X); ret.Min.Y = CheckedMin(b.Min.Y, b2.Min.Y); ret.Min.Z = CheckedMin(b.Min.Z, b2.Min.Z); ret.Max.X = CheckedMax(b.Max.X, b2.Max.X); ret.Max.Y = CheckedMax(b.Max.Y, b2.Max.Y); ret.Max.Z = CheckedMax(b.Max.Z, b2.Max.Z); return ret; }
public static PerspectiveCamera CreateFromBounds(AxisAlignedBox3D bounds, Viewport3D viewport, float fieldOfView, float yaw = 0.0f, float pitch = 0.0f, float zoom = 1.0f) { // Calculate initial guess at camera settings. Matrix3D transform = Matrix3D.CreateFromYawPitchRoll(yaw, pitch, 0); Vector3D cameraDirection = Vector3D.Normalize(transform.Transform(Vector3D.Forward)); PerspectiveCamera initialGuess = new PerspectiveCamera { FieldOfView = fieldOfView, NearPlaneDistance = 1.0f, FarPlaneDistance = bounds.Size.Length() * 10, Position = bounds.Center - cameraDirection * bounds.Size.Length() * 2, LookDirection = cameraDirection, UpDirection = Vector3D.Up }; Matrix3D projection = initialGuess.GetProjectionMatrix(viewport.AspectRatio); Matrix3D view = initialGuess.GetViewMatrix(); // Project bounding box corners onto screen, and calculate screen bounds. float closestZ = float.MaxValue; Box2D? screenBounds = null; Point3D[] corners = bounds.GetCorners(); foreach (Point3D corner in corners) { Point3D screenPoint = viewport.Project(corner, projection, view, Matrix3D.Identity); if (screenPoint.Z < closestZ) closestZ = screenPoint.Z; IntPoint2D intScreenPoint = new IntPoint2D((int) screenPoint.X, (int) screenPoint.Y); if (screenBounds == null) screenBounds = new Box2D(intScreenPoint, intScreenPoint); else { Box2D value = screenBounds.Value; value.Expand(intScreenPoint); screenBounds = value; } } // Now project back from screen bounds into scene, setting Z to the minimum bounding box Z value. IntPoint2D minScreen = screenBounds.Value.Min; IntPoint2D maxScreen = screenBounds.Value.Max; Point3D min = viewport.Unproject(new Point3D(minScreen.X, minScreen.Y, closestZ), projection, view, Matrix3D.Identity); Point3D max = viewport.Unproject(new Point3D(maxScreen.X, maxScreen.Y, closestZ), projection, view, Matrix3D.Identity); // Use these new values to calculate the distance the camera should be from the AABB centre. Vector3D size = Vector3D.Abs(max - min); float radius = size.Length(); float dist = radius / (2 * MathUtility.Tan(fieldOfView * viewport.AspectRatio / 2)); Point3D closestBoundsCenter = (min + (max - min) / 2); Point3D position = closestBoundsCenter - cameraDirection * dist * (1 / zoom); return new PerspectiveCamera { FieldOfView = fieldOfView, NearPlaneDistance = 1.0f, FarPlaneDistance = dist * 10, Position = position, LookDirection = cameraDirection, UpDirection = Vector3D.Up }; }
public bool Intersects(AxisAlignedBox3D box) { return(Contains(box) != ContainmentType.Disjoint); }
public AxisAlignedBox3D Transform(AxisAlignedBox3D box) { return box.Transform(Value); }