private void AddEntity(MySolarSystemMapData data, Vector3 posMillKm, float radiusMillKm, string name, MySolarSystemEntityEnum entityType, Color color, object entityData = null)
 {
     float radius = radiusMillKm * MyBgrCubeConsts.MILLION_KM;
     Vector3 offset;
     MyMwcVector3Int sector = MySolarSystemUtils.MillionKmToSectors(posMillKm, out offset);
     var entity = new MySolarSystemMapEntity(sector, offset, radius, name, entityType, color);
     entity.EntityData = entityData;
     data.Entities.Add(entity);
 }
        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 DrawSunDebug(MySolarSystemMapEntity entity)
 {
     Matrix world = Matrix.CreateScale(KmToGameUnits(entity.Radius));
     MyDebugDraw.DrawSphereWireframe(world, Color.Yellow.ToVector3(), 1.0f);
 }
        void AddAsteroid(MySolarSystemMapEntity entity)
        {
            Vector3 pos = EntityPosition(entity, m_currentCamera);
            float radius = KmToGameUnits(entity.Radius);
            
            float dist = GameUnitsToKm((pos).Length());
            
            const float dist1km = 3000;
            float distForSize = entity.Radius * dist1km;

            const float dist1kmBlendStart = 2000;
            float distForSizeBlendStart = entity.Radius * dist1kmBlendStart;
            
            if (dist > distForSize || dist < minDistFromCamera)
            {
                //return;
            }

            float alpha = MathHelper.Clamp(1 - ((dist - distForSizeBlendStart) / (distForSize - distForSizeBlendStart)), 0, 1);

            float distToTarget = (pos - m_currentCamera.CameraToTarget).Length();
            alpha *= CalculateBlend(SectorToGameUnits(SECTOR_RENDER_HALFSIZE), SectorToGameUnits(1), distToTarget);

            if (alpha <= float.Epsilon)
            {
                return;
            }

            float asteroidSize = radius / MySolarSystemMapCamera.SECTOR_SIZE_GAMEUNITS / 2 + 0.01f;
            AddIcon(pos, asteroidSize / 10000, MyTransparentMaterialEnum.SolarMapAsteroid, new Vector4(Vector3.One * alpha, alpha), null, null, 0.0001f, false, Vector3.Zero);

            double absY = pos.Y + m_currentCamera.Position.Y + m_currentCamera.PositionSector.Y * MySolarSystemMapCamera.SECTOR_SIZE_GAMEUNITS;

            Vector4 color = Vector4.One;
            if (absY < 0)
            {
                color = Color.Brown.ToVector4();
            }

            // Make alpha to power of 2 to make lines fade better
            alpha *= alpha;
            color *= alpha;
            color.W = alpha;

            if (absY != 0)
            {
                AddLineBillboardUnscaling(MyTransparentMaterialEnum.SolarMapZeroPlaneLine, color, pos, Vector3.Up, Math.Abs((float)-absY), 0.002f, 0);
            }
        }
        void AddFactionInfo(MySolarSystemMapEntity entity)
        {
            Vector3 pos = EntityPosition(entity, m_currentCamera);
            const float radius = 20; // hard coded radius

            MyTransparentMaterialEnum texture = (MyTransparentMaterialEnum)entity.EntityData;

            AddIcon(pos, radius, texture, entity.Color, entity.Name, null, 0.7f, false, new Vector3(0,1,0));
        }
        void AddFactionMap(MySolarSystemMapEntity entity)
        {
            Vector3 pos = EntityPosition(entity, m_currentCamera);
            float radius = KmToGameUnits(entity.Radius);

            float height = Math.Abs(pos.Y);
            float lower = 2 * MySolarSystemMapCamera.SECTOR_SIZE_GAMEUNITS;
            float upper = 1000 * MySolarSystemMapCamera.SECTOR_SIZE_GAMEUNITS;
            float blend = CalculateBlend(lower, upper, height);

            //pos.Y = 0; // MillionKmToGameUnits(0.1f);
            Vector4 c = entity.Color.ToVector4();
            c.W = blend;
            c *= c.W;
            c.W *= 0.5f;
            MyTransparentGeometry.AddBillboardOriented(MyTransparentMaterialEnum.SolarMapFactionMap, c, pos, Vector3.Forward, Vector3.Left, radius, -3);
        }
 void AddDustField(MySolarSystemMapEntity entity)
 {
     Vector3 pos = EntityPosition(entity, m_currentCamera);
     float radius = KmToGameUnits(entity.Radius);
     
     MyTransparentGeometry.AddBillboardOriented(MyTransparentMaterialEnum.SolarMapDust, entity.Color.ToVector4() * 0.3f, pos, m_currentCamera.Up, m_currentCamera.Left, radius, -2, true);
 }
        void AddAsteroidField(MySolarSystemMapEntity entity)
        {
            Vector3 areaPos = EntityPosition(entity, m_currentCamera);
            float areaRadius = KmToGameUnits(entity.Radius);

            float blendSizeLower = SectorToGameUnits(10000);
            float blendSizeUpper = SectorToGameUnits(150000);
            float minAsteroidFieldDist = SectorToGameUnits(20000);
            float maxAsteroidFieldDist = SectorToGameUnits(200000);

            // Size of billboards in fraction of whole size
            const float billboardSizeRatio = 0.2f;
            const int billboardsPerAsteroidField = 25;

            float radius = billboardSizeRatio * areaRadius;

            Random rnd = new Random(entity.Sector.X ^ entity.Sector.Y ^ entity.Sector.Z ^ (int)entity.PositionInSector.X ^ (int)entity.PositionInSector.Y ^ (int)entity.PositionInSector.Z);

            for (int i = 0; i < billboardsPerAsteroidField; i++)
            {
                Vector3 dir = rnd.Direction();
                float maxDist = areaRadius - radius;
                Vector3 pos = areaPos + dir * maxDist;
                float dist = pos.Length();

                float alphaLower = CalculateBlend(minAsteroidFieldDist, minAsteroidFieldDist + blendSizeLower, dist);
                float alphaUpper = 1 - CalculateBlend(maxAsteroidFieldDist, maxAsteroidFieldDist + blendSizeUpper, dist);
                float alpha = alphaLower * alphaUpper;
                if (alpha < float.Epsilon)
                {
                    return;
                }
                Vector4 color = entity.Color.ToVector4();
                color *= alpha;
                //color.W = alpha;
                
                /*if (dist < minAsteroidFieldDist || dist > maxAsteroidFieldDist)
                {
                    return;
                }*/

                MyTransparentGeometry.AddBillboardOriented(MyTransparentMaterialEnum.SolarMapAsteroidField, color, pos, m_currentCamera.Up, m_currentCamera.Left, radius, -2);
            }
        }
 private void AddOutpost(MySolarSystemMapEntity entity)
 {
     Vector3 pos = EntityPosition(entity, m_currentCamera);
     const float radius = 30;
     AddIcon(pos, radius, MyTransparentMaterialEnum.SolarMapOutpost, Color.White, entity.Name, null, 1000, false, Vector3.Zero);
 }
        void AddSun(MySolarSystemMapEntity entity)
        {
            // Size of billboard is 2.85x bigger than sun in it's center
            const float billboardSizeRatio = 1.85f;

            Vector3 pos = EntityPosition(entity, m_currentCamera);

            // Sun billboard size won't decrease when further than 150 million km
            float sunDistanceMinSize = MillionKmToGameUnits(150);
            AddPointBillboardUnscalingFromDistance(MyTransparentMaterialEnum.SolarMapSun, Vector4.One, pos, KmToGameUnits(entity.Radius) * billboardSizeRatio, 0, sunDistanceMinSize, 0, false);
            AddText(pos, entity.Name, MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_TOP, 0.6f, Color.Yellow, MyGuiManager.GetFontMinerWarsWhite());
        }
 static Vector3 EntityPosition(MySolarSystemMapEntity entity, MySolarSystemMapCamera camera)
 {
     return EntityPosition(entity.Sector, entity.PositionInSector, camera);            
 }