private void GetBoxToPlanePVertexNVertex(ref MyBoundingBox box, ref MyVector3 planeNormal, out MyVector3 p, out MyVector3 n) { p = box.Minimum; if (planeNormal.X >= 0) { p.X = box.Maximum.X; } if (planeNormal.Y >= 0) { p.Y = box.Maximum.Y; } if (planeNormal.Z >= 0) { p.Z = box.Maximum.Z; } n = box.Maximum; if (planeNormal.X >= 0) { n.X = box.Minimum.X; } if (planeNormal.Y >= 0) { n.Y = box.Minimum.Y; } if (planeNormal.Z >= 0) { n.Z = box.Minimum.Z; } }
/// <summary> /// Constructs a <see cref="MyBoundingSphere"/> from a given box. /// </summary> /// <param name="box">The box that will designate the extents of the sphere.</param> /// <returns>The newly constructed bounding sphere.</returns> public static MyBoundingSphere FromBox(MyBoundingBox box) { MyBoundingSphere result; FromBox(ref box, out result); return(result); }
/// <summary> /// Constructs a <see cref="MyBoundingSphere"/> from a given box. /// </summary> /// <param name="box">The box that will designate the extents of the sphere.</param> /// <param name="result">When the method completes, the newly constructed bounding sphere.</param> public static void FromBox(ref MyBoundingBox box, out MyBoundingSphere result) { MyVector3.Lerp(ref box.Minimum, ref box.Maximum, 0.5f, out result.Center); float x = box.Minimum.X - box.Maximum.X; float y = box.Minimum.Y - box.Maximum.Y; float z = box.Minimum.Z - box.Maximum.Z; float distance = (float)(Math.Sqrt((x * x) + (y * y) + (z * z))); result.Radius = distance * 0.5f; }
/// <summary> /// Determines whether there is an intersection between a <see cref="MyRay"/> and a <see cref="MyOrientedBoundingBox"/>. /// </summary> /// <param name="ray">The ray to test.</param> /// <param name="point">When the method completes, contains the point of intersection, /// or <see cref="MyVector3.Zero"/> if there was no intersection.</param> /// <returns>Whether the two objects intersected.</returns> public bool Intersects(ref MyRay ray, out MyVector3 point) { // Put ray in box space MyMatrix invTrans; MyMatrix.Invert(ref Transformation, out invTrans); MyRay bRay; MyVector3.TransformNormal(ref ray.Direction, ref invTrans, out bRay.Direction); MyVector3.TransformCoordinate(ref ray.Position, ref invTrans, out bRay.Position); //Perform a regular ray to BoundingBox check var bb = new MyBoundingBox(-Extents, Extents); var intersects = MyCollision.RayIntersectsBox(ref bRay, ref bb, out point); //Put the result intersection back to world if (intersects) MyVector3.TransformCoordinate(ref point, ref Transformation, out point); return intersects; }
/// <summary> /// Determines the intersection relationship between the frustum and a bounding box. /// </summary> /// <param name="box">The box.</param> /// <returns>Type of the containment</returns> public MyContainmentType Contains(ref MyBoundingBox box) { MyVector3 p, n; MyPlane plane; var result = MyContainmentType.Contains; for (int i = 0; i < 6; i++) { plane = GetPlane(i); GetBoxToPlanePVertexNVertex(ref box, ref plane.Normal, out p, out n); if (MyCollision.PlaneIntersectsPoint(ref plane, ref p) == MyPlaneIntersectionType.Back) { return(MyContainmentType.Disjoint); } if (MyCollision.PlaneIntersectsPoint(ref plane, ref n) == MyPlaneIntersectionType.Back) { result = MyContainmentType.Intersects; } } return(result); }
/// <summary> /// Merge an OrientedBoundingBox B into another OrientedBoundingBox A, by expanding A to contain B and keeping A orientation. /// </summary> /// <param name="A">The <see cref="MyOrientedBoundingBox"/> to merge into it.</param> /// <param name="B">The <see cref="MyOrientedBoundingBox"/> to be merged</param> /// <param name="NoMatrixScaleApplied"> /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox. /// </param> /// <remarks> /// Unlike merging axis aligned boxes, The operation is not interchangeable, because it keeps A orientation and merge B into it. /// </remarks> public static void Merge(ref MyOrientedBoundingBox A, ref MyOrientedBoundingBox B, bool NoMatrixScaleApplied = false) { MyMatrix AtoB_Matrix = GetBoxToBoxMatrix(ref A, ref B, NoMatrixScaleApplied); //Get B corners in A Space var bCorners = B.GetLocalCorners(); MyVector3.TransformCoordinate(bCorners, ref AtoB_Matrix, bCorners); //Get A local Bounding Box var A_LocalBB = new MyBoundingBox(-A.Extents, A.Extents); //Find B BoundingBox in A Space var B_LocalBB = MyBoundingBox.FromPoints(bCorners); //Merger A and B local Bounding Boxes MyBoundingBox mergedBB; MyBoundingBox.Merge(ref B_LocalBB, ref A_LocalBB, out mergedBB); //Find the new Extents and Center, Transform Center back to world var newCenter = mergedBB.Minimum + (mergedBB.Maximum - mergedBB.Minimum) / 2f; A.Extents = mergedBB.Maximum - newCenter; MyVector3.TransformCoordinate(ref newCenter, ref A.Transformation, out newCenter); A.Transformation.TranslationVector = newCenter; }
/// <summary> /// Determines whether the current objects contains a <see cref="MyBoundingBox"/>. /// </summary> /// <param name="box">The box to test.</param> /// <returns>The type of containment the two objects have.</returns> public MyContainmentType Contains(ref MyBoundingBox box) { return(MyCollision.SphereContainsBox(ref this, ref box)); }
/// <summary> /// Determines if there is an intersection between the current object and a <see cref="MyBoundingBox"/>. /// </summary> /// <param name="box">The box to test.</param> /// <returns>Whether the two objects intersected.</returns> public bool Intersects(MyBoundingBox box) { return(Intersects(ref box)); }
/// <summary> /// Determines if there is an intersection between the current object and a <see cref="MyBoundingBox"/>. /// </summary> /// <param name="box">The box to test.</param> /// <returns>Whether the two objects intersected.</returns> public bool Intersects(ref MyBoundingBox box) { return(MyCollision.BoxIntersectsSphere(ref box, ref this)); }
/// <summary> /// Get the vector shift which when added to camera position will do the effect of zoom to extents (zoom to fit) operation, /// so all the passed points will fit in the current view. /// </summary> /// <param name="boundingBox">The bounding box.</param> /// <returns>The zoom to fit vector</returns> public MyVector3 GetZoomToExtentsShiftVector(ref MyBoundingBox boundingBox) { return(GetZoomToExtentsShiftDistance(boundingBox.GetCorners()) * pNear.Normal); }
/// <summary> /// Get the distance which when added to camera position along the lookat direction will do the effect of zoom to extents (zoom to fit) operation, /// so all the passed points will fit in the current view. /// if the returned value is positive, the camera will move toward the lookat direction (ZoomIn). /// if the returned value is negative, the camera will move in the reverse direction of the lookat direction (ZoomOut). /// </summary> /// <param name="boundingBox">The bounding box.</param> /// <returns>The zoom to fit distance</returns> public float GetZoomToExtentsShiftDistance(ref MyBoundingBox boundingBox) { return(GetZoomToExtentsShiftDistance(boundingBox.GetCorners())); }
/// <summary> /// Checks whether the current BoundingFrustum intersects a BoundingBox. /// </summary> /// <param name="box">The box.</param> /// <param name="result"><c>true</c> if the current BoundingFrustum intersects a BoundingSphere.</param> public void Intersects(ref MyBoundingBox box, out bool result) { result = Contains(ref box) != MyContainmentType.Disjoint; }
/// <summary> /// Checks whether the current BoundingFrustum intersects a BoundingBox. /// </summary> /// <param name="box">The box.</param> /// <returns><c>true</c> if the current BoundingFrustum intersects a BoundingSphere.</returns> public bool Intersects(ref MyBoundingBox box) { return(Contains(ref box) != MyContainmentType.Disjoint); }
/// <summary> /// Determines the intersection relationship between the frustum and a bounding box. /// </summary> /// <param name="box">The box.</param> /// <param name="result">Type of the containment.</param> public void Contains(ref MyBoundingBox box, out MyContainmentType result) { result = Contains(ref box); }
/// <summary> /// Check the intersection between an <see cref="MyOrientedBoundingBox"/> and <see cref="MyBoundingBox"/> /// </summary> /// <param name="box">The BoundingBox to test.</param> /// <returns>The type of containment the two objects have.</returns> /// <remarks> /// For accuracy, The transformation matrix for the <see cref="MyOrientedBoundingBox"/> must not have any scaling applied to it. /// Anyway, scaling using Scale method will keep this method accurate. /// </remarks> public MyContainmentType Contains(ref MyBoundingBox box) { var cornersCheck = Contains(box.GetCorners()); if (cornersCheck != MyContainmentType.Disjoint) return cornersCheck; var boxCenter = box.Minimum + (box.Maximum - box.Minimum) / 2f; var boxExtents = box.Maximum - boxCenter; var SizeA = Extents; var SizeB = boxExtents; var RotA = GetRows(ref Transformation); float ExtentA, ExtentB, Separation; int i, k; MyMatrix R; // Rotation from B to A MyMatrix.Invert(ref Transformation, out R); var AR = new MyMatrix(); // absolute values of R matrix, to use with box extents for (i = 0; i < 3; i++) for (k = 0; k < 3; k++) { AR[i, k] = Math.Abs(R[i, k]); } // Vector separating the centers of Box B and of Box A var vSepWS = boxCenter - Center; // Rotated into Box A's coordinates var vSepA = new MyVector3(MyVector3.Dot(vSepWS, RotA[0]), MyVector3.Dot(vSepWS, RotA[1]), MyVector3.Dot(vSepWS, RotA[2])); // Test if any of A's basis vectors separate the box for (i = 0; i < 3; i++) { ExtentA = SizeA[i]; ExtentB = MyVector3.Dot(SizeB, new MyVector3(AR[i, 0], AR[i, 1], AR[i, 2])); Separation = Math.Abs(vSepA[i]); if (Separation > ExtentA + ExtentB) return MyContainmentType.Disjoint; } // Test if any of B's basis vectors separate the box for (k = 0; k < 3; k++) { ExtentA = MyVector3.Dot(SizeA, new MyVector3(AR[0, k], AR[1, k], AR[2, k])); ExtentB = SizeB[k]; Separation = Math.Abs(MyVector3.Dot(vSepA, new MyVector3(R[0, k], R[1, k], R[2, k]))); if (Separation > ExtentA + ExtentB) return MyContainmentType.Disjoint; } // Now test Cross Products of each basis vector combination ( A[i], B[k] ) for (i = 0; i < 3; i++) for (k = 0; k < 3; k++) { int i1 = (i + 1) % 3, i2 = (i + 2) % 3; int k1 = (k + 1) % 3, k2 = (k + 2) % 3; ExtentA = SizeA[i1] * AR[i2, k] + SizeA[i2] * AR[i1, k]; ExtentB = SizeB[k1] * AR[i, k2] + SizeB[k2] * AR[i, k1]; Separation = Math.Abs(vSepA[i2] * R[i1, k] - vSepA[i1] * R[i2, k]); if (Separation > ExtentA + ExtentB) return MyContainmentType.Disjoint; } // No separating axis found, the boxes overlap return MyContainmentType.Intersects; }
/// <summary> /// Get the axis-aligned <see cref="MyBoundingBox"/> which contains all <see cref="MyOrientedBoundingBox"/> corners. /// </summary> /// <returns>The axis-aligned BoundingBox of this OrientedBoundingBox.</returns> public MyBoundingBox GetBoundingBox() { return MyBoundingBox.FromPoints(GetCorners()); }
/// <summary> /// Determines if there is an intersection between the current object and a <see cref="MyBoundingBox"/>. /// </summary> /// <param name="box">The box to test.</param> /// <returns>Whether the two objects intersected.</returns> public MyPlaneIntersectionType Intersects(ref MyBoundingBox box) { return(MyCollision.PlaneIntersectsBox(ref this, ref box)); }
/// <summary> /// Determines if there is an intersection between the current object and a <see cref="MyBoundingBox"/>. /// </summary> /// <param name="box">The box to test.</param> /// <param name="point">When the method completes, contains the point of intersection, /// or <see cref="MyVector3.Zero"/> if there was no intersection.</param> /// <returns>Whether the two objects intersected.</returns> public bool Intersects(ref MyBoundingBox box, out MyVector3 point) { return(MyCollision.RayIntersectsBox(ref this, ref box, out point)); }
/// <summary> /// Determines if there is an intersection between the current object and a <see cref="MyBoundingBox"/>. /// </summary> /// <param name="box">The box to test.</param> /// <param name="distance">When the method completes, contains the distance of the intersection, /// or 0 if there was no intersection.</param> /// <returns>Whether the two objects intersected.</returns> public bool Intersects(ref MyBoundingBox box, out float distance) { return(MyCollision.RayIntersectsBox(ref this, ref box, out distance)); }
/// <summary> /// Determines the intersection relationship between the frustum and a bounding box. /// </summary> /// <param name="box">The box.</param> /// <returns>Type of the containment</returns> public MyContainmentType Contains(MyBoundingBox box) { return(Contains(ref box)); }
/// <summary> /// Creates an <see cref="MyOrientedBoundingBox"/> from a BoundingBox. /// </summary> /// <param name="bb">The BoundingBox to create from.</param> /// <remarks> /// Initially, the OBB is axis-aligned box, but it can be rotated and transformed later. /// </remarks> public MyOrientedBoundingBox(MyBoundingBox bb) { var Center = bb.Minimum + (bb.Maximum - bb.Minimum) / 2f; Extents = bb.Maximum - Center; Transformation = MyMatrix.Translation(Center); }