/// <summary>
        /// Zoom in on a planet
        /// </summary>
        public void EnterPlanet(CelestialBody celestialBody)
        {
            controller.zoomed    = celestialBody;
            celestialBody.zoomed = true;
            systemScale.SetActive(false);
            planetScale.SetActive(true);
            Utility.DestroyAllChildren(planetScale.transform);
            var localCopy = GameObject.Instantiate(celestialBody.gameObject, Vector3.zero, Quaternion.identity, planetScale.transform);

            localCopy.name = "Local Copy of " + celestialBody.type.ToString();
            localCopy.transform.localRotation = Quaternion.identity;
            localCopy.transform.localScale    = Vector3.one * controller.planetScaleMultiplier;

            if (celestialBody is DynamicPlanet)
            {
                Utility.DestroyAllChildren(localCopy.transform, "region");
                (celestialBody as DynamicPlanet).regions.ForEach(r => r.Destroy());
            }
            var rings = localCopy.transform.Find("rings");

            if (rings != null)
            {
                PlanetRings.UpdatePlanetRadius(rings.gameObject, celestialBody.radius * controller.planetScaleMultiplier);
            }

            celestialBody.originalGameObject = celestialBody.gameObject;
            celestialBody.gameObject         = localCopy;

            TeleportPlayerIn(celestialBody);
            CopyRelativeCelestials(celestialBody);
            UpdateVolumetricAtmosphere(celestialBody);
        }
        public GameObject InitializePlanet(Planet planet)
        {
            PlanetTextureGenerator texGen   = null;
            GameObject             planetGO = null;

            var planetData = (PlanetData)planet.GetSerializationData();

            switch (planetData.Type)
            {
            case PlanetType.Terra:
                planetGO = Instantiate(_terraPrefab, Vector2.zero, Quaternion.identity);
                texGen   = new Terra(PlanetTextureGenerator.DefaultResolution, planetData);
                break;

            case PlanetType.Gas:
                planetGO = Instantiate(_gasPrefab, Vector2.zero, Quaternion.identity);
                texGen   = new Gas(PlanetTextureGenerator.DefaultResolution, planetData);
                break;

            case PlanetType.Desert:
                planetGO = Instantiate(_desertPrefab, Vector2.zero, Quaternion.identity);
                texGen   = new Desert(PlanetTextureGenerator.DefaultResolution, planetData);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            planetGO.name = planetData.Name;

            var planetTexture = new Texture2D(texGen.XSize, texGen.YSize);

            planetTexture.Resize(texGen.XSize, texGen.YSize, TextureFormat.RGB565, true);
            planetTexture.SetPixels(texGen.TextureColors);
            planetTexture.Apply();

            var meshes = planetGO.GetComponentsInChildren <MeshRenderer>();

            //0 - планета, 1 - облака, 2 - кольца, осторожнее с иерархией в префабе
            meshes[0].material.mainTexture = planetTexture;

            if (planetData.RingsMass > 0)
            {
                var rings        = new PlanetRings(PlanetTextureGenerator.DefaultResolution / 2, planetData);
                var ringsTexture = new Texture2D(rings.XSize, rings.YSize);
                ringsTexture.SetPixels(rings.TextureColors);
                ringsTexture.Apply();

                meshes[2].material.mainTexture = ringsTexture;
            }
            else
            {
                meshes[2].gameObject.SetActive(false);
            }

            planetGO.GetComponentInChildren <PlanetRotator>().RotationSpeed = planetData.RotationSpeed;
            planetGO.AddComponent <PlanetWatcher>().Planet = planet;

            return(planetGO);
        }
        private void UpdateRelativePositions()
        {
            Vector3 player = GetWorldPlayerPosition();

            foreach (var kv in localCopies)
            {
                CelestialBody celestialBody = kv.Key;
                GameObject    copy          = kv.Value;
                CelestialBody zoomed        = controller.zoomed;

                Quaternion inverse = Quaternion.Inverse(zoomed.rotation);
                Shader.SetGlobalVector("_SkyboxRotation", zoomed.rotation.eulerAngles);

                Vector3 planetToPlanet = celestialBody.position - zoomed.position;
                planetToPlanet = inverse * planetToPlanet;

                Vector3 rotatedCelestialBodyPosition = zoomed.position + planetToPlanet;

                Vector3 realDistance    = rotatedCelestialBodyPosition - player;
                float   realMagnitude   = realDistance.magnitude;
                float   v_realMagnitude = Mathf.Clamp((realMagnitude + 2000f) / 14000f, 0, 1); //0 - 1
                v_realMagnitude = Mathf.Pow(v_realMagnitude, .1f);                             //move close objects farther away

                float   newMagnitude = 90000 * v_realMagnitude;                                //max unity coords
                Vector3 newDistance  = realDistance.normalized * newMagnitude;
                float   factor       = newMagnitude / realMagnitude;

                Vector3 relativePos = controller.playerPosition + newDistance;
                celestialBody.relativePosition = relativePos;
                copy.transform.position        = relativePos;
                copy.transform.localScale      = Vector3.one * factor;

                foreach (Transform child in copy.transform)
                {
                    if (child.name == "rings")
                    {
                        PlanetRings.UpdatePlanetRadius(child.gameObject, celestialBody.radius * factor);
                    }
                }

                if (celestialBody.type is CelestialType.Star)
                {
                    Shader.SetGlobalVector("_SunPos", celestialBody.relativePosition);
                    Vector3 from = Vector3.forward;
                    Vector3 to   = Vector3.zero - celestialBody.relativePosition;
                    copy.transform.rotation = Quaternion.FromToRotation(from, to); //Directional Light
                }
            }
        }