예제 #1
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);
     }
 }
예제 #2
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);
            }
        }
예제 #3
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);
            }
        }