private static IEnumerable<MyObjectInfo> GetAsteroids(MySectorObjectCounts asteroidCounts, float entityMinimalSize)
 {
     var asteroids = asteroidCounts.AllObjects.Where(s => s.SizeInMeters > entityMinimalSize);
     return asteroids;
 }
        private void AddSectorEntities(MySectorObjectCounts asteroidCounts, MyMwcVector3Int sectorPosition, Random random, float entityMinimalSize, int maxEntityCount,  List<MySolarSystemMapEntity> entities, bool onlyStaticAsteroids)
        {
                      
            // Space around asteroid should be at least 1.2x - 2x it's size
            float asteroidSpacingCoeficient = 0.7f;

            // Asteroid count mean is 40%
            float asteroidCountMean = 0.4f;

            Dictionary<int, int> entityCounts = new Dictionary<int, int>();
            foreach (MySolarSystemEntityEnum t in Enum.GetValues(typeof(MySolarSystemEntityEnum)))
            {
                entityCounts.Add((int)t, 0);
            }

            MyDynamicAABBTree prunningStructure = new MyDynamicAABBTree(Vector3.Zero);

            foreach (BoundingSphere boundingSphere in m_safeAreas)
            {
                BoundingBox bb = BoundingBox.CreateFromSphere(boundingSphere);
                prunningStructure.AddProxy(ref bb, new Render.MyRenderObject(null, null), 0);
            }


            // Generate asteroids, check collisions (order asteroids by size)
            //var asteroids = GetAsteroids(asteroidCounts, entityMinimalSize);
            var asteroids = GetAsteroids(asteroidCounts, entityMinimalSize);

            foreach (var info in asteroids)
            {
                if (info.EntityType != MySolarSystemEntityEnum.StaticAsteroid && onlyStaticAsteroids)
                    continue;

                float radius = info.SizeInMeters / 2;
                float count = info.ObjectCount;
                float positionOffset = 1.3f;
                count = (float)Math.Round(count * random.Float(1 - asteroidCountMean, 1 + asteroidCountMean));

                if (info.EntityType == MySolarSystemEntityEnum.VoxelAsteroid)
                {
                    positionOffset = 0.6f; //generate voxels more in center
                }

                while (entityCounts[(int)info.EntityType] < count && entityCounts[(int)info.EntityType] < maxEntityCount)
                {
                    Vector3? pos = FindEntityPosition(prunningStructure, random, radius, positionOffset, asteroidSpacingCoeficient);

                    if (pos.HasValue)
                    {
                        MySolarSystemMapEntity entity = new MySolarSystemMapEntity(sectorPosition, pos.Value, info.SizeInMeters, info.EntityType.ToString(), info.EntityType);
                        entities.Add(entity);

                        if (!MySectorGenerator.IsOutsideSector(pos.Value, radius))
                        {
                            entityCounts[(int)info.EntityType]++;
                        }
                        
                        BoundingBox bb = new BoundingBox(pos.Value - new Vector3(radius), pos.Value + new Vector3(radius));
                        prunningStructure.AddProxy(ref bb, new Render.MyRenderObject(null, null), 0);
                    }
                    else
                        entityCounts[(int)info.EntityType]++;
                }
            }
        }
 private void EnsureMinimalAsteroidCounts(MySectorObjectCounts asteroidCounts)
 {
     foreach (var pair in MySolarSystemConstants.MinimumObjectsProperties.Values)
     {
         float value;
         if (!asteroidCounts.Values.TryGetValue(pair.Key, out value) || value < pair.Value)
         {
             asteroidCounts.Values[pair.Key] = pair.Value;
         }
     }
 }
 private MySectorObjectCounts ApplyAreaInfluence(MySectorObjectCounts objectCounts, float areaInfluence)
 {
     MySectorObjectCounts result = new MySectorObjectCounts();
     foreach (var item in objectCounts.Values)
     {
         result.Values[item.Key] = item.Value * areaInfluence;
     }
     return result;
 }
        public MyMwcObjectBuilder_Sector GenerateObjectBuilders(MyMwcVector3Int sectorPosition, MySectorObjectCounts sectorObjectCounts, bool onlyStaticAsteroids)
        {
            Random rnd = new Random(m_seed);
            List<MySolarSystemMapEntity> entities = new List<MySolarSystemMapEntity>();
            AddSectorEntities(sectorObjectCounts, sectorPosition, rnd, 0, int.MaxValue, entities, onlyStaticAsteroids);

            List<MyMwcObjectBuilder_Base> sectorObjects = new List<MyMwcObjectBuilder_Base>();

            MyWeightDictionary<MyMwcVoxelMaterialsEnum> primaryMaterials = new MyWeightDictionary<MyMwcVoxelMaterialsEnum>(MySolarSystemConstants.DefaultAsteroidMaterials);
            MyWeightDictionary<MyMwcVoxelMaterialsEnum> secondaryMaterials = new MyWeightDictionary<MyMwcVoxelMaterialsEnum>(MySolarSystemConstants.DefaultSecondaryMaterials);

            GenerateSectorObjectBuildersFromSolarEntities(entities, sectorObjects, rnd, primaryMaterials, secondaryMaterials, sectorObjectCounts.StaticAsteroidTypeset);

            return new MyMwcObjectBuilder_Sector()
            {
                SectorObjects = sectorObjects,
            };
        }
        /// <param name="interpolator">1 means use other object</param>
        public MySectorObjectCounts InterpolateWith(MySectorObjectCounts otherObject, float interpolator)
        {
            var result = new MySectorObjectCounts();
            // This function assumes that both collection contains all types of objects
            foreach (var kv in Values)
            {
                float currentValue = kv.Value;
                float otherValue = otherObject.Values[kv.Key];
                result.Values[kv.Key] = MathHelper.Lerp(currentValue, otherValue, interpolator);
            }

            StaticAsteroidTypeset = interpolator > 0.5f ? StaticAsteroidTypeset : otherObject.StaticAsteroidTypeset;

            return result;
        }