예제 #1
0
        protected void UpdateRenderObject()
        {
            m_actualWorldAABB = BoundingBoxD.CreateInvalid();

            if (AnimationController.CharacterBones != null)
            {
                for (int i = 1; i < Model.Bones.Length; i++)
                {
                    Vector3D p1 = Vector3D.Transform(AnimationController.CharacterBones[i].Parent.AbsoluteTransform.Translation, WorldMatrix);
                    Vector3D p2 = Vector3D.Transform(AnimationController.CharacterBones[i].AbsoluteTransform.Translation, WorldMatrix);

                    m_actualWorldAABB.Include(ref p1);
                    m_actualWorldAABB.Include(ref p2);
                }
            }

            ContainmentType containmentType;

            m_aabb.Contains(ref m_actualWorldAABB, out containmentType);
            if (containmentType != ContainmentType.Contains)
            {
                m_actualWorldAABB.Inflate(0.5f);
                MatrixD worldMatrix = WorldMatrix;
                VRageRender.MyRenderProxy.UpdateRenderObject(Render.RenderObjectIDs[0], ref worldMatrix, false, m_actualWorldAABB);
                m_aabb = m_actualWorldAABB;
            }
        }
        public void PrepareVoxelTriangleTests(BoundingBoxD cellBoundingBox, List<MyCubeGrid> gridsToTestOutput)
        {
            ProfilerShort.Begin("PrepareVoxelTriangleTests");

            m_tmpEntityList.Clear();

            // Each triangle will be tested with grids up to one largest cube further away from them, so we have to reflect this in the bounding box.
            float largeCubeSize = MyDefinitionManager.Static.GetCubeSize(MyCubeSize.Large);
            cellBoundingBox.Inflate(largeCubeSize);

            // Furthermore, a triangle cannot lie in a cube under existing block, so we have to extend the bbox even further
            if (MyPerGameSettings.NavmeshPresumesDownwardGravity)
            {
                var min = cellBoundingBox.Min;
                min.Y -= largeCubeSize;
                cellBoundingBox.Min = min;
            }

            MyGamePruningStructure.GetAllEntitiesInBox(ref cellBoundingBox, m_tmpEntityList);
            foreach (var entity in m_tmpEntityList)
            {
                var grid = entity as MyCubeGrid;
                if (grid == null) continue;

                if (!MyGridPathfinding.GridCanHaveNavmesh(grid)) continue;

                gridsToTestOutput.Add(grid);
            }

            m_tmpEntityList.Clear();

            ProfilerShort.End();
        }
예제 #3
0
        /// <summary>
        /// How far away is the closest entity to myCubeGrid?
        /// </summary>
        /// <returns>Distance to closest Entity, may be negative</returns>
        public double ClosestEntity()
        {
            BoundingBoxD NearbyBox = myCubeGrid.WorldAABB;

            NearbyBox.Inflate(NearbyRange);

            HashSet <IMyEntity> offenders = new HashSet <IMyEntity>();          // = MyAPIGateway.Entities.GetEntitiesInAABB_Safe(ref NearbyBox);

            MyAPIGateway.Entities.GetEntitiesInAABB_Safe_NoBlock(NearbyBox, offenders, collect_Entities);
            if (offenders.Count == 0)
            {
                myLogger.debugLog("AABB is empty", "ClosestEntity()");
                return(NearbyRange);
            }
            myLogger.debugLog("collected entities to test: " + offenders.Count, "ClosestEntity()");

            double distClosest = NearbyRange;

            foreach (IMyEntity entity in offenders)
            {
                double distance = myCubeGrid.Distance_ShorterBounds(entity);
                if (distance < distClosest)
                {
                    distClosest = distance;
                }
            }
            return(distClosest);
        }
예제 #4
0
        private static void CheckNeighbourStaticGridsAfterVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape)
        {
            // Check static grids around (possible change to dynamic)
            if (Sync.IsServer && MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled)
            {
                BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
                cutOutBox.Inflate(0.25);

                List <MyEntity> boxOverlapList = new List <MyEntity>();
                MyEntities.GetElementsInBox(ref cutOutBox, boxOverlapList);

                foreach (var entity in boxOverlapList)
                {
                    var grid = entity as MyCubeGrid;
                    if (grid != null && grid.IsStatic)
                    {
                        if (grid.Physics != null && grid.Physics.Shape != null)
                        {
                            grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks());
                        }

                        if (type == MyVoxelBase.OperationType.Cut)
                        {
                            grid.TestDynamic = true;
                        }
                    }
                }

                boxOverlapList.Clear();
            }
        }
        /// <summary>
        /// Writes all surrounding blocks around the given one with the given size.
        /// </summary>
        private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MyCubeBlock> outBlocks)
        {
            outBlocks.Clear();

            BoundingBoxD aabb = new BoundingBoxD(block.Min * block.CubeGrid.GridSize - block.CubeGrid.GridSize / 2, block.Max * block.CubeGrid.GridSize + block.CubeGrid.GridSize / 2);

            if (block.FatBlock != null)
            {
                aabb = (BoundingBoxD)block.FatBlock.Model.BoundingBox;
                aabb.Translate(block.Position * block.CubeGrid.GridSize);
            }

            aabb = aabb.Transform(block.CubeGrid.WorldMatrix);
            aabb.Inflate(0.125);

            List <MyEntity> boxOverlapList = new List <MyEntity>();

            MyEntities.GetElementsInBox(ref aabb, boxOverlapList);

            for (int i = 0; i < boxOverlapList.Count; i++)
            {
                var otherBlock = boxOverlapList[i] as MyCubeBlock;
                if (otherBlock != null && otherBlock.CubeGrid.IsStatic && otherBlock.CubeGrid.EnableSmallToLargeConnections && otherBlock.SlimBlock != block && otherBlock.CubeGrid != block.CubeGrid &&
                    otherBlock.CubeGrid.GridSizeEnum == cubeSizeEnum && !(otherBlock is MyCompoundCubeBlock) && !(otherBlock is MyFracturedBlock))
                {
                    outBlocks.Add(otherBlock);
                }
            }

            boxOverlapList.Clear();
        }
예제 #6
0
        public unsafe void PrepareVoxelTriangleTests(BoundingBoxD cellBoundingBox, List <MyCubeGrid> gridsToTestOutput)
        {
            m_tmpEntityList.Clear();
            float cubeSize = MyDefinitionManager.Static.GetCubeSize(MyCubeSize.Large);

            cellBoundingBox.Inflate((double)cubeSize);
            if (MyPerGameSettings.NavmeshPresumesDownwardGravity)
            {
                Vector3D min     = cellBoundingBox.Min;
                double * numPtr1 = (double *)ref min.Y;
                numPtr1[0]         -= cubeSize;
                cellBoundingBox.Min = min;
            }
            MyGamePruningStructure.GetAllEntitiesInBox(ref cellBoundingBox, m_tmpEntityList, MyEntityQueryType.Both);
            foreach (MyCubeGrid grid in m_tmpEntityList)
            {
                if (grid == null)
                {
                    continue;
                }
                if (MyGridPathfinding.GridCanHaveNavmesh(grid))
                {
                    gridsToTestOutput.Add(grid);
                }
            }
            m_tmpEntityList.Clear();
        }
예제 #7
0
        public void CreateSingleCluster()
        {
            BoundingBoxD bb = SingleCluster.Value;

            bb.Inflate(200); //inflate 200m so objects near world border have AABB inside => physics created
            CreateCluster(ref bb);
        }
예제 #8
0
        private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MyCubeBlock> outBlocks)
        {
            outBlocks.Clear();
            BoundingBoxD boundingBox = new BoundingBoxD((Vector3D)((block.Min * block.CubeGrid.GridSize) - (block.CubeGrid.GridSize / 2f)), (block.Max * block.CubeGrid.GridSize) + (block.CubeGrid.GridSize / 2f));

            if (block.FatBlock != null)
            {
                Matrix matrix;
                boundingBox = block.FatBlock.Model.BoundingBox;
                block.FatBlock.Orientation.GetMatrix(out matrix);
                boundingBox = boundingBox.TransformFast(matrix);
                boundingBox.Translate(boundingBox.Center);
            }
            boundingBox = boundingBox.TransformFast(block.CubeGrid.WorldMatrix);
            boundingBox.Inflate((double)0.125);
            List <VRage.Game.Entity.MyEntity> foundElements = new List <VRage.Game.Entity.MyEntity>();

            Sandbox.Game.Entities.MyEntities.GetElementsInBox(ref boundingBox, foundElements);
            int num = 0;

            while (true)
            {
                while (true)
                {
                    if (num >= foundElements.Count)
                    {
                        foundElements.Clear();
                        return;
                    }
                    MyCubeBlock item = foundElements[num] as MyCubeBlock;
                    if (((item != null) && (!ReferenceEquals(item.SlimBlock, block) && (item.CubeGrid.IsStatic && (item.CubeGrid.EnableSmallToLargeConnections && (item.CubeGrid.SmallToLargeConnectionsInitialized && (!ReferenceEquals(item.CubeGrid, block.CubeGrid) && ((item.CubeGrid.GridSizeEnum == cubeSizeEnum) && !(item is MyFracturedBlock)))))))) && !item.Components.Has <MyFractureComponentBase>())
                    {
                        MyCompoundCubeBlock block3 = item as MyCompoundCubeBlock;
                        if (block3 != null)
                        {
                            foreach (MySlimBlock block4 in block3.GetBlocks())
                            {
                                if (ReferenceEquals(block4, block))
                                {
                                    continue;
                                }
                                if (!block4.FatBlock.Components.Has <MyFractureComponentBase>())
                                {
                                    outBlocks.Add(block4.FatBlock);
                                }
                            }
                            break;
                        }
                        outBlocks.Add(item);
                    }
                    break;
                }
                num++;
            }
        }
예제 #9
0
        private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MySlimBlock> outBlocks)
        {
            outBlocks.Clear();
            BoundingBoxD aabbForNeighbors = new BoundingBoxD((Vector3D)(block.Min * block.CubeGrid.GridSize), (Vector3D)(block.Max * block.CubeGrid.GridSize));
            BoundingBoxD box = new BoundingBoxD((Vector3D)((block.Min * block.CubeGrid.GridSize) - (block.CubeGrid.GridSize / 2f)), (block.Max * block.CubeGrid.GridSize) + (block.CubeGrid.GridSize / 2f));

            if (block.FatBlock != null)
            {
                Matrix matrix;
                box = block.FatBlock.Model.BoundingBox;
                block.FatBlock.Orientation.GetMatrix(out matrix);
                box = box.TransformFast(matrix);
                box.Translate(box.Center);
            }
            box.Inflate((double)0.125);
            BoundingBoxD boundingBox = box.TransformFast(block.CubeGrid.WorldMatrix);
            List <VRage.Game.Entity.MyEntity> foundElements = new List <VRage.Game.Entity.MyEntity>();

            Sandbox.Game.Entities.MyEntities.GetElementsInBox(ref boundingBox, foundElements);
            for (int i = 0; i < foundElements.Count; i++)
            {
                MyCubeGrid objA = foundElements[i] as MyCubeGrid;
                if (((objA != null) && (objA.IsStatic && (!ReferenceEquals(objA, block.CubeGrid) && (objA.EnableSmallToLargeConnections && objA.SmallToLargeConnectionsInitialized)))) && (objA.GridSizeEnum == cubeSizeEnum))
                {
                    m_tmpSlimBlocksList.Clear();
                    objA.GetBlocksIntersectingOBB(box, block.CubeGrid.WorldMatrix, m_tmpSlimBlocksList);
                    CheckNeighborBlocks(block, aabbForNeighbors, objA, m_tmpSlimBlocksList);
                    foreach (MySlimBlock block2 in m_tmpSlimBlocksList)
                    {
                        if (block2.FatBlock == null)
                        {
                            outBlocks.Add(block2);
                            continue;
                        }
                        if (!(block2.FatBlock is MyFracturedBlock) && !block2.FatBlock.Components.Has <MyFractureComponentBase>())
                        {
                            if (block2.FatBlock is MyCompoundCubeBlock)
                            {
                                foreach (MySlimBlock block3 in (block2.FatBlock as MyCompoundCubeBlock).GetBlocks())
                                {
                                    if (!block3.FatBlock.Components.Has <MyFractureComponentBase>())
                                    {
                                        outBlocks.Add(block3);
                                    }
                                }
                                continue;
                            }
                            outBlocks.Add(block2);
                        }
                    }
                    m_tmpSlimBlocksList.Clear();
                }
            }
            foundElements.Clear();
        }
예제 #10
0
        public static BoundingBoxD AdjustAABBByVelocity(BoundingBoxD aabb, Vector3 velocity, float inflate = 1.1f)
        {
            if (velocity.LengthSquared() > 0.001f)
            {
                velocity.Normalize();
            }
            aabb.Inflate((double)inflate);
            BoundingBoxD box = aabb;

            box += (BoundingBoxD)((velocity * 2000f) * inflate);
            aabb.Include(box);
            return(aabb);
        }
        /// <summary>
        /// Writes all surrounding blocks around the given one with the given size.
        /// </summary>
        private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MyCubeBlock> outBlocks)
        {
            outBlocks.Clear();

            BoundingBoxD aabb = new BoundingBoxD(block.Min * block.CubeGrid.GridSize - block.CubeGrid.GridSize / 2, block.Max * block.CubeGrid.GridSize + block.CubeGrid.GridSize / 2);

            if (block.FatBlock != null)
            {
                var aabbCenter = aabb.Center;
                aabb = (BoundingBoxD)block.FatBlock.Model.BoundingBox;
                Matrix m;
                block.FatBlock.Orientation.GetMatrix(out m);
                aabb = aabb.TransformFast(m);
                aabb.Translate(aabbCenter);
            }

            aabb = aabb.TransformFast(block.CubeGrid.WorldMatrix);
            aabb.Inflate(0.125);

            List <MyEntity> boxOverlapList = new List <MyEntity>();

            MyEntities.GetElementsInBox(ref aabb, boxOverlapList);

            for (int i = 0; i < boxOverlapList.Count; i++)
            {
                var otherBlock = boxOverlapList[i] as MyCubeBlock;
                if (otherBlock != null && otherBlock.SlimBlock != block &&
                    otherBlock.CubeGrid.IsStatic && otherBlock.CubeGrid.EnableSmallToLargeConnections && otherBlock.CubeGrid.SmallToLargeConnectionsInitialized &&
                    otherBlock.CubeGrid != block.CubeGrid && otherBlock.CubeGrid.GridSizeEnum == cubeSizeEnum && !(otherBlock is MyFracturedBlock) &&
                    !(otherBlock.Components.Has <MyFractureComponentBase>()))
                {
                    var compound = otherBlock as MyCompoundCubeBlock;
                    if (compound != null)
                    {
                        foreach (var blockInCompound in compound.GetBlocks())
                        {
                            if (blockInCompound != block && !(blockInCompound.FatBlock.Components.Has <MyFractureComponentBase>()))
                            {
                                outBlocks.Add(blockInCompound.FatBlock);
                            }
                        }
                    }
                    else
                    {
                        outBlocks.Add(otherBlock);
                    }
                }
            }

            boxOverlapList.Clear();
        }
        /// <summary>
        /// Writes all surrounding blocks around the given one with the given size.
        /// </summary>
        private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MyCubeBlock> outBlocks)
        {
            outBlocks.Clear();

            BoundingBoxD aabb = new BoundingBoxD(block.Min * block.CubeGrid.GridSize - block.CubeGrid.GridSize / 2, block.Max * block.CubeGrid.GridSize + block.CubeGrid.GridSize / 2);

            if (block.FatBlock != null)
            {
                aabb = (BoundingBoxD)block.FatBlock.Model.BoundingBox;
                aabb.Translate(block.Position * block.CubeGrid.GridSize);
            }

            aabb = aabb.Transform(block.CubeGrid.WorldMatrix);
            aabb.Inflate(0.125);

            List <MyEntity> boxOverlapList = new List <MyEntity>();

            MyEntities.GetElementsInBox(ref aabb, boxOverlapList);

            for (int i = 0; i < boxOverlapList.Count; i++)
            {
                var otherGrid = boxOverlapList[i] as MyCubeGrid;
                if (otherGrid != null)
                {
                    foreach (var gridBlock in otherGrid.CubeBlocks)
                    {
                        if (IsValidForConnection(gridBlock.FatBlock, block, cubeSizeEnum))
                        {
                            if (!IsCompoundAndProcessed(gridBlock.FatBlock, block, outBlocks))
                            {
                                outBlocks.Add(gridBlock.FatBlock);
                            }
                        }
                    }
                }
                else
                {
                    var otherBlock = boxOverlapList[i] as MyCubeBlock;
                    if (IsValidForConnection(otherBlock, block, cubeSizeEnum))
                    {
                        if (!IsCompoundAndProcessed(otherBlock, block, outBlocks))
                        {
                            outBlocks.Add(otherBlock);
                        }
                    }
                }
            }

            boxOverlapList.Clear();
        }
예제 #13
0
        private static void OnVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape)
        {
            if (Sync.IsServer)
            {
                BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
                cutOutBox.Inflate(0.25);

                MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList);
                // Check static grids around (possible change to dynamic)
                if (/*MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL &&*/ MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled)
                {
                    foreach (var entity in m_overlapList)
                    {
                        var grid = entity as MyCubeGrid;
                        if (grid != null && grid.IsStatic)
                        {
                            if (grid.Physics != null && grid.Physics.Shape != null)
                            {
                                grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks());
                            }

                            if (type == MyVoxelBase.OperationType.Cut)
                            {
                                grid.TestDynamic = true;
                            }
                        }
                    }
                }
            }
            var      voxelPhysics = voxelMap as MyVoxelPhysics;
            MyPlanet planet       = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet;

            if (planet != null)
            {
                var planetEnvironment = planet.Components.Get <MyPlanetEnvironmentComponent>();
                if (planetEnvironment != null)
                {
                    var sectors = planetEnvironment.GetSectorsInRange(shape);
                    if (sectors != null)
                    {
                        foreach (var sector in sectors)
                        {
                            sector.DisableItemsInShape(shape);
                        }
                    }
                }
            }
            m_overlapList.Clear();
        }
예제 #14
0
 public static void NotifyVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, ref BoundingBoxD cutOutBox)
 {
     cutOutBox.Inflate((double)0.25);
     MyGamePruningStructure.GetTopmostEntitiesInBox(ref cutOutBox, m_overlapList, MyEntityQueryType.Both);
     if (MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST)
     {
         foreach (MyEntity entity in m_overlapList)
         {
             if (Sync.IsServer)
             {
                 MyCubeGrid grid = entity as MyCubeGrid;
                 if ((grid != null) && grid.IsStatic)
                 {
                     if ((grid.Physics != null) && (grid.Physics.Shape != null))
                     {
                         grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks());
                     }
                     if (type == MyVoxelBase.OperationType.Cut)
                     {
                         grid.TestDynamic = MyCubeGrid.MyTestDynamicReason.GridSplit;
                     }
                 }
             }
             MyPhysicsBody physics = entity.Physics as MyPhysicsBody;
             if (((physics != null) && !physics.IsStatic) && (physics.RigidBody != null))
             {
                 physics.RigidBody.Activate();
             }
         }
     }
     m_overlapList.Clear();
     if (Sync.IsServer)
     {
         MyPlanetEnvironmentComponent component = voxelMap.Components.Get <MyPlanetEnvironmentComponent>();
         if (component != null)
         {
             component.GetSectorsInRange(ref cutOutBox, m_overlapList);
             using (List <MyEntity> .Enumerator enumerator = m_overlapList.GetEnumerator())
             {
                 while (enumerator.MoveNext())
                 {
                     ((MyEnvironmentSector)enumerator.Current).DisableItemsInBox(ref cutOutBox);
                 }
             }
             m_overlapList.Clear();
         }
     }
 }
예제 #15
0
        private static void OnVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape)
        {
            if (!Sync.IsServer)
            {
                return;
            }
            BoundingBoxD cutOutBox = shape.GetWorldBoundaries();

            cutOutBox.Inflate(0.25);

            MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList);
            // Check static grids around (possible change to dynamic)
            if (MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled)
            {
                foreach (var entity in m_overlapList)
                {
                    var grid = entity as MyCubeGrid;
                    if (grid != null && grid.IsStatic)
                    {
                        if (grid.Physics != null && grid.Physics.Shape != null)
                        {
                            grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks());
                        }

                        if (type == MyVoxelBase.OperationType.Cut)
                        {
                            grid.TestDynamic = true;
                        }
                    }
                }
            }
            var      voxelPhysics = voxelMap as MyVoxelPhysics;
            MyPlanet planet       = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet;

            if (planet != null)
            {
                var center = cutOutBox.Center;
                foreach (var environment in planet.GetEnvironmentItemsAtPosition(ref center))
                {
                    environment.RemoveItemsAroundPoint(cutOutBox.Center, cutOutBox.HalfExtents.Max());
                }
            }
            m_overlapList.Clear();
        }
예제 #16
0
        public static MyEntity FindSupportForCharacterAABB(MyEntity entity)
        {
            if (entity == null)
            {
                return(null);
            }
            BoundingBoxD characterBox = entity.PositionComp.WorldAABB;

            characterBox.Inflate(1.0);
            m_entities.Clear();

            MyEntities.GetTopMostEntitiesInBox(ref characterBox, m_entities);

            float      maxRadius   = 0;
            MyCubeGrid biggestGrid = null;

            foreach (var parent in m_entities)
            {
                MyCubeGrid grid = parent as MyCubeGrid;

                if (grid != null)
                {
                    if (grid.Physics == null || grid.Physics.IsStatic || grid.GridSizeEnum == MyCubeSize.Small)
                    {
                        continue;
                    }
                    grid = MyGridPhysicsStateGroup.GetMasterGrid(grid);
                    var rad = grid.PositionComp.LocalVolume.Radius;
                    if (rad > maxRadius || (rad == maxRadius && (biggestGrid == null || grid.EntityId > biggestGrid.EntityId)))
                    {
                        maxRadius   = rad;
                        biggestGrid = grid;
                    }
                }
            }

            if (biggestGrid != null && biggestGrid.CubeBlocks.Count > 10)
            {
                return(biggestGrid);
            }
            return(null);
        }
예제 #17
0
        public void EnsureClusterSpace(BoundingBoxD aabb)
        {
            if (SingleCluster.HasValue)
            {
                return;
            }

            aabb.Inflate(3000);
            m_clusterTree.OverlapAllBoundingBox(ref aabb, m_returnedClusters);

            bool needReorder = true;

            if (m_returnedClusters.Count == 1)
            {
                if (m_returnedClusters[0].AABB.Contains(aabb) == ContainmentType.Contains)
                {
                    needReorder = false;
                }
            }

            if (needReorder)
            {
                ulong objectId       = m_clusterObjectCounter++;
                int   staticObjectId = MyDynamicAABBTreeD.NullNode;

                m_objectsData[objectId] = new MyObjectData()
                {
                    Id                = objectId,
                    Cluster           = null,
                    ActivationHandler = null,
                    AABB              = aabb,
                    StaticId          = staticObjectId
                };

                ReorderClusters(aabb, objectId);

                RemoveObjectFromCluster(m_objectsData[objectId], false);

                m_objectsData.Remove(objectId);
            }
        }
예제 #18
0
        // DigVoxels will dig voxels around the grids if necessary.
        //
        // Grids built inside dug out voxel (e.g. underground bases) have the problem that once saved
        // in hangar, voxels are likely to regenerate, and the grids cannot be loaded again without
        // exploding, requiring either admin assistance to dig it out, or give up on the grids.
        //
        // However it is not desirable to dig out all voxels around the grids unconditionally, grids placed
        // on voxels (e.g. surface bases) can load just fine and voxels under them should remain intact.
        //
        // Therefore the criteria is: if the grids center is inside voxels then dig voxels around, otherwise not.
        // The current digging strategy is simply a bounding box around it, aligned on the biggest grid and as
        // large as necessary for the whole grid to fit, plus an arbitrary 2 meters to fit a character standing.
        //
        // The grids center and the bounding box are determined by FindGridBounds.
        //
        // It is worth noting that this behavior can be used to dig out voxels for free, e.g. a long line of
        // blocks in each direction would result in a large cube dug out; or, in gravity a station grid that was
        // previously held by voxels would now appear to float in the air. These are definitely quirks but
        // not game breaking, as players can achieve the same result themselves.
        //
        // Needs to run in the game thread.
        private void DigVoxels()
        {
            var center = new BoundingBoxD(SphereD.Center - 0.1f, SphereD.Center + 0.1f);

            foreach (MyVoxelBase voxel in MySession.Static.VoxelMaps.Instances)
            {
                if (voxel.StorageName == null)
                {
                    continue;                            // invalid voxel
                }
                // ignore ghost asteroids: planets don't have physics linked directly to entity and
                // asteroids do have physics and they're disabled when in ghost placement mode, but not null
                if (!(voxel is MyPlanet) && (voxel.Physics == null || !voxel.Physics.Enabled))
                {
                    continue;
                }

                // before we check if it's inside voxel material (complex), there's a fast check
                // we can do: if it's not near the voxel map, then bail out
                if (!voxel.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref center))
                {
                    continue;
                }

                // dig only if the grids center is inside voxel material
                // this allows to leave untouched grids that are partially in voxels on purpose
                if (!voxel.IsAnyAabbCornerInside(ref MatrixD.Identity, center))
                {
                    continue;
                }

                // in practice, this is reached only once because voxel material cannot overlap

                var box = new BoundingBoxD(BoxAAB.Min, BoxAAB.Max);
                box.Inflate(2f); // just enough for one character height
                var shape = MyAPIGateway.Session.VoxelMaps.GetBoxVoxelHand();
                shape.Boundaries = box;
                shape.Transform  = _BiggestGrid.PositionAndOrientation.Value.GetMatrix();
                MyAPIGateway.Session.VoxelMaps.CutOutShape(voxel, shape);
            }
        }
예제 #19
0
        public void PrepareVoxelTriangleTests(BoundingBoxD cellBoundingBox, List <MyCubeGrid> gridsToTestOutput)
        {
            ProfilerShort.Begin("PrepareVoxelTriangleTests");

            m_tmpEntityList.Clear();

            // Each triangle will be tested with grids up to one largest cube further away from them, so we have to reflect this in the bounding box.
            float largeCubeSize = MyDefinitionManager.Static.GetCubeSize(MyCubeSize.Large);

            cellBoundingBox.Inflate(largeCubeSize);

            // Furthermore, a triangle cannot lie in a cube under existing block, so we have to extend the bbox even further
            if (MyPerGameSettings.NavmeshPresumesDownwardGravity)
            {
                var min = cellBoundingBox.Min;
                min.Y -= largeCubeSize;
                cellBoundingBox.Min = min;
            }

            MyGamePruningStructure.GetAllEntitiesInBox(ref cellBoundingBox, m_tmpEntityList);
            foreach (var entity in m_tmpEntityList)
            {
                var grid = entity as MyCubeGrid;
                if (grid == null)
                {
                    continue;
                }

                if (!MyGridPathfinding.GridCanHaveNavmesh(grid))
                {
                    continue;
                }

                gridsToTestOutput.Add(grid);
            }

            m_tmpEntityList.Clear();

            ProfilerShort.End();
        }
예제 #20
0
        public static MyEntity FindSupportForCharacterAABB(MyEntity entity)
        {
            BoundingBoxD characterBox = entity.PositionComp.WorldAABB;

            characterBox.Inflate(1.0);
            m_entities.Clear();

            MyEntities.GetTopMostEntitiesInBox(ref characterBox, m_entities);

            float      maxRadius   = 0;
            MyCubeGrid biggestGrid = null;
            MyEntity   voxel       = null;

            foreach (var parent in m_entities)
            {
                MyCubeGrid grid = parent as MyCubeGrid;
                if (parent is MyVoxelBase)
                {
                    voxel = (parent as MyVoxelBase).RootVoxel;
                }
                if (grid != null)
                {
                    var rad = grid.PositionComp.LocalVolume.Radius;
                    if (rad > maxRadius || (rad == maxRadius && (biggestGrid == null || grid.EntityId > biggestGrid.EntityId)))
                    {
                        maxRadius   = rad;
                        biggestGrid = grid;
                    }
                }
            }

            if (biggestGrid == null)
            {
                return(voxel);
            }
            return(biggestGrid);
        }
        // ReSharper restore InconsistentNaming
        public void DebugDraw(bool force = false)
        {
            force |= ForceDebugDraw;
            if (!force && !Settings.DebugDraw)
            {
                return;
            }
            var transform = Grid.WorldMatrix;
            var gridSize  = Grid.GridSize;

            foreach (var room in Construction.Rooms)
            {
                if (force || Settings.DebugDrawBlocks)
                {
                    var localAABB = new BoundingBoxD((room.BoundingBox.Min - 0.5f) * gridSize, (room.BoundingBox.Max + 0.5f) * gridSize);
                    MySimpleObjectDraw.DrawTransparentBox(ref transform, ref localAABB, ref DebugColorBlocksTotal, MySimpleObjectRasterizer.Wireframe, 1, .02f);
                }
                if (force || Settings.DebugDrawReservedTotal && room.Part.ReservedSpaces.Any())
                {
                    var temp    = Utilities.TransformBoundingBox(room.Part.ReservedSpace, room.Transform);
                    var tmpAABB = new BoundingBoxD((temp.Min - 0.5f) * gridSize, (temp.Max + 0.5f) * gridSize);
                    MySimpleObjectDraw.DrawTransparentBox(ref transform, ref tmpAABB, ref DebugColorReservedSpaceTotal, MySimpleObjectRasterizer.Wireframe, 1, .02f);
                }
                if (force || Settings.DebugDrawReserved)
                {
                    foreach (var rs in room.Part.ReservedSpaces)
                    {
                        var temp    = Utilities.TransformBoundingBox(rs.Box, room.Transform);
                        var tmpAABB = new BoundingBoxD(temp.Min * gridSize, (temp.Max + 1) * gridSize);
                        tmpAABB = tmpAABB.Inflate(-0.02);
                        Color color;
                        if (rs.IsShared && rs.IsOptional)
                        {
                            color = DebugColorReservedSpaceBoth;
                        }
                        else if (rs.IsShared)
                        {
                            color = DebugColorReservedSpaceShared;
                        }
                        else if (rs.IsOptional)
                        {
                            color = DebugColorReservedSpaceOptional;
                        }
                        else
                        {
                            color = DebugColorReservedSpace;
                        }
                        MySimpleObjectDraw.DrawTransparentBox(ref transform, ref tmpAABB, ref color, MySimpleObjectRasterizer.Wireframe, 1, .005f);
                    }
                }
                // ReSharper disable once InvertIf
                if (force || Settings.DebugDrawMountPoints)
                {
                    foreach (var mount in room.MountPoints)
                    {
                        foreach (var block in mount.MountPoint.Blocks)
                        {
                            var anchorLoc = (Vector3)block.AnchorLocation;
                            var opposeLoc = (Vector3)(block.AnchorLocation + (block.MountDirection * 2));
                            opposeLoc += 0.5f * Vector3.Abs(Vector3I.One - Vector3I.Abs(block.MountDirection)); // hacky way to get perp. components
                            anchorLoc -= 0.5f * Vector3.Abs(Vector3I.One - Vector3I.Abs(block.MountDirection));

                            var anchor  = gridSize * Vector3.Transform(anchorLoc, room.Transform.GetFloatMatrix());
                            var oppose  = gridSize * Vector3.Transform(opposeLoc, room.Transform.GetFloatMatrix());
                            var tmpAABB = new BoundingBoxD(Vector3.Min(anchor, oppose), Vector3.Max(anchor, oppose));
                            MySimpleObjectDraw.DrawTransparentBox(ref transform, ref tmpAABB, ref DebugColorMountPoint, MySimpleObjectRasterizer.Solid, 1, .02f);
                        }
                    }
                }
            }
        }
예제 #22
0
        public static bool DefaultGizmoCloseEnough(ref MatrixD invGridWorldMatrix, BoundingBoxD gizmoBox, float gridSize, float intersectionDistance)
        {
            //MyRenderProxy.DebugDrawText2D(new Vector2(0.0f, 0.0f), "Intersection distance = " + intersectionDistance, Color.Red, 1.0f);

            var m = invGridWorldMatrix;

            MyCharacter character = MySession.LocalCharacter;
            if (character == null)
                return false;

            // Character head for measuring distance to intesection.
            Vector3D originHead = character.GetHeadMatrix(true).Translation;
            // Camera position adn direction. Used for ray cast to cube block box.
            Vector3D originCamera = MySector.MainCamera.Position;
            Vector3 direction = MySector.MainCamera.ForwardVector;

            Vector3 localHead = Vector3D.Transform(originHead, m);
            Vector3 localStart = Vector3D.Transform(originCamera, m);
            Vector3 localEnd = Vector3D.Transform(originCamera + direction * intersectionDistance, m);
            LineD line = new LineD(localStart, localEnd);

            // AABB of added block
            float inflate = 0.025f * gridSize;
            gizmoBox.Inflate(inflate);

            /*{
                Vector4 blue = Color.Blue.ToVector4();
                Matrix mtx = Matrix.Invert(invGridWorldMatrix);
                MySimpleObjectDraw.DrawTransparentBox(ref mtx, ref gizmoBox, ref blue, MySimpleObjectRasterizer.Wireframe, 1, 0.04f);
            }*/

            double distance = double.MaxValue;
            if (gizmoBox.Intersects(line, out distance))
            {
                // Distance from the player's head to the gizmo box.
                double distanceToPlayer = gizmoBox.Distance(localHead);
                return distanceToPlayer <= 5.0;
            }
            return false;
        }
예제 #23
0
        public static bool DefaultGizmoCloseEnough(ref MatrixD invGridWorldMatrix, BoundingBoxD gizmoBox, float gridSize, float intersectionDistance)
        {
            //MyRenderProxy.DebugDrawText2D(new Vector2(0.0f, 0.0f), "Intersection distance = " + intersectionDistance, Color.Red, 1.0f);

            var m = invGridWorldMatrix;

            MyCharacter character = MySession.Static.LocalCharacter;
            if (character == null)
                return false;

            // Character head for measuring distance to intesection.
            Vector3D originHead = character.GetHeadMatrix(true).Translation;
            // Camera position adn direction. Used for ray cast to cube block box.
            Vector3D originCamera = MySector.MainCamera.Position;
            Vector3 direction = MySector.MainCamera.ForwardVector;

            double cameraHeadDist = (originHead - MySector.MainCamera.Position).Length();

            Vector3 localHead = Vector3D.Transform(originHead, m);
            Vector3 localStart = Vector3D.Transform(originCamera, m);
            Vector3 localEnd = Vector3D.Transform(originCamera + direction * (intersectionDistance + (float)cameraHeadDist), m);
            LineD line = new LineD(localStart, localEnd);

            // AABB of added block
            float inflate = 0.025f * gridSize;
            gizmoBox.Inflate(inflate);

            //{
            //    Color blue = Color.Blue;
            //    MatrixD mtx = MatrixD.Invert(invGridWorldMatrix);
            //    MySimpleObjectDraw.DrawTransparentBox(ref mtx, ref gizmoBox, ref blue, MySimpleObjectRasterizer.Wireframe, 1, 0.04f);



            //    MyRenderProxy.DebugDrawLine3D(originCamera, originCamera + direction * (intersectionDistance + (float)cameraHeadDist), Color.Red, Color.Red, false);
            //}

            double distance = double.MaxValue;
            if (gizmoBox.Intersects(ref line, out distance))
            {
                // Distance from the player's head to the gizmo box.
                double distanceToPlayer = gizmoBox.Distance(localHead);
                if (MySession.Static.ControlledEntity is MyShipController)
                {
                    if (MyCubeBuilder.Static.CubeBuilderState.CurrentBlockDefinition.CubeSize == MyCubeSize.Large)
                        return distanceToPlayer <= MyCubeBuilder.CubeBuilderDefinition.BuildingDistLargeSurvivalShip;
                    else
                        return distanceToPlayer <= MyCubeBuilder.CubeBuilderDefinition.BuildingDistSmallSurvivalShip;
                }
                else
                {
                    if (MyCubeBuilder.Static.CubeBuilderState.CurrentBlockDefinition.CubeSize == MyCubeSize.Large)
                        return distanceToPlayer <= MyCubeBuilder.CubeBuilderDefinition.BuildingDistLargeSurvivalCharacter;
                    else
                        return distanceToPlayer <= MyCubeBuilder.CubeBuilderDefinition.BuildingDistSmallSurvivalCharacter;
                }
            }
            return false;
        }
        /// <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);
        }
        private unsafe void RasterSectorsForCollision(MyEntity entity)
        {
            if (!(entity is MyCubeGrid))
            {
                return;
            }

            BoundingBoxD range = entity.PositionComp.WorldAABB;

            range.Inflate(8);
            range.Translate(-PlanetTranslation);

            Vector2I top = new Vector2I(1 << m_clipmaps[0].Depth) - 1;

            Vector3D *pos = stackalloc Vector3D[8];

            range.GetCornersUnsafe(pos);

            // bitmask for faces, 7th bit is simple bit
            int markedFaces = 0;
            int firstFace   = 0;

            for (var i = 0; i < 8; ++i)
            {
                Vector3D copy = pos[i];

                int index = MyPlanetCubemapHelper.FindCubeFace(ref copy);
                firstFace = index;
                index     = 1 << index;

                if ((markedFaces & ~index) != 0)
                {
                    markedFaces |= 0x40;
                }

                markedFaces |= index;
            }

            // This way we can ensure a single code path.
            int startFace = 0;
            int endFace   = 5;

            // If we only encounter one face we narrow it down.
            if ((markedFaces & 0x40) == 0)
            {
                startFace = endFace = firstFace;
            }

            for (int face = startFace; face <= endFace; ++face)
            {
                if (((1 << face) & markedFaces) == 0)
                {
                    continue;
                }

                // Offset
                var offset = 1 << m_clipmaps[face].Depth - 1;

                BoundingBox2D bounds = BoundingBox2D.CreateInvalid();
                for (int i = 0; i < 8; ++i)
                {
                    Vector3D copy = pos[i];

                    Vector2D normCoords;
                    MyPlanetCubemapHelper.ProjectForFace(ref copy, face, out normCoords);
                    bounds.Include(normCoords);
                }

                bounds.Min += 1;
                bounds.Min *= offset;

                bounds.Max += 1;
                bounds.Max *= offset;

                // Calculate bounds in sectors.
                var start = new Vector2I((int)bounds.Min.X, (int)bounds.Min.Y);
                var end   = new Vector2I((int)bounds.Max.X, (int)bounds.Max.Y);

                Vector2I.Max(ref start, ref Vector2I.Zero, out start);
                Vector2I.Min(ref end, ref top, out end);

                for (int x = start.X; x <= end.X; ++x)
                {
                    for (int y = start.Y; y <= end.Y; ++y)
                    {
                        long sect = MyPlanetSectorId.MakeSectorId(x, y, face);

                        List <MyOrientedBoundingBoxD> boxes;
                        if (!m_obstructorsPerSector.TryGetValue(sect, out boxes))
                        {
                            boxes = new List <MyOrientedBoundingBoxD>();
                            m_obstructorsPerSector.Add(sect, boxes);
                        }

                        var bb = entity.PositionComp.LocalAABB;
                        bb.Inflate(8); // inflate by 8m to increase the likellyhood of overlap with trees' roots.

                        boxes.Add(new MyOrientedBoundingBoxD((BoundingBoxD)bb, entity.PositionComp.WorldMatrix));
                    }
                }
            }
        }
예제 #26
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);
        }
예제 #27
0
        public ulong AddObject(BoundingBoxD bbox, Vector3 velocity, IMyActivationHandler activationHandler, ulong?customId)
        {
            if (SingleCluster.HasValue && m_clusters.Count == 0)
            {
                BoundingBoxD bb = SingleCluster.Value;
                bb.Inflate(200); //inflate 200m so objects near world border have AABB inside => physics created
                CreateCluster(ref bb);
            }

            BoundingBoxD inflatedBBox;

            if (SingleCluster.HasValue)
            {
                inflatedBBox = bbox;
            }
            else
            {
                inflatedBBox = bbox.GetInflated(MinimumDistanceFromBorder);
            }

            m_clusterTree.OverlapAllBoundingBox(ref inflatedBBox, m_returnedClusters);

            MyCluster cluster     = null;
            bool      needReorder = false;

            if (m_returnedClusters.Count == 1)
            {
                if (m_returnedClusters[0].AABB.Contains(inflatedBBox) == ContainmentType.Contains)
                {
                    cluster = m_returnedClusters[0];
                }
                else
                if (m_returnedClusters[0].AABB.Contains(inflatedBBox) == ContainmentType.Intersects && activationHandler.IsStaticForCluster)
                {
                    if (m_returnedClusters[0].AABB.Contains(bbox) == ContainmentType.Disjoint)
                    {       //completely out
                    }
                    else
                    {
                        cluster = m_returnedClusters[0];
                    }
                }
                else
                {
                    needReorder = true;
                }
            }
            else
            if (m_returnedClusters.Count > 1)
            {
                needReorder = true;
            }
            else
            if (m_returnedClusters.Count == 0)
            {
                if (!activationHandler.IsStaticForCluster)
                {
                    var clusterBB = new BoundingBoxD(bbox.Center - IdealClusterSize / 2, bbox.Center + IdealClusterSize / 2);
                    m_clusterTree.OverlapAllBoundingBox(ref clusterBB, m_returnedClusters);

                    if (m_returnedClusters.Count == 0)
                    {     //Space is empty, create new cluster
                        m_staticTree.OverlapAllBoundingBox(ref clusterBB, m_objectDataResultList);
                        cluster = CreateCluster(ref clusterBB);

                        foreach (var ob in m_objectDataResultList)
                        {
                            System.Diagnostics.Debug.Assert(m_objectsData[ob].Cluster == null, "Found object must not be in cluster!");
                            AddObjectToCluster(cluster, ob, false);
                        }
                    }
                    else      //There is still some blocking cluster
                    {
                        needReorder = true;
                    }
                }
            }

            ulong objectId       = customId.HasValue ? customId.Value : m_clusterObjectCounter++;
            int   staticObjectId = MyDynamicAABBTreeD.NullNode;

            m_objectsData[objectId] = new MyObjectData()
            {
                Id                = objectId,
                Cluster           = cluster,
                ActivationHandler = activationHandler,
                AABB              = bbox,
                StaticId          = staticObjectId
            };

            System.Diagnostics.Debug.Assert(!needReorder || (!SingleCluster.HasValue && needReorder), "Object cannot be added outside borders of a single cluster");

            if (needReorder && !SingleCluster.HasValue)
            {
                System.Diagnostics.Debug.Assert(cluster == null, "Error in cluster logic");

                ReorderClusters(bbox, objectId);
                if (!m_objectsData[objectId].ActivationHandler.IsStaticForCluster)
                {
                    System.Diagnostics.Debug.Assert(m_objectsData[objectId].Cluster != null, "Object not added");
                }
#if DEBUG
                m_clusterTree.OverlapAllBoundingBox(ref bbox, m_returnedClusters);

                System.Diagnostics.Debug.Assert(m_returnedClusters.Count <= 1, "Clusters overlap!");
                if (m_returnedClusters.Count != 0)
                {
                    System.Diagnostics.Debug.Assert(activationHandler.IsStaticForCluster ? m_returnedClusters[0].AABB.Contains(inflatedBBox) != ContainmentType.Disjoint : m_returnedClusters[0].AABB.Contains(inflatedBBox) == ContainmentType.Contains, "Clusters reorder failure!");
                }
#endif
            }

            if (activationHandler.IsStaticForCluster)
            {
                staticObjectId = m_staticTree.AddProxy(ref bbox, objectId, 0);

                m_objectsData[objectId].StaticId = staticObjectId;
            }

            if (cluster != null)
            {
                return(AddObjectToCluster(cluster, objectId, false));
            }
            else
            {
                return(objectId);
            }
        }
        /// <summary>
        /// Casts preview grids aabbs and get shortest distance. Returns shortest intersection or null.
        /// </summary>
        protected Vector3D?GetFreeSpacePlacementPositionGridAabbs(bool copyPaste, out bool buildAllowed)
        {
            Vector3D?freePlacementIntersectionPoint = null;

            buildAllowed = true;

            float gridSize = PreviewGrids[0].GridSize;

            double shortestDistance = double.MaxValue;
            double?currentRayInts   = MyCubeBuilder.GetCurrentRayIntersection();

            if (currentRayInts.HasValue)
            {
                shortestDistance = currentRayInts.Value;
            }

            Vector3D worldRefPointOffset = Vector3D.Zero;

            if (copyPaste)
            {
                Matrix firstGridOrientation = GetFirstGridOrientationMatrix();
                worldRefPointOffset = Vector3.TransformNormal(m_dragPointToPositionLocal, firstGridOrientation);
            }

            Vector3D worldRefPoint = PreviewGrids[0].GridIntegerToWorld(Vector3I.Zero);

            foreach (var grid in PreviewGrids)
            {
                Vector3 halfExt  = grid.PositionComp.LocalAABB.HalfExtents;
                Vector3 minLocal = grid.Min * grid.GridSize - Vector3.Half * grid.GridSize;
                Vector3 maxLocal = grid.Max * grid.GridSize + Vector3.Half * grid.GridSize;

                MatrixD gridWorlTransform = MatrixD.Identity;
                gridWorlTransform.Translation = 0.5f * (minLocal + maxLocal);
                gridWorlTransform             = gridWorlTransform * grid.WorldMatrix;

                Vector3I size       = grid.Max - grid.Min + Vector3I.One;
                Vector3  sizeOffset = Vector3I.Abs((size % 2) - Vector3I.One) * 0.5 * grid.GridSize;
                sizeOffset = Vector3.TransformNormal(sizeOffset, grid.WorldMatrix);
                Vector3D offset = gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint /*- sizeOffset*/;// Vector3.Zero;// gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint;

                HkShape shape = new HkBoxShape(halfExt);

                Vector3D rayStart = MyCubeBuilder.IntersectionStart + offset;
                double   castPlaneDistanceToRayStart = DistanceFromCharacterPlane(ref rayStart);
                rayStart -= castPlaneDistanceToRayStart * MyCubeBuilder.IntersectionDirection;

                Vector3D rayEnd = MyCubeBuilder.IntersectionStart + (m_dragDistance - castPlaneDistanceToRayStart) * MyCubeBuilder.IntersectionDirection + offset;
                MatrixD  matrix = gridWorlTransform;
                matrix.Translation = rayStart;

                try
                {
                    float?dist = MyPhysics.CastShape(rayEnd, shape, ref matrix, MyPhysics.CollisionLayers.CollisionLayerWithoutCharacter);
                    if (dist.HasValue && dist.Value != 0f)
                    {
                        Vector3D intersectionPoint = rayStart + dist.Value * (rayEnd - rayStart);

                        const bool debugDraw = true;
                        if (debugDraw)
                        {
                            Color        green     = Color.Green;
                            BoundingBoxD localAABB = new BoundingBoxD(-halfExt, halfExt);
                            localAABB.Inflate(0.03f);
                            MatrixD drawMatrix = matrix;
                            drawMatrix.Translation = intersectionPoint;
                            MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix, ref localAABB, ref green, MySimpleObjectRasterizer.Wireframe, 1, 0.04f);
                        }

                        double fixedDistance = DistanceFromCharacterPlane(ref intersectionPoint) - castPlaneDistanceToRayStart;
                        if (fixedDistance <= 0)
                        {
                            fixedDistance    = 0;
                            shortestDistance = 0;
                            buildAllowed     = false;
                            break;
                        }

                        if (fixedDistance < shortestDistance)
                        {
                            shortestDistance = fixedDistance;
                        }
                    }
                    else
                    {
                        buildAllowed = false;
                    }
                }
                finally
                {
                    shape.RemoveReference();
                }
            }

            if (shortestDistance != 0 && shortestDistance < m_dragDistance)
            {
                freePlacementIntersectionPoint = MyCubeBuilder.IntersectionStart + shortestDistance * MyCubeBuilder.IntersectionDirection;
            }
            else
            {
                buildAllowed = false;
            }

            return(freePlacementIntersectionPoint);
        }
예제 #29
0
        /// <summary>
        /// Casts preview grids aabbs and get shortest distance. Returns shortest intersection or null.
        /// </summary>
        protected Vector3D? GetFreeSpacePlacementPositionGridAabbs(bool copyPaste, out bool buildAllowed)
        {
            Vector3D? freePlacementIntersectionPoint = null;
            buildAllowed = true;

            float gridSize = PreviewGrids[0].GridSize;

            double shortestDistance = double.MaxValue;
            double? currentRayInts = GetCurrentRayIntersection();
            if (currentRayInts.HasValue)
                shortestDistance = currentRayInts.Value;

            Vector3D worldRefPointOffset = Vector3D.Zero;
            if (copyPaste)
            {
                Matrix firstGridOrientation = GetFirstGridOrientationMatrix();
                worldRefPointOffset = Vector3.TransformNormal(m_dragPointToPositionLocal, firstGridOrientation);
            }

            Vector3D worldRefPoint = PreviewGrids[0].GridIntegerToWorld(Vector3I.Zero);

            foreach (var grid in PreviewGrids)
            {
                Vector3 halfExt = grid.PositionComp.LocalAABB.HalfExtents;
                Vector3 minLocal = grid.Min * grid.GridSize - Vector3.Half * grid.GridSize;
                Vector3 maxLocal = grid.Max * grid.GridSize + Vector3.Half * grid.GridSize;

                MatrixD gridWorlTransform = MatrixD.Identity;
                gridWorlTransform.Translation = 0.5f * (minLocal + maxLocal);
                gridWorlTransform = gridWorlTransform * grid.WorldMatrix;

                Vector3I size = grid.Max - grid.Min + Vector3I.One;
                Vector3 sizeOffset = Vector3I.Abs((size % 2) - Vector3I.One) * 0.5 * grid.GridSize;
                sizeOffset = Vector3.TransformNormal(sizeOffset, grid.WorldMatrix);
                Vector3D offset = gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint /*- sizeOffset*/;// Vector3.Zero;// gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint;

                HkShape shape = new HkBoxShape(halfExt);

                Vector3D rayStart = MyCubeBuilder.IntersectionStart + offset;
                double castPlaneDistanceToRayStart = DistanceFromCharacterPlane(ref rayStart);
                rayStart -= castPlaneDistanceToRayStart * MyCubeBuilder.IntersectionDirection;

                Vector3D rayEnd = MyCubeBuilder.IntersectionStart + (m_dragDistance - castPlaneDistanceToRayStart) * MyCubeBuilder.IntersectionDirection + offset;
                MatrixD matrix = gridWorlTransform;
                matrix.Translation = rayStart;

                try
                {
                    float? dist = MyPhysics.CastShape(rayEnd, shape, ref matrix, MyPhysics.CollisionLayerWithoutCharacter);
                    if (dist.HasValue && dist.Value != 0f)
                    {
                        Vector3D intersectionPoint = rayStart + dist.Value * (rayEnd - rayStart);

                        const bool debugDraw = true;
                        if (debugDraw)
                        {
                            Color green = Color.Green;
                            BoundingBoxD localAABB = new BoundingBoxD(-halfExt, halfExt);
                            localAABB.Inflate(0.03f);
                            MatrixD drawMatrix = matrix;
                            drawMatrix.Translation = intersectionPoint;
                            MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix, ref localAABB, ref green, MySimpleObjectRasterizer.Wireframe, 1, 0.04f);
                        }

                        double fixedDistance = DistanceFromCharacterPlane(ref intersectionPoint) - castPlaneDistanceToRayStart;
                        if (fixedDistance <= 0)
                        {
                            fixedDistance = 0;
                            shortestDistance = 0;
                            buildAllowed = false;
                            break;
                        }

                        if (fixedDistance < shortestDistance)
                            shortestDistance = fixedDistance;
                    }
                    else
                    {
                        buildAllowed = false;
                    }
                }
                finally
                {
                    shape.RemoveReference();
                }

            }

            if (shortestDistance != 0 && shortestDistance < m_dragDistance)
                freePlacementIntersectionPoint = MyCubeBuilder.IntersectionStart + shortestDistance * MyCubeBuilder.IntersectionDirection;
            else
                buildAllowed = false;

            return freePlacementIntersectionPoint;
        }
예제 #30
0
        protected void UpdateRenderObject()
        {
            m_actualWorldAABB = BoundingBoxD.CreateInvalid();

            if (AnimationController.CharacterBones != null)
            for (int i = 1; i < Model.Bones.Length; i++)
            {
                Vector3D p1 = Vector3D.Transform(AnimationController.CharacterBones[i].Parent.AbsoluteTransform.Translation, WorldMatrix);
                Vector3D p2 = Vector3D.Transform(AnimationController.CharacterBones[i].AbsoluteTransform.Translation, WorldMatrix);

                m_actualWorldAABB.Include(ref p1);
                m_actualWorldAABB.Include(ref p2);
            }

            ContainmentType containmentType;
            m_aabb.Contains(ref m_actualWorldAABB, out containmentType);
            if (containmentType != ContainmentType.Contains)
            {
                m_actualWorldAABB.Inflate(0.5f);
                MatrixD worldMatrix = WorldMatrix;
                VRageRender.MyRenderProxy.UpdateRenderObject(Render.RenderObjectIDs[0], ref worldMatrix, false, m_actualWorldAABB);
                m_aabb = m_actualWorldAABB;
            }
        }
        /// <summary>
        /// Writes all surrounding blocks around the given one with the given size.
        /// </summary>
        private void GetSurroundingBlocksFromStaticGrids(MySlimBlock block, MyCubeSize cubeSizeEnum, HashSet <MySlimBlock> outBlocks)
        {
            outBlocks.Clear();

            BoundingBoxD aabbForNeighbors = new BoundingBoxD(block.Min * block.CubeGrid.GridSize, block.Max * block.CubeGrid.GridSize);
            BoundingBoxD aabb             = new BoundingBoxD(block.Min * block.CubeGrid.GridSize - block.CubeGrid.GridSize / 2, block.Max * block.CubeGrid.GridSize + block.CubeGrid.GridSize / 2);

            if (block.FatBlock != null)
            {
                var aabbCenter = aabb.Center;
                aabb = (BoundingBoxD)block.FatBlock.Model.BoundingBox;
                Matrix m;
                block.FatBlock.Orientation.GetMatrix(out m);
                aabb = aabb.TransformFast(m);
                aabb.Translate(aabbCenter);
            }

            aabb.Inflate(0.125);
            var aabbWorld = aabb.TransformFast(block.CubeGrid.WorldMatrix);

            List <MyEntity> boxOverlapList = new List <MyEntity>();

            MyEntities.GetElementsInBox(ref aabbWorld, boxOverlapList);

            for (int i = 0; i < boxOverlapList.Count; i++)
            {
                var cubeGrid = boxOverlapList[i] as MyCubeGrid;
                if (cubeGrid != null)
                {
                    if (cubeGrid.IsStatic && cubeGrid != block.CubeGrid && cubeGrid.EnableSmallToLargeConnections && cubeGrid.SmallToLargeConnectionsInitialized &&
                        cubeGrid.GridSizeEnum == cubeSizeEnum)
                    {
                        Debug.Assert(m_tmpSlimBlocksList.Count == 0);
                        m_tmpSlimBlocksList.Clear();
                        cubeGrid.GetBlocksIntersectingOBB(aabb, block.CubeGrid.WorldMatrix, m_tmpSlimBlocksList);

                        CheckNeighborBlocks(block, aabbForNeighbors, cubeGrid, m_tmpSlimBlocksList);

                        foreach (var slimBlock in m_tmpSlimBlocksList)
                        {
                            if (slimBlock.FatBlock != null)
                            {
                                if (slimBlock.FatBlock is MyFracturedBlock)
                                {
                                    continue;
                                }

                                if (slimBlock.FatBlock.Components.Has <MyFractureComponentBase>())
                                {
                                    continue;
                                }

                                if (slimBlock.FatBlock is MyCompoundCubeBlock)
                                {
                                    foreach (var blockInCompound in (slimBlock.FatBlock as MyCompoundCubeBlock).GetBlocks())
                                    {
                                        if (!(blockInCompound.FatBlock.Components.Has <MyFractureComponentBase>()))
                                        {
                                            outBlocks.Add(blockInCompound);
                                        }
                                    }
                                }
                                else
                                {
                                    outBlocks.Add(slimBlock);
                                }
                            }
                            else
                            {
                                outBlocks.Add(slimBlock);
                            }
                        }

                        m_tmpSlimBlocksList.Clear();
                    }
                }
            }

            boxOverlapList.Clear();
        }
        private bool TryFindLocationOutsideForestInternal(Vector3D? desiredLocationSize, out Vector3D location, Predicate<AreaData> predicate = null)
        {
            Vector3D desiredHalfSize = desiredLocationSize.HasValue ? desiredLocationSize.Value * 0.5f : Vector3D.Zero;
            desiredHalfSize.Y = 0;

            if (m_highLevelBoxes.Count == 0)
            {
                // no forest on the map, generate starting point
                bool valid = false;
                while (m_initialForestLocations.Count > 0 && !valid)
                {
                    var potentialTreePosition = m_initialForestLocations.Dequeue();
                    valid = true;
                    BoundingBoxD itemBox = new BoundingBoxD(potentialTreePosition, potentialTreePosition);
                    itemBox.Inflate(desiredHalfSize);

                    var entities = MyEntities.GetEntitiesInAABB(ref itemBox);
                    foreach (var entity in entities)
                    {
                        if (entity is MyEnvironmentItems)
                            continue;
                        if (entity is MyVoxelBase)
                            continue;
                        var entityBox = entity.PositionComp.WorldAABB;
                        var containment = entityBox.Intersects(itemBox);
                        if (containment)
                        {
                            valid = false;
                            break;
                        }
                    }
                    entities.Clear();

                    if (valid)
                    {
                        Vector3D end = potentialTreePosition;
                        end.Y -= 20;
                        if (RaycastForExactPosition(potentialTreePosition, end, out location))
                        {
                            d_foundEnlargingPoints.Add(location);
                            return true;
                        }
                        else
                        {
                            valid = false;
                        }
                    }
                }

                location = Vector3D.Zero;
                return false;
            }
            else
            {
                if (!TryGetRandomAreas(m_tmpAreas))
                {
                    location = Vector3D.Zero;
                    return false;
                }

                int areaIdx = 0;
                int randomStartIdx = MyUtils.GetRandomInt(m_tmpAreas.Count);
                while (areaIdx < m_tmpAreas.Count)
                {
                    var spawnArea = m_tmpAreas[randomStartIdx];
                    randomStartIdx = (randomStartIdx + 1) % m_tmpAreas.Count;
                    areaIdx++;

                    if (!spawnArea.IsValid || spawnArea.IsFull)
                        continue;

                    if (predicate != null && !predicate(spawnArea.GetAreaData()))
                    {
                        spawnArea.IsFull = true;
                        continue;
                    }

                    var spawnBox = spawnArea.ForestBox;
                    var forestBox = spawnArea.ForestBox;
                    spawnBox = forestBox.Inflate(desiredHalfSize);
                    spawnBox.Inflate(new Vector3D(0.2, 0, 0.2)); // inflate for some minimum size

                    MyBBSetSampler setSampler = new MyBBSetSampler(spawnBox.Min, spawnBox.Max);
                    setSampler.SubtractBB(ref forestBox);
                    RefineSampler(spawnArea, ref spawnBox, ref desiredHalfSize, setSampler);

                    if (!setSampler.Valid)
                        continue;

                    Vector3D exactLocation;
                    Vector3D samplePosition = setSampler.Sample();
                    if (TryGetExactLocation(spawnArea, samplePosition, 40, out exactLocation))
                    {
                        location = exactLocation;
                        d_foundEnlargingPoints.Add(exactLocation);
                        m_tmpAreas.Clear();
                        return true;
                    }
                    else
                    {
                        location = Vector3D.Zero;
                        m_tmpAreas.Clear();
                        return false;
                    }
                }
            }

            location = Vector3D.Zero;
            m_tmpAreas.Clear();
            return false;
        }
예제 #33
0
 public ulong AddObject(BoundingBoxD bbox, IMyActivationHandler activationHandler, ulong?customId, string tag, long entityId, bool batch)
 {
     using (this.m_clustersLock.AcquireExclusiveUsing())
     {
         BoundingBoxD inflated;
         ulong        num5;
         if (this.SingleCluster.HasValue && (this.m_clusters.Count == 0))
         {
             BoundingBoxD clusterBB = this.SingleCluster.Value;
             clusterBB.Inflate((double)200.0);
             this.CreateCluster(ref clusterBB);
         }
         if (this.SingleCluster.HasValue || this.ForcedClusters)
         {
             inflated = bbox;
         }
         else
         {
             inflated = bbox.GetInflated(MinimumDistanceFromBorder);
         }
         this.m_clusterTree.OverlapAllBoundingBox <MyCluster>(ref inflated, this.m_returnedClusters, 0, true);
         MyCluster cluster = null;
         bool      flag    = false;
         if (this.m_returnedClusters.Count == 1)
         {
             if (this.m_returnedClusters[0].AABB.Contains(inflated) == ContainmentType.Contains)
             {
                 cluster = this.m_returnedClusters[0];
             }
             else if ((this.m_returnedClusters[0].AABB.Contains(inflated) == ContainmentType.Intersects) && activationHandler.IsStaticForCluster)
             {
                 if (this.m_returnedClusters[0].AABB.Contains(bbox) != ContainmentType.Disjoint)
                 {
                     cluster = this.m_returnedClusters[0];
                 }
             }
             else
             {
                 flag = true;
             }
         }
         else if (this.m_returnedClusters.Count > 1)
         {
             if (!activationHandler.IsStaticForCluster)
             {
                 flag = true;
             }
         }
         else if (this.m_returnedClusters.Count == 0)
         {
             if (this.SingleCluster.HasValue)
             {
                 return(ulong.MaxValue);
             }
             if (!activationHandler.IsStaticForCluster)
             {
                 BoundingBoxD xd3 = new BoundingBoxD(bbox.Center - ((Vector3D)(IdealClusterSize / 2f)), bbox.Center + ((Vector3D)(IdealClusterSize / 2f)));
                 this.m_clusterTree.OverlapAllBoundingBox <MyCluster>(ref xd3, this.m_returnedClusters, 0, true);
                 if (this.m_returnedClusters.Count == 0)
                 {
                     this.m_staticTree.OverlapAllBoundingBox <ulong>(ref xd3, m_objectDataResultList, 0, true);
                     cluster = this.CreateCluster(ref xd3);
                     foreach (ulong num in m_objectDataResultList)
                     {
                         if (this.m_objectsData[num].Cluster == null)
                         {
                             this.AddObjectToCluster(cluster, num, false);
                         }
                     }
                 }
                 else
                 {
                     flag = true;
                 }
             }
         }
         ulong        objectId = customId.HasValue ? customId.Value : num5;
         int          num3     = -1;
         MyObjectData data     = new MyObjectData {
             Id                = objectId,
             Cluster           = cluster,
             ActivationHandler = activationHandler,
             AABB              = bbox,
             StaticId          = num3,
             Tag               = tag,
             EntityId          = entityId
         };
         this.m_objectsData[objectId] = data;
         if ((flag && !this.SingleCluster.HasValue) && !this.ForcedClusters)
         {
             this.ReorderClusters(bbox, objectId);
             bool isStaticForCluster = this.m_objectsData[objectId].ActivationHandler.IsStaticForCluster;
         }
         if (activationHandler.IsStaticForCluster)
         {
             num3 = this.m_staticTree.AddProxy(ref bbox, objectId, 0, true);
             this.m_objectsData[objectId].StaticId = num3;
         }
         if (cluster != null)
         {
             return(this.AddObjectToCluster(cluster, objectId, batch));
         }
         return(objectId);
     }
 }
예제 #34
0
        private Vector3D?FindSuitableJumpLocation(Vector3D desiredLocation)
        {
            BoundingBoxD shipBBox = GetAggregateBBox();

            // 1 Km distante to other objects to prevent spawning in bases
            shipBBox.Inflate(1000f);

            BoundingBoxD regionBBox = shipBBox.GetInflated(shipBBox.HalfExtents * 10);

            regionBBox.Translate(desiredLocation - regionBBox.Center);


            MyProceduralWorldGenerator.Static.OverlapAllPlanetSeedsInSphere(new BoundingSphereD(regionBBox.Center, regionBBox.HalfExtents.AbsMax()), m_objectsInRange);
            Vector3D currentSearchPosition = desiredLocation;

            foreach (var planet in m_objectsInRange)
            {
                if (planet.BoundingVolume.Contains(currentSearchPosition) != ContainmentType.Disjoint)
                {
                    Vector3D v = currentSearchPosition - planet.BoundingVolume.Center;
                    v.Normalize();
                    v *= planet.BoundingVolume.HalfExtents * 1.5;
                    currentSearchPosition = planet.BoundingVolume.Center + v;
                    break;
                }
            }
            m_objectsInRange.Clear();

            MyProceduralWorldGenerator.Static.OverlapAllAsteroidSeedsInSphere(new BoundingSphereD(regionBBox.Center, regionBBox.HalfExtents.AbsMax()), m_objectsInRange);
            foreach (var asteroid in m_objectsInRange)
            {
                m_obstaclesInRange.Add(asteroid.BoundingVolume);
            }
            m_objectsInRange.Clear();

            MyGamePruningStructure.GetTopMostEntitiesInBox(ref regionBBox, m_entitiesInRange);

            // Inflate the obstacles so we only need to check the center of the ship for collisions
            foreach (var entity in m_entitiesInRange)
            {
                if (!(entity is MyPlanet))
                {
                    m_obstaclesInRange.Add(entity.PositionComp.WorldAABB.GetInflated(shipBBox.HalfExtents));
                }
            }

            int maxStepCount = 10;
            int stepCount    = 0;

            // When we collide with an obsticle, we add it here
            BoundingBoxD?aggregateCollidedObstacles = null;
            bool         obstructed = false;
            bool         found      = false;

            while (stepCount < maxStepCount)
            {
                stepCount++;
                obstructed = false;
                foreach (var obstacle in m_obstaclesInRange)
                {
                    var contains = obstacle.Contains(currentSearchPosition);
                    if (contains == ContainmentType.Contains ||
                        contains == ContainmentType.Intersects)
                    {
                        if (!aggregateCollidedObstacles.HasValue)
                        {
                            aggregateCollidedObstacles = obstacle;
                        }
                        aggregateCollidedObstacles = aggregateCollidedObstacles.Value.Include(obstacle);
                        aggregateCollidedObstacles = aggregateCollidedObstacles.Value.Inflate(1.0);
                        currentSearchPosition      = ClosestPointOnBounds(aggregateCollidedObstacles.Value, currentSearchPosition);
                        obstructed = true;
                        break;
                    }
                }

                if (!obstructed)
                {
                    // No obstacle found, return current search position
                    found = true;
                    break;
                }
            }

            m_obstaclesInRange.Clear();
            m_entitiesInRange.Clear();
            m_objectsInRange.Clear();

            if (found)
            {
                return(currentSearchPosition);
            }
            else
            {
                return(null);
            }
        }