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); } }
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); } }
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); } }