Example #1
0
            private static void GetIntersectingFace(MatrixD matrix, Vector3D hitPosLocal, ICollection <int> impactFaces)
            {
                var boxMax = matrix.Backward + matrix.Right + matrix.Up;
                var boxMin = -boxMax;
                var box    = new BoundingBoxD(boxMin, boxMax);

                var   maxWidth = box.Max.LengthSquared();
                var   testLine = new LineD(Vector3D.Zero, Vector3D.Normalize(hitPosLocal) * maxWidth); //This is to ensure we intersect the box
                LineD testIntersection;

                box.Intersect(ref testLine, out testIntersection);

                var intersection = testIntersection.To;

                var projFront = VectorProjection(intersection, matrix.Forward);

                if (projFront.LengthSquared() >= 0.65 * matrix.Forward.LengthSquared()) //if within the side thickness
                {
                    impactFaces.Add(intersection.Dot(matrix.Forward) > 0 ? 5 : 4);
                }

                var projLeft = VectorProjection(intersection, matrix.Left);

                if (projLeft.LengthSquared() >= 0.65 * matrix.Left.LengthSquared()) //if within the side thickness
                {
                    impactFaces.Add(intersection.Dot(matrix.Left) > 0 ? 1 : 0);
                }

                var projUp = VectorProjection(intersection, matrix.Up);

                if (projUp.LengthSquared() >= 0.65 * matrix.Up.LengthSquared()) //if within the side thickness
                {
                    impactFaces.Add(intersection.Dot(matrix.Up) > 0 ? 2 : 3);
                }
            }
Example #2
0
        internal static bool FaceIntersected(MatrixD shieldShape, MatrixD gridLocalMatrix, Vector3D worldPos, Vector3I faces)
        {
            var referenceLocalPosition = gridLocalMatrix.Translation;
            var worldDirection         = worldPos - referenceLocalPosition;
            var localPosition          = Vector3D.TransformNormal(worldDirection, MatrixD.Transpose(gridLocalMatrix));
            var impactTransNorm        = localPosition - shieldShape.Translation;

            var boxMax = shieldShape.Backward + shieldShape.Right + shieldShape.Up;
            var boxMin = -boxMax;
            var box    = new BoundingBoxD(boxMin, boxMax);

            var      maxWidth = box.Max.LengthSquared();
            Vector3D norm;

            Vector3D.Normalize(ref impactTransNorm, out norm);
            var   testLine = new LineD(Vector3D.Zero, norm * maxWidth); //This is to ensure we intersect the box
            LineD testIntersection;

            box.Intersect(ref testLine, out testIntersection);

            var intersection = testIntersection.To;

            var projFront = VectorProjection(intersection, shieldShape.Forward);

            if (projFront.LengthSquared() >= 0.8 * shieldShape.Forward.LengthSquared()) //if within the side thickness
            {
                var face = intersection.Dot(shieldShape.Forward) > 0 ? 5 : 4;
                Log.Line($"FaceIntersected (4-5): {face} - {faces}");
                if (faces.Z == 2 || faces.Z != 0 && face == 5 && faces.Z == -1 || face == 4 && faces.Z == 1)
                {
                    return(true);
                }
            }

            var projLeft = VectorProjection(intersection, shieldShape.Left);

            if (projLeft.LengthSquared() >= 0.8 * shieldShape.Left.LengthSquared()) //if within the side thickness
            {
                var face = intersection.Dot(shieldShape.Left) > 0 ? 1 : 0;
                Log.Line($"FaceIntersected (1-0): {face}  - {faces}");
                if (faces.X == 2 || faces.X != 0 && face == 1 && faces.X == -1 || face == 0 && faces.X == 1)
                {
                    return(true);
                }
            }

            var projUp = VectorProjection(intersection, shieldShape.Up);

            if (projUp.LengthSquared() >= 0.8 * shieldShape.Up.LengthSquared()) //if within the side thickness
            {
                var face = intersection.Dot(shieldShape.Up) > 0 ? 2 : 3;
                Log.Line($"FaceIntersected(2-3): {face} - {faces}");
                if (faces.Y == 2 || faces.Y != 0 && face == 2 && faces.Y == -1 || face == 3 && faces.Y == 1)
                {
                    return(true);
                }
            }

            return(false);
        }
Example #3
0
        public override bool IsOverlapOverThreshold(BoundingBoxD worldAabb, float thresholdPercentage)
        {
            //Debug.Assert(
            //    worldAabb.Size.X > MyVoxelConstants.VOXEL_SIZE_IN_METRES &&
            //    worldAabb.Size.Y > MyVoxelConstants.VOXEL_SIZE_IN_METRES &&
            //    worldAabb.Size.Z > MyVoxelConstants.VOXEL_SIZE_IN_METRES,
            //    "One of the sides of queried AABB is too small compared to voxel size. Results will be unreliable.");

            Vector3I minCorner, maxCorner;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Min, out minCorner);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Max, out maxCorner);

            minCorner += StorageMin;
            maxCorner += StorageMin;

            Storage.ClampVoxelCoord(ref minCorner);
            Storage.ClampVoxelCoord(ref maxCorner);
            m_storageCache.Resize(minCorner, maxCorner);
            Storage.ReadRange(m_storageCache, MyStorageDataTypeFlags.Content, 0, ref minCorner, ref maxCorner);
            BoundingBoxD voxelBox;

            //MyRenderProxy.DebugDrawAABB(worldAabb, Color.White, 1f, 1f, true);

            var    invFullVoxel         = 1.0 / (double)MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT;
            var    voxelVolume          = 1.0 / (double)MyVoxelConstants.VOXEL_VOLUME_IN_METERS;
            double overlapContentVolume = 0.0;

            var queryVolume = worldAabb.Volume;

            //using (var batch = MyRenderProxy.DebugDrawBatchAABB(Matrix.Identity, new Color(Color.Green, 0.1f), true, true))
            {
                Vector3I coord, cache;
                for (coord.Z = minCorner.Z, cache.Z = 0; coord.Z <= maxCorner.Z; coord.Z++, cache.Z++)
                {
                    for (coord.Y = minCorner.Y, cache.Y = 0; coord.Y <= maxCorner.Y; coord.Y++, cache.Y++)
                    {
                        for (coord.X = minCorner.X, cache.X = 0; coord.X <= maxCorner.X; coord.X++, cache.X++)
                        {
                            MyVoxelCoordSystems.VoxelCoordToWorldAABB(PositionLeftBottomCorner, ref coord, out voxelBox);
                            if (worldAabb.Intersects(voxelBox))
                            {
                                var contentVolume = m_storageCache.Content(ref cache) * invFullVoxel * voxelVolume;
                                var overlapVolume = worldAabb.Intersect(voxelBox).Volume;
                                overlapContentVolume += contentVolume * overlapVolume;

                                //batch.Add(ref voxelBox);
                            }
                        }
                    }
                }
            }

            var overlapVolumePercentage = overlapContentVolume / queryVolume;

            //MyRenderProxy.DebugDrawText3D(worldAabb.Center, overlapVolumePercentage.ToString("0.000"), Color.White, 1f, false);
            return(overlapVolumePercentage >= thresholdPercentage);
        }
        public void SubtractBB(ref BoundingBoxD bb)
        {
            if (m_bBox.Intersects(ref bb) == false)
            {
                return;
            }

            BoundingBoxD intersected = m_bBox.Intersect(bb);

            m_sampler.Subtract(ref m_bBox, ref intersected);
        }
Example #5
0
            private void GetIntersectingFace(MatrixD matrix, Vector3D hitPosLocal, ICollection <Session.ShieldSides> impactFaces)
            {
                if (Shield?.ShellActive == null)
                {
                    return;
                }

                var boxMax = matrix.Backward + matrix.Right + matrix.Up;
                var boxMin = -boxMax;
                var box    = new BoundingBoxD(boxMin, boxMax);

                var   maxWidth = box.Max.LengthSquared();
                var   testLine = new LineD(Vector3D.Zero, Vector3D.Normalize(hitPosLocal) * maxWidth); //This is to ensure we intersect the box
                LineD testIntersection;

                box.Intersect(ref testLine, out testIntersection);

                var intersection = testIntersection.To;

                var projFront = VectorProjection(intersection, matrix.Forward);

                if (projFront.LengthSquared() >= 0.65 * matrix.Forward.LengthSquared()) //if within the side thickness
                {
                    var dot = intersection.Dot(matrix.Forward);
                    //var face = intersection.Dot(matrix.Forward) > 0 ? Shield.RealSideStates[(Session.ShieldSides)0].Side : Shield.RealSideStates[(Session.ShieldSides)1].Side;
                    var face = dot > 0 ? Session.ShieldSides.Forward : Session.ShieldSides.Backward;
                    impactFaces.Add(face);
                }

                var projLeft = VectorProjection(intersection, matrix.Left);

                if (projLeft.LengthSquared() >= 0.65 * matrix.Left.LengthSquared()) //if within the side thickness
                {
                    var dot = intersection.Dot(matrix.Left);
                    //var face = intersection.Dot(matrix.Left) > 0 ? Shield.RealSideStates[(Session.ShieldSides)3].Side : Shield.RealSideStates[(Session.ShieldSides)2].Side;
                    var face = dot > 0 ? Session.ShieldSides.Left : Session.ShieldSides.Right;
                    impactFaces.Add(face);
                }

                var projUp = VectorProjection(intersection, matrix.Up);

                if (projUp.LengthSquared() >= 0.65 * matrix.Up.LengthSquared()) //if within the side thickness
                {
                    var dot = intersection.Dot(matrix.Up);
                    //var face = intersection.Dot(matrix.Up) > 0 ? Shield.RealSideStates[Session.ShieldSides.Up].Side : Shield.RealSideStates[Session.ShieldSides.Down].Side;
                    var face = dot > 0 ? Session.ShieldSides.Up : Session.ShieldSides.Down;
                    impactFaces.Add(face);
                }
            }
Example #6
0
        public static double GetIntersectingSurfaceArea(MatrixD matrix, Vector3D hitPosLocal)
        {
            var surfaceArea = -1d;

            var boxMax = matrix.Backward + matrix.Right + matrix.Up;
            var boxMin = -boxMax;
            var box    = new BoundingBoxD(boxMin, boxMax);

            var   maxWidth = box.Max.LengthSquared();
            var   testLine = new LineD(Vector3D.Zero, Vector3D.Normalize(hitPosLocal) * maxWidth);
            LineD testIntersection;

            box.Intersect(ref testLine, out testIntersection);

            var intersection = testIntersection.To;

            var epsilon   = 1e-6;
            var projFront = VectorProjection(intersection, matrix.Forward);

            if (Math.Abs(projFront.LengthSquared() - matrix.Forward.LengthSquared()) < epsilon)
            {
                var a = Vector3D.Distance(matrix.Left, matrix.Right);
                var b = Vector3D.Distance(matrix.Up, matrix.Down);
                surfaceArea = a * b;
            }

            var projLeft = VectorProjection(intersection, matrix.Left);

            if (Math.Abs(projLeft.LengthSquared() - matrix.Left.LengthSquared()) < epsilon)
            {
                var a = Vector3D.Distance(matrix.Forward, matrix.Backward);
                var b = Vector3D.Distance(matrix.Up, matrix.Down);
                surfaceArea = a * b;
            }

            var projUp = VectorProjection(intersection, matrix.Up);

            if (Math.Abs(projUp.LengthSquared() - matrix.Up.LengthSquared()) < epsilon)
            {
                var a = Vector3D.Distance(matrix.Forward, matrix.Backward);
                var b = Vector3D.Distance(matrix.Left, matrix.Right);
                surfaceArea = a * b;
            }
            return(surfaceArea);
        }
Example #7
0
        public float GetVoxelContentInBoundingBox_Obsolete(BoundingBoxD worldAabb, out float cellCount)
        {
            MyPrecalcComponent.AssertUpdateThread();

            cellCount = 0;
            float result = 0;

            Vector3I minCorner, maxCorner;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Min, out minCorner);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Max, out maxCorner);

            minCorner += StorageMin;
            maxCorner += StorageMin;

            Storage.ClampVoxelCoord(ref minCorner);
            Storage.ClampVoxelCoord(ref maxCorner);
            m_tempStorage.Resize(minCorner, maxCorner);
            Storage.ReadRange(m_tempStorage, MyStorageDataTypeFlags.Content, 0, ref minCorner, ref maxCorner);

            BoundingBoxD voxelBox;
            Vector3I     coord, cache;

            for (coord.Z = minCorner.Z, cache.Z = 0; coord.Z <= maxCorner.Z; coord.Z++, cache.Z++)
            {
                for (coord.Y = minCorner.Y, cache.Y = 0; coord.Y <= maxCorner.Y; coord.Y++, cache.Y++)
                {
                    for (coord.X = minCorner.X, cache.X = 0; coord.X <= maxCorner.X; coord.X++, cache.X++)
                    {
                        MyVoxelCoordSystems.VoxelCoordToWorldAABB(PositionLeftBottomCorner - StorageMin * MyVoxelConstants.VOXEL_SIZE_IN_METRES, ref coord, out voxelBox);
                        if (worldAabb.Intersects(voxelBox))
                        {
                            float content        = m_tempStorage.Content(ref cache) / MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT;
                            float containPercent = (float)(worldAabb.Intersect(voxelBox).Volume / MyVoxelConstants.VOXEL_VOLUME_IN_METERS);
                            result    += content * containPercent;
                            cellCount += containPercent;
                        }
                    }
                }
            }
            return(result);
        }
Example #8
0
            private void UpdateSlimBlock()
            {
                var grid = _root as IMyCubeGrid;

                _block = grid?.FirstBlock(_hit.Position,
                                          _hit.Position + _maxPrediction * _ray.Direction);
                if (_block == null)
                {
                    return;
                }

                Vector3 halfExtents;

                _block.ComputeScaledHalfExtents(out halfExtents);
                Vector3D center;

                _block.ComputeScaledCenter(out center);
                var   bb = new BoundingBoxD(center - halfExtents, center + halfExtents);
                LineD l;
                var   m = grid.WorldMatrixNormalizedInv;

                l.From      = Vector3D.Transform(_ray.From, ref m);
                l.To        = Vector3D.Transform(_ray.To, ref m);
                l.Direction = Vector3D.TransformNormal(_ray.Direction, ref m);
                l.Length    = _ray.Length;
                double t1, t2;

                if (bb.Intersect(ref l, out t1, out t2))
                {
                    _hitPosition = _ray.From + _ray.Direction * t1;
                }
                else
                {
                    _hitPosition = _ray.From + (Vector3.Transform(center, grid.WorldMatrix) - _ray.From).Dot(_ray.Direction) * _ray.Direction;
                }
            }
Example #9
0
        public float GetVoxelContentInBoundingBox_Obsolete(BoundingBoxD worldAabb, out float cellCount)
        {
            MyPrecalcComponent.AssertUpdateThread();

            cellCount = 0;
            float result = 0;

            Vector3I minCorner, maxCorner;
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Min, out minCorner);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Max, out maxCorner);

            minCorner += StorageMin;
            maxCorner += StorageMin;

            Storage.ClampVoxelCoord(ref minCorner);
            Storage.ClampVoxelCoord(ref maxCorner);
            m_storageCache.Resize(minCorner, maxCorner);
            Storage.ReadRange(m_storageCache, MyStorageDataTypeFlags.Content, 0, ref minCorner, ref maxCorner);
            BoundingBoxD voxelBox;

            Vector3I coord, cache;
            for (coord.Z = minCorner.Z, cache.Z = 0; coord.Z <= maxCorner.Z; coord.Z++, cache.Z++)
            {
                for (coord.Y = minCorner.Y, cache.Y = 0; coord.Y <= maxCorner.Y; coord.Y++, cache.Y++)
                {
                    for (coord.X = minCorner.X, cache.X = 0; coord.X <= maxCorner.X; coord.X++, cache.X++)
                    {
                        MyVoxelCoordSystems.VoxelCoordToWorldAABB(PositionLeftBottomCorner - StorageMin * MyVoxelConstants.VOXEL_SIZE_IN_METRES, ref coord, out voxelBox);
                        if (worldAabb.Intersects(voxelBox))
                        {
                            float content = m_storageCache.Content(ref cache) / MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT;
                            float containPercent = (float)(worldAabb.Intersect(voxelBox).Volume / MyVoxelConstants.VOXEL_VOLUME_IN_METERS);
                            result += content * containPercent;
                            cellCount += containPercent;
                        }
                    }
                }
            }
            return result;
        }
        /// <summary>
        /// Returns true if the given small block connects to large one.
        /// </summary>
        /// <param name="smallBlock">small block</param>
        /// <param name="smallBlockWorldAabb">small block world AABB</param>
        /// <param name="largeBlock">large block</param>
        /// <param name="largeBlockWorldAabb">large block wotld AABB</param>
        /// <returns>true when connected</returns>
        private bool SmallBlockConnectsToLarge(MySlimBlock smallBlock, ref BoundingBoxD smallBlockWorldAabb, MySlimBlock largeBlock, ref BoundingBoxD largeBlockWorldAabb)
        {
            Debug.Assert(smallBlock.BlockDefinition.CubeSize == MyCubeSize.Small);
            Debug.Assert(largeBlock.BlockDefinition.CubeSize == MyCubeSize.Large);
            Debug.Assert(!(smallBlock.FatBlock is MyCompoundCubeBlock));
            Debug.Assert(!(largeBlock.FatBlock is MyCompoundCubeBlock));

            BoundingBoxD smallBlockWorldAabbReduced = smallBlockWorldAabb;

            smallBlockWorldAabbReduced.Inflate(-smallBlock.CubeGrid.GridSize / 4);

            // Small block aabb penetrates large block aabb (large timbers).
            bool penetratesAabbs = largeBlockWorldAabb.Contains(smallBlockWorldAabbReduced) == ContainmentType.Intersects;

            if (!penetratesAabbs)
            {
                Vector3D centerToCenter = smallBlockWorldAabb.Center - largeBlockWorldAabb.Center;
                Vector3I addDir         = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(centerToCenter));
                // Check small grid mount points
                Quaternion smallBlockRotation;
                smallBlock.Orientation.GetQuaternion(out smallBlockRotation);
                smallBlockRotation = Quaternion.CreateFromRotationMatrix(smallBlock.CubeGrid.WorldMatrix) * smallBlockRotation;
                if (!MyCubeGrid.CheckConnectivitySmallBlockToLargeGrid(largeBlock.CubeGrid, smallBlock.BlockDefinition, ref smallBlockRotation, ref addDir))
                {
                    return(false);
                }
            }

            BoundingBoxD smallBlockWorldAabbInflated = smallBlockWorldAabb;

            smallBlockWorldAabbInflated.Inflate(2 * smallBlock.CubeGrid.GridSize / 3);

            // Trim small block aabb with large block aabb.
            BoundingBoxD intersectedBox       = smallBlockWorldAabbInflated.Intersect(largeBlockWorldAabb);
            Vector3D     intersectedBoxCenter = intersectedBox.Center;
            HkShape      shape = new HkBoxShape((Vector3)intersectedBox.HalfExtents);

            Quaternion largeRotation;

            largeBlock.Orientation.GetQuaternion(out largeRotation);
            largeRotation = Quaternion.CreateFromRotationMatrix(largeBlock.CubeGrid.WorldMatrix) * largeRotation;
            Vector3D largeTranslation;

            largeBlock.ComputeWorldCenter(out largeTranslation);

            bool result = false;

            try
            {
                if (largeBlock.FatBlock != null)
                {
                    MyModel model = largeBlock.FatBlock.Model;
                    if (model != null)
                    {
                        HkShape[] shapes = model.HavokCollisionShapes;
                        if (shapes == null || shapes.Length == 0)
                        {
                            return(false);
                        }

                        for (int i = 0; i < shapes.Length; ++i)
                        {
                            result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapes[i], ref largeTranslation, ref largeRotation);
                            if (result)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        HkShape shapeLarge = new HkBoxShape(largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize / 2);

                        result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapeLarge, ref largeTranslation, ref largeRotation);

                        shapeLarge.RemoveReference();
                    }
                }
                else
                {
                    HkShape shapeLarge = new HkBoxShape(largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize / 2);

                    result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapeLarge, ref largeTranslation, ref largeRotation);

                    shapeLarge.RemoveReference();
                }
            }
            finally
            {
                shape.RemoveReference();
            }

            return(result);
        }
Example #11
0
        public override bool IsOverlapOverThreshold(BoundingBoxD worldAabb, float thresholdPercentage)
        {
            //Debug.Assert(
            //    worldAabb.Size.X > MyVoxelConstants.VOXEL_SIZE_IN_METRES &&
            //    worldAabb.Size.Y > MyVoxelConstants.VOXEL_SIZE_IN_METRES &&
            //    worldAabb.Size.Z > MyVoxelConstants.VOXEL_SIZE_IN_METRES,
            //    "One of the sides of queried AABB is too small compared to voxel size. Results will be unreliable.");

            Vector3I minCorner, maxCorner;
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Min, out minCorner);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Max, out maxCorner);

            minCorner += StorageMin;
            maxCorner += StorageMin;

            Storage.ClampVoxelCoord(ref minCorner);
            Storage.ClampVoxelCoord(ref maxCorner);
            m_storageCache.Resize(minCorner, maxCorner);
            Storage.ReadRange(m_storageCache, MyStorageDataTypeFlags.Content, 0, ref minCorner, ref maxCorner);
            BoundingBoxD voxelBox;

            //MyRenderProxy.DebugDrawAABB(worldAabb, Color.White, 1f, 1f, true);

            var invFullVoxel = 1.0 / (double)MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT;
            var voxelVolume = 1.0 / (double)MyVoxelConstants.VOXEL_VOLUME_IN_METERS;
            double overlapContentVolume = 0.0;

            var queryVolume = worldAabb.Volume;

            //using (var batch = MyRenderProxy.DebugDrawBatchAABB(Matrix.Identity, new Color(Color.Green, 0.1f), true, true))
            {
                Vector3I coord, cache;
                for (coord.Z = minCorner.Z, cache.Z = 0; coord.Z <= maxCorner.Z; coord.Z++, cache.Z++)
                {
                    for (coord.Y = minCorner.Y, cache.Y = 0; coord.Y <= maxCorner.Y; coord.Y++, cache.Y++)
                    {
                        for (coord.X = minCorner.X, cache.X = 0; coord.X <= maxCorner.X; coord.X++, cache.X++)
                        {
                            MyVoxelCoordSystems.VoxelCoordToWorldAABB(PositionLeftBottomCorner, ref coord, out voxelBox);
                            if (worldAabb.Intersects(voxelBox))
                            {
                                var contentVolume = m_storageCache.Content(ref cache) * invFullVoxel * voxelVolume;
                                var overlapVolume = worldAabb.Intersect(voxelBox).Volume;
                                overlapContentVolume += contentVolume * overlapVolume;

                                //batch.Add(ref voxelBox);
                            }
                        }
                    }
                }
            }

            var overlapVolumePercentage = overlapContentVolume / queryVolume;
            //MyRenderProxy.DebugDrawText3D(worldAabb.Center, overlapVolumePercentage.ToString("0.000"), Color.White, 1f, false);
            return overlapVolumePercentage >= thresholdPercentage;
        }
        private void SplitArea(BoundingBoxD box1, BoundingBoxD box2, List<BoundingBoxD> output)
        {
            var intersectValue = box1.Intersect(box2);

            double x1 = Math.Min(intersectValue.Min.X, box2.Min.X);
            double x2 = intersectValue.Min.X;
            double x3 = intersectValue.Max.X;
            double x4 = Math.Max(intersectValue.Max.X, box2.Max.X);

            double z1 = Math.Min(intersectValue.Min.Z, box2.Min.Z);
            double z2 = intersectValue.Min.Z;
            double z3 = intersectValue.Max.Z;
            double z4 = Math.Max(intersectValue.Max.Z, box2.Max.Z);

            bool sameXMin = x1 == x2;
            bool sameXMax = x3 == x4;
            bool sameZMin = z1 == z2;
            bool sameZMax = z3 == z4;

            double minY = DEBUG_BOX_Y_MIN_POS;
            double maxY = DEBUG_BOX_Y_MAX_POS;

            if (sameXMin && sameXMax)
            {
                if (sameZMin && !sameZMax)
                {
                    output.Add(new BoundingBoxD(new Vector3D(x1, minY, z3), new Vector3D(x4, maxY, z4)));
                }
                else if (!sameZMin && sameZMax)
                {
                    output.Add(new BoundingBoxD(new Vector3D(x1, minY, z1), new Vector3D(x4, maxY, z2)));
                }
                else
                {
                    output.Add(new BoundingBoxD(new Vector3D(x1, minY, z1), new Vector3D(x4, maxY, z2)));
                    output.Add(new BoundingBoxD(new Vector3D(x1, minY, z3), new Vector3D(x4, maxY, z4)));
                }
            }
            else if (sameZMin && sameZMax)
            {
                if (sameXMin && !sameXMax)
                {
                    output.Add(new BoundingBoxD(new Vector3D(x3, minY, z1), new Vector3D(x4, maxY, z4)));
                }
                else if (!sameXMin && sameXMax)
                {
                    output.Add(new BoundingBoxD(new Vector3D(x1, minY, z1), new Vector3D(x2, maxY, z2)));
                }
                else
                {
                    output.Add(new BoundingBoxD(new Vector3D(x1, minY, z1), new Vector3D(x2, maxY, z4)));
                    output.Add(new BoundingBoxD(new Vector3D(x3, minY, z1), new Vector3D(x4, maxY, z4)));
                }
            }
            else
            {
                if (sameXMin)
                {
                    if (sameZMin)
                    {
                        output.Add(new BoundingBoxD(new Vector3D(x3, minY, z1), new Vector3D(x4, maxY, z3)));
                        output.Add(new BoundingBoxD(new Vector3D(x1, minY, z3), new Vector3D(x4, maxY, z4)));
                    }
                    else if (sameZMax)
                    {
                        output.Add(new BoundingBoxD(new Vector3D(x1, minY, z1), new Vector3D(x4, maxY, z2)));
                        output.Add(new BoundingBoxD(new Vector3D(x3, minY, z2), new Vector3D(x4, maxY, z4)));
                    }
                    else
                    {
                        output.Add(new BoundingBoxD(new Vector3D(x1, minY, z1), new Vector3D(x4, maxY, z2)));
                        output.Add(new BoundingBoxD(new Vector3D(x3, minY, z2), new Vector3D(x4, maxY, z3)));
                        output.Add(new BoundingBoxD(new Vector3D(x1, minY, z3), new Vector3D(x4, maxY, z4)));
                    }
                }
                else if (sameXMax)
                {
                    if (sameZMin)
                    {
                        output.Add(new BoundingBoxD(new Vector3D(x1, minY, z1), new Vector3D(x2, maxY, z3)));
                        output.Add(new BoundingBoxD(new Vector3D(x1, minY, z3), new Vector3D(x4, maxY, z4)));
                    }
                    else if (sameZMax)
                    {
                        output.Add(new BoundingBoxD(new Vector3D(x1, minY, z1), new Vector3D(x4, maxY, z2)));
                        output.Add(new BoundingBoxD(new Vector3D(x1, minY, z2), new Vector3D(x4, maxY, z4)));
                    }
                    else
                    {
                        output.Add(new BoundingBoxD(new Vector3D(x1, minY, z1), new Vector3D(x4, maxY, z2)));
                        output.Add(new BoundingBoxD(new Vector3D(x1, minY, z2), new Vector3D(x3, maxY, z3)));
                        output.Add(new BoundingBoxD(new Vector3D(x1, minY, z3), new Vector3D(x4, maxY, z4)));
                    }
                }
                else if (sameZMin)
                {
                    output.Add(new BoundingBoxD(new Vector3D(x1, minY, z1), new Vector3D(x2, maxY, z4)));
                    output.Add(new BoundingBoxD(new Vector3D(x2, minY, z3), new Vector3D(x3, maxY, z4)));
                    output.Add(new BoundingBoxD(new Vector3D(x3, minY, z1), new Vector3D(x4, maxY, z4)));
                }
                else if (sameZMax)
                {
                    output.Add(new BoundingBoxD(new Vector3D(x1, minY, z1), new Vector3D(x2, maxY, z4)));
                    output.Add(new BoundingBoxD(new Vector3D(x2, minY, z1), new Vector3D(x3, maxY, z3)));
                    output.Add(new BoundingBoxD(new Vector3D(x3, minY, z1), new Vector3D(x4, maxY, z4)));
                }
                else
                {
                    MyDebug.AssertDebug(false);
                }
            }
        }
Example #13
0
        private bool SmallBlockConnectsToLarge(MySlimBlock smallBlock, ref BoundingBoxD smallBlockWorldAabb, MySlimBlock largeBlock, ref BoundingBoxD largeBlockWorldAabb)
        {
            Quaternion   quaternion;
            Vector3D     vectord2;
            BoundingBoxD box = smallBlockWorldAabb;

            box.Inflate((double)(-smallBlock.CubeGrid.GridSize / 4f));
            if (!largeBlockWorldAabb.Intersects(box))
            {
                Quaternion quaternion2;
                Vector3I   addNormal = this.GetSmallBlockAddDirection(ref smallBlockWorldAabb, ref box, ref largeBlockWorldAabb);
                smallBlock.Orientation.GetQuaternion(out quaternion2);
                quaternion2 = Quaternion.CreateFromRotationMatrix(smallBlock.CubeGrid.WorldMatrix) * quaternion2;
                if (!MyCubeGrid.CheckConnectivitySmallBlockToLargeGrid(largeBlock.CubeGrid, smallBlock.BlockDefinition, ref quaternion2, ref addNormal))
                {
                    return(false);
                }
            }
            BoundingBoxD xd2 = smallBlockWorldAabb;

            xd2.Inflate((double)((2f * smallBlock.CubeGrid.GridSize) / 3f));
            BoundingBoxD xd3    = xd2.Intersect(largeBlockWorldAabb);
            Vector3D     center = xd3.Center;
            HkShape      shape  = (HkShape) new HkBoxShape((Vector3)xd3.HalfExtents);

            largeBlock.Orientation.GetQuaternion(out quaternion);
            quaternion = Quaternion.CreateFromRotationMatrix(largeBlock.CubeGrid.WorldMatrix) * quaternion;
            largeBlock.ComputeWorldCenter(out vectord2);
            bool flag = false;

            try
            {
                if (largeBlock.FatBlock == null)
                {
                    HkShape shape3 = (HkShape) new HkBoxShape((largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize) / 2f);
                    flag = MyPhysics.IsPenetratingShapeShape(shape, ref center, ref Quaternion.Identity, shape3, ref vectord2, ref quaternion);
                    shape3.RemoveReference();
                }
                else
                {
                    MyModel model = largeBlock.FatBlock.Model;
                    if ((model == null) || (model.HavokCollisionShapes == null))
                    {
                        HkShape shape2 = (HkShape) new HkBoxShape((largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize) / 2f);
                        flag = MyPhysics.IsPenetratingShapeShape(shape, ref center, ref Quaternion.Identity, shape2, ref vectord2, ref quaternion);
                        shape2.RemoveReference();
                    }
                    else
                    {
                        HkShape[] havokCollisionShapes = model.HavokCollisionShapes;
                        for (int i = 0; i < havokCollisionShapes.Length; i++)
                        {
                            flag = MyPhysics.IsPenetratingShapeShape(shape, ref center, ref Quaternion.Identity, havokCollisionShapes[i], ref vectord2, ref quaternion);
                            if (flag)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            finally
            {
                shape.RemoveReference();
            }
            return(flag);
        }
        // To help debug even when using stackalloc
        public unsafe bool IntersectInternalWStack(ref LineD line, MyCellCoord * stack, int stackSize) {
#else

            int stackSize = MySparseOctree.EstimateStackSize(m_treeHeight);
            MyCellCoord* stack = stackalloc MyCellCoord[stackSize];
#endif
            var finalB = BoundingBoxD.CreateInvalid();

            LineD result;
            result.From = line.To;
            result.To = line.From;

            MyCellCoord data = new MyCellCoord(m_treeHeight + LeafLodCount, ref Vector3I.Zero);
            int stackIdx = 0;
            stack[stackIdx++] = data;
            MyCellCoord cell = new MyCellCoord();

            BoundingBoxI bb = new BoundingBoxI(new Vector3I(Vector3.Min(line.From, line.To)), new Vector3I(Vector3.Ceiling(Vector3.Max(line.From, line.To))));

            double startOfft, endOfft;

            while (stackIdx > 0)
            {
                Debug.Assert(stackIdx <= stackSize);
                data = stack[--stackIdx];

                cell.Lod = Math.Max(data.Lod - LeafLodCount, 0);
                cell.CoordInLod = data.CoordInLod;

                int lodDiff;
                IMyOctreeLeafNode leaf;
                if (m_contentLeaves.TryGetValue(cell.PackId64(), out leaf))
                {
                    lodDiff = data.Lod;
                    var rangeMinInDataLod = bb.Min >> lodDiff;
                    var rangeMaxInDataLod = bb.Max >> lodDiff;
                    if (data.CoordInLod.IsInsideInclusive(ref rangeMinInDataLod, ref rangeMaxInDataLod))
                    {
                        var start = rangeMinInDataLod << data.Lod;
                        var end = (rangeMaxInDataLod) << data.Lod;

                        var leafBounds = new BoundingBoxD(start, end);
                        
                        LineD ll;
                        leafBounds.Intersect(ref line, out ll);



                        if (leaf.Intersect(ref ll, out startOfft, out endOfft))
                        {
                            if (finalB.Contains(ll.From) == ContainmentType.Disjoint)
                            {
                                result.From = ll.From;
                                finalB.Include(ll.From);
                            }
                            if (finalB.Contains(ll.To) == ContainmentType.Disjoint)
                            {
                                result.To = ll.To;
                                finalB.Include(ll.To);
                            }
                        }
                    }
                    continue;
                }

                cell.Lod -= 1;
                lodDiff = data.Lod - 1;
                var node = m_contentNodes[cell.PackId64()];

                var min = bb.Min >> lodDiff;
                var max = bb.Max >> lodDiff;
                var nodePositionInChild = data.CoordInLod << 1;
                min -= nodePositionInChild;
                max -= nodePositionInChild;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    Vector3I childPosRelative;
                    ComputeChildCoord(i, out childPosRelative);
                    if (!childPosRelative.IsInsideInclusive(ref min, ref max))
                        continue;

                    BoundingBoxD nodeBounds;
                    nodeBounds.Min = childPosRelative + cell.CoordInLod << lodDiff;
                    nodeBounds.Max = nodeBounds.Min + (1 << data.Lod);

                    if (finalB.Contains(nodeBounds) == ContainmentType.Contains) continue;

                    if (!nodeBounds.Intersects(ref line))
                        continue;

                    if (node.HasChild(i))
                    {
                        Debug.Assert(stackIdx < stackSize);
                        stack[stackIdx++] = new MyCellCoord(data.Lod - 1, nodePositionInChild + childPosRelative);
                    }
                }
            }

            if (!finalB.Valid) return false;

            line.To = result.To;
            line.From = result.From;
            line.Length = (result.To - result.From).Length();
            return true;
        }