private List <MyEntity> EntitiesInLargeAABB(BoundingBoxD start, BoundingBoxD end)
        {
            Vector3D[] pathPoints = new Vector3D[4];
            pathPoints[0] = start.Min;
            pathPoints[1] = start.Max;
            pathPoints[2] = end.Min;
            pathPoints[3] = end.Max;
            BoundingBoxD PathAABB = BoundingBoxD.CreateFromPoints(pathPoints);

            //m_logger.debugLog("Path AABB = " + PathAABB, "EntitiesInLargeAABB()");

            m_offenders.Clear();
            MyGamePruningStructure.GetTopMostEntitiesInBox(ref PathAABB, m_offenders);
            m_offRemove.Clear();
            for (int i = 0; i < m_offenders.Count; i++)
            {
                if (!collect_Entity(m_grid, m_offenders[i]) ||
                    (m_ignoreEntity != null && m_ignoreEntity == m_offenders[i]))
                {
                    //m_logger.debugLog("discarding: " + m_offenders[i].getBestName(), "EntitiesInLargeAABB()");
                    m_offRemove.Add(m_offenders[i]);
                }
            }
            for (int i = 0; i < m_offRemove.Count; i++)
            {
                m_offenders.Remove(m_offRemove[i]);
            }

            return(m_offenders);
        }
Exemple #2
0
        private HashSet <IMyEntity> EntitiesInLargeAABB(BoundingBoxD start, BoundingBoxD end)
        {
            List <Vector3D> PathPoints = new List <Vector3D>();

            PathPoints.Add(start.Min);
            PathPoints.Add(start.Max);
            PathPoints.Add(end.Min);
            PathPoints.Add(end.Max);
            BoundingBoxD PathAABB = BoundingBoxD.CreateFromPoints(PathPoints);

            myLogger.debugLog("Path AABB = " + PathAABB, "EntitiesInLargeAABB()");

            HashSet <IMyEntity> results = new HashSet <IMyEntity>();

            MyAPIGateway.Entities.GetEntitiesInAABB_Safe_NoBlock(PathAABB, results, collect_Entities);
            return(results);
        }
Exemple #3
0
        /// <summary>
        /// <para>Test for entities intersecting a line segment.</para>
        /// </summary>
        /// <param name="world">Line to test for entities</param>
        /// <param name="pointOfIntersection">the point of contact between Line and intersecting entity</param>
        /// <param name="collect">Ignore entity if function returns false. Not tested against IMyCubeBlock</param>
        /// <param name="collect_CubeBlock">If null, do not ignore any IMyCubeBlock. Ignore IMyCubeBlock if function returns false</param>
        /// <param name="sort">entities will be sorted according to results of this function</param>
        /// <returns>An entity intersecting the Line</returns>
        /// <remarks>
        /// <para>For IMyCubeGrid, if a cell the line passes through is occupied, the cell is considered to be the point of intersection</para>
        /// <para>For entities that are not IMyCubeGrid, Line will be tested against IMyEntity.WorldVolume</para>
        /// </remarks>
        public static IMyEntity EntityOnLine(LineD world, out Vector3D?pointOfIntersection, Func <IMyEntity, bool> collect, Func <IMyCubeBlock, bool> collect_CubeBlock = null, Func <IMyEntity, double> sort = null)
        {
            if (collect == null)
            {
                throw new ArgumentNullException("collect");
            }

            // Get entities in AABB
            Vector3D[]              points         = { world.From, world.To };
            BoundingBoxD            AABB           = BoundingBoxD.CreateFromPoints(points);
            ICollection <IMyEntity> entitiesInAABB = MyAPIGateway.Entities.GetEntitiesInAABB_Safe(ref AABB);

            RayD worldRay = new RayD(world.From, world.Direction);

            if (sort != null)
            {
                SortedDictionary <double, IMyEntity> sortedEntities = new SortedDictionary <double, IMyEntity>();
                foreach (IMyEntity entity in entitiesInAABB)
                {
                    // filter entities
                    if (entity is IMyCubeBlock || !collect(entity))
                    {
                        continue;
                    }

                    sortedEntities.Add(sort(entity), entity);
                }
                entitiesInAABB = sortedEntities.Values;
            }

            foreach (IMyEntity entity in entitiesInAABB)
            {
                if (sort == null)
                {
                    // filter entities
                    if (entity is IMyCubeBlock || !collect(entity))
                    {
                        continue;
                    }
                }

                // ray cast
                IMyCubeGrid entityAsGrid = entity as IMyCubeGrid;
                if (entityAsGrid != null)
                {
                    // TODO: test GetLineIntersectionExact...

                    List <Vector3I> rayCastCells = new List <Vector3I>();
                    entityAsGrid.RayCastCells(world.From, world.To, rayCastCells);                     // I do not know if rayCastCells will be sorted

                    foreach (Vector3I cell in rayCastCells)
                    {
                        IMySlimBlock block = entityAsGrid.GetCubeBlock(cell);
                        if (block == null)
                        {
                            continue;
                        }
                        IMyCubeBlock FatBlock = block.FatBlock;
                        if (FatBlock == null)
                        {
                            pointOfIntersection = entityAsGrid.GridIntegerToWorld(cell);
                            return(entityAsGrid);
                        }
                        else
                        if (collect_CubeBlock == null || collect_CubeBlock(FatBlock))
                        {
                            pointOfIntersection = entityAsGrid.GridIntegerToWorld(cell);
                            return(entityAsGrid);
                        }
                    }
                }
                else
                {
                    double tMin, tMax;
                    if (entity.WorldVolume.IntersectRaySphere(worldRay, out tMin, out tMax))
                    {
                        pointOfIntersection = tMin * worldRay.Direction + worldRay.Position;
                        return(entity);
                    }
                }
            }

            pointOfIntersection = null;
            return(null);
        }
Exemple #4
0
        public unsafe void ScanItems(int targetLod)
        {
            int lodDiff = MinimumScannedLod - targetLod;

            if (lodDiff < 1)
            {
                return;
            }

            int startingLod = MinimumScannedLod - 1;

            int totalItems = m_itemCountTotal;

            int[] localLodOffsets = new int[lodDiff];
            for (int lod = startingLod; lod >= targetLod; --lod)
            {
                int count = m_scanHelper.GetItemsForLod(lod);
                localLodOffsets[lod - targetLod] = totalItems; // Using for cumulative sum
                totalItems += count;
            }

            List <MySurfaceParams> surfaceParams = new List <MySurfaceParams>(totalItems);
            // Step 1: Generate Points
            List <Vector3> points = new List <Vector3>(totalItems);

            /*if (m_environment.ScanningMethod == MyProceduralScanningMethod.Grid)
             * {
             *  // compute non-centric basis for the grid method.
             *  Vector3 start = -BasisX - BasisY;
             *
             *  // has to be per lod otherwise we will have gaps.
             *  for (int lod = startingLod; lod >= targetLod; --lod)
             *  {
             *      int relativeLod = lod - targetLod;
             *      int count = lod > targetLod ? localLodOffsets[relativeLod - 1] - localLodOffsets[relativeLod] : totalItems - localLodOffsets[relativeLod];
             *      float root = (float)Math.Sqrt(count);
             *
             *      int width = (int)Math.Ceiling(root);
             *      int height = (int)Math.Floor(root);
             *
             *      float hrecip = .5f / height;
             *      float wrecip = .5f / width;
             *
             *      Vector3 newBasisX = 2 * BasisX + wrecip;
             *      Vector3 newBasisY = 2 * BasisY + hrecip;
             *
             *      for (int x = 0; x < width; ++x)
             *          for (int y = 0; y < height; ++y)
             *          {
             *              Vector3 pos = start + newBasisX * ((float)x / width) + newBasisY * ((float)y / height);
             *              pos += newBasisX * m_itemPositionRng.NextFloat(-wrecip, wrecip) + newBasisY * m_itemPositionRng.NextFloat(-hrecip, hrecip);
             *              points.Add(pos);
             *          }
             *  }
             * }
             * else*/
            {
                // Random is default
                for (int i = 0; i < m_itemCountTotal; ++i)
                {
                    points.Add(ComputeRandomItemPosition());
                }
            }

            BoundingBoxD box = BoundingBoxD.CreateFromPoints(Bounds);

            // Step 2: Query surface
            Provider.Owner.QuerySurfaceParameters(WorldPos, ref box, points, surfaceParams);

            // Step 3: Select items to spawn
            Items.Capacity = Items.Count + points.Count;

            int locationOffset = 0;
            int itemOffset     = 0;

            fixed(ItemInfo *items = Items.GetInternalArray())
            fixed(MySurfaceParams * parms = surfaceParams.GetInternalArray())
            for (int lod = startingLod; lod >= targetLod; --lod)
            {
                int relativeLod = lod - targetLod;

                // Count of items in this lod
                int count = lod > targetLod ? localLodOffsets[relativeLod - 1] - localLodOffsets[relativeLod] : totalItems - localLodOffsets[relativeLod];

                // Scan those items.
                for (int i = 0; i < count; ++i)
                {
                    //Debug.Assert(itemOffset < points.Count);

                    var definition = GetItemForPosition(ref parms[itemOffset], lod);
                    if (definition != null)
                    {
                        Vector3 up = -parms[itemOffset].Gravity;

                        items[m_totalSpawned].Position   = parms[itemOffset].Position;
                        items[m_totalSpawned].ModelIndex = -1;
                        items[m_totalSpawned].Rotation   = Quaternion.CreateFromForwardUp(GetRandomPerpendicularVector(ref up, parms[itemOffset].Position.GetHashCode()), up);
                        parms[locationOffset++]          = parms[itemOffset];

                        items[m_totalSpawned].DefinitionIndex = definition.Index;

                        var moduled = GetModule(definition);

                        if (moduled != null)
                        {
                            MyLodEnvironmentItemSet set;

                            if (!moduled.ItemsPerDefinition.TryGetValue(definition.Index, out set))
                            {
                                moduled.ItemsPerDefinition[definition.Index] = set = new MyLodEnvironmentItemSet()
                                {
                                    Items = new List <int>()
                                };
                            }

                            set.Items.Add(m_totalSpawned);
                        }

                        m_totalSpawned++;
                        Debug.Assert(m_totalSpawned <= m_itemCountTotal);
                    }
                    itemOffset++;
                }

                ItemCountForLod[lod] = m_totalSpawned;

                foreach (var module in m_modules.Values)
                {
                    if (module == null)
                    {
                        continue;
                    }
                    //if (module.Module.MaximumLodIndex >= relativeLod)
                    foreach (var def in module.ItemsPerDefinition.Keys.ToArray())
                    {
                        //Debug.Assert(lod <= 15 && lod >= 0);
                        var set = module.ItemsPerDefinition[def];
                        //set.LodOffsets[lod] = set.Items.Count;
                        module.ItemsPerDefinition[def] = set;
                    }
                }
            }

            Items.SetSize(m_totalSpawned);


            // Update modules
            m_scanning = true;
            foreach (var moduleData in m_modules.Values)
            {
                if (moduleData == null)
                {
                    continue;
                }

                moduleData.Module.ProcessItems(moduleData.ItemsPerDefinition, surfaceParams, new[] { 0, 0, 0, 0 }, startingLod, targetLod);
            }
            m_scanning = false;

            MinimumScannedLod = targetLod;
        }