public SectorTreeComponent(MyPlanetsDebugInputComponent comp)
            {
                Size = Radius * Math.Sqrt(2);
                double sectorSize = 64;

                m_comp = comp;

                m_tree = new My2DClipmap <DebugDrawHandler> [6];

                for (m_activeClipmap = 0; m_activeClipmap < m_tree.Length; m_activeClipmap++)
                {
                    var forward = Base6Directions.Directions[m_activeClipmap];

                    var up = Base6Directions.Directions[(int)Base6Directions.GetPerpendicular((Base6Directions.Direction)m_activeClipmap)];

                    // Forward is -z so it inverts the orientation of the map which we do not want.
                    MatrixD wm = MatrixD.CreateFromDir(-forward, up);

                    wm.Translation = (Vector3D)forward * Size / 2;

                    m_tree[m_activeClipmap] = new My2DClipmap <DebugDrawHandler>();
                    m_tree[m_activeClipmap].Init(this, ref wm, sectorSize, Size);
                }

                AddShortcut(MyKeys.NumPad8, true, false, false, false, () => "Toggle clipmap update", () => m_update = !m_update);
            }
        public void InitEnvironment()
        {
            EnvironmentDefinition = Planet.Generator.EnvironmentDefinition;

            PlanetTranslation = Planet.WorldMatrix.Translation;

            m_InstanceHash = Planet.GetInstanceHash();

            double radius    = Planet.AverageRadius;
            double faceSize  = radius * Math.Sqrt(2);
            double faceSize2 = faceSize / 2;

            double sectorSize = EnvironmentDefinition.SectorSize;

            // Prepare each clipmap
            for (int i = 0; i < 6; ++i)
            {
                // get forward and up
                Vector3D forward, up;
                MyPlanetCubemapHelper.GetForwardUp((Base6Directions.Direction)i, out forward, out up);

                var translation = forward * faceSize2 + PlanetTranslation;

                forward = -forward;

                // prepare matrix
                MatrixD worldMatrix;
                MatrixD.CreateWorld(ref translation, ref forward, ref up, out worldMatrix);

                // Setup origins
                Vector3D origin = new Vector3D(-faceSize2, -faceSize2, 0);
                Vector3D.Transform(ref origin, ref worldMatrix, out origin);

                // Basis vectors
                Vector3D basisX = new Vector3D(1, 0, 0), basisY = new Vector3D(0, 1, 0);
                Vector3D.RotateAndScale(ref basisX, ref worldMatrix, out basisX);
                Vector3D.RotateAndScale(ref basisY, ref worldMatrix, out basisY);

                // Create and init the clipmap.
                m_clipmaps[i] = new My2DClipmap <MyPlanetEnvironmentClipmapProxy>();
                ActiveClipmap = m_clipmaps[i];
                ActiveFace    = i;

                m_clipmaps[i].Init(this, ref worldMatrix, sectorSize, faceSize);
                ActiveFace = -1;

                // Prepare the provider for the face
                var provider = new MyProceduralEnvironmentProvider {
                    ProviderId = i
                };

                provider.Init(this, ref origin, ref basisX, ref basisY, ActiveClipmap.LeafSize, m_providerData[i]);

                Providers[i] = provider;
            }
        }
        private void UpdateClipmaps()
        {
            // This avoids the clipmap from overruning and going bad
            if (m_sectorsToWorkParallel.Count > 0)
            {
                return;
            }

            Vector3D camera = MySector.MainCamera.Position - PlanetTranslation;

            double distance = camera.Length();

            // Update only if relevant
            if (distance > Planet.AverageRadius + m_clipmaps[0].FaceHalf && Proxies.Count == 0)
            {
                return;
            }

            distance = Math.Abs(Planet.Provider.Shape.GetDistanceToSurfaceCacheless(camera));

            // Get cubemap coordinates
            Vector2D texcoords;
            int      direction;

            MyPlanetCubemapHelper.ProjectToCube(ref camera, out direction, out texcoords);

            // Update each clipmap accordingly.
            for (int face = 0; face < 6; ++face)
            {
                ActiveFace    = face;
                ActiveClipmap = m_clipmaps[face];

                Vector2D localCoords;
                MyPlanetCubemapHelper.TranslateTexcoordsToFace(ref texcoords, direction, face, out localCoords);

                Vector3D pos;
                pos.X = localCoords.X * ActiveClipmap.FaceHalf;
                pos.Y = localCoords.Y * ActiveClipmap.FaceHalf;

                if ((face ^ direction) == 1)
                {
                    pos.Z = distance + Planet.AverageRadius * 2;
                }
                else
                {
                    pos.Z = distance;
                }

                //pos.Z = 0;

                ActiveClipmap.Update(pos);
                EvaluateOperations(); // Enqueue operations from this clipmap.
            }

            ActiveFace = -1;
        }
        public void CloseAll()
        {
            m_parallelSyncPoint.Reset();

            // Clear physics
            foreach (var sector in PhysicsSectors.Values)
            {
                sector.EnablePhysics(false);

                if (sector.LodLevel == -1 && !sector.IsPendingLodSwitch)
                {
                    m_sectorsClosing.Add(sector);
                }
            }
            m_sectorsWithPhysics.Clear();

            // Clear graphics
            for (int index = 0; index < m_clipmaps.Length; index++)
            {
                ActiveFace = index;
                (ActiveClipmap = m_clipmaps[index]).Clear();
                EvaluateOperations();
            }

            ActiveFace    = -1;
            ActiveClipmap = null;

            foreach (var sector in m_sectorsClosing)
            {
                if (sector.HasParallelWorkPending)
                {
                    sector.DoParallelWork();
                }

                if (sector.HasSerialWorkPending)
                {
                    sector.DoSerialWork();
                }

                sector.Close();
            }

            m_sectorsClosing.Clear();
            m_sectorsToWorkParallel.Clear();
            m_sectorsToWorkSerial.Clear();

            m_parallelSyncPoint.Set();
        }
        public void InitEnvironment()
        {
            EnvironmentDefinition = Planet.Generator.EnvironmentDefinition;

            PlanetTranslation = Planet.WorldMatrix.Translation;

            m_InstanceHash = Planet.GetInstanceHash();

            double radius = Planet.AverageRadius;
            double faceSize = radius * Math.Sqrt(2);
            double faceSize2 = faceSize / 2;

            double sectorSize = EnvironmentDefinition.SectorSize;

            // Prepare each clipmap
            for (int i = 0; i < 6; ++i)
            {
                // get forward and up
                Vector3D forward, up;
                MyPlanetCubemapHelper.GetForwardUp((Base6Directions.Direction)i, out forward, out up);

                var translation = forward * faceSize2 + PlanetTranslation;

                forward = -forward;

                // prepare matrix
                MatrixD worldMatrix;
                MatrixD.CreateWorld(ref translation, ref forward, ref up, out worldMatrix);

                // Setup origins
                Vector3D origin = new Vector3D(-faceSize2, -faceSize2, 0);
                Vector3D.Transform(ref origin, ref worldMatrix, out origin);

                // Basis vectors
                Vector3D basisX = new Vector3D(1, 0, 0), basisY = new Vector3D(0, 1, 0);
                Vector3D.RotateAndScale(ref basisX, ref worldMatrix, out basisX);
                Vector3D.RotateAndScale(ref basisY, ref worldMatrix, out basisY);

                // Create and init the clipmap.
                m_clipmaps[i] = new My2DClipmap<MyPlanetEnvironmentClipmapProxy>();
                ActiveClipmap = m_clipmaps[i];
                ActiveFace = i;

                m_clipmaps[i].Init(this, ref worldMatrix, sectorSize, faceSize);
                ActiveFace = -1;

                // Prepare the provider for the face
                var provider = new MyProceduralEnvironmentProvider { ProviderId = i };

                provider.Init(this, ref origin, ref basisX, ref basisY, ActiveClipmap.LeafSize, m_providerData[i]);

                Providers[i] = provider;
            }
        }
        private void UpdateClipmaps()
        {
            // This avoids the clipmap from overruning and going bad
            if (m_sectorsToWorkParallel.Count > 0) return;

            Vector3D camera = MySector.MainCamera.Position - PlanetTranslation;

            double distance = camera.Length();

            // Update only if relevant
            if (distance > Planet.AverageRadius + m_clipmaps[0].FaceHalf && Proxies.Count == 0)
            {
                return;
            }

            distance = Math.Abs(Planet.Provider.Shape.GetDistanceToSurfaceCacheless(camera));

            // Get cubemap coordinates
            Vector2D texcoords;
            int direction;
            MyPlanetCubemapHelper.ProjectToCube(ref camera, out direction, out texcoords);

            // Update each clipmap accordingly.
            for (int face = 0; face < 6; ++face)
            {
                ActiveFace = face;
                ActiveClipmap = m_clipmaps[face];

                Vector2D localCoords;
                MyPlanetCubemapHelper.TranslateTexcoordsToFace(ref texcoords, direction, face, out localCoords);

                Vector3D pos;
                pos.X = localCoords.X * ActiveClipmap.FaceHalf;
                pos.Y = localCoords.Y * ActiveClipmap.FaceHalf;

                if ((face ^ direction) == 1)
                    pos.Z = distance + Planet.AverageRadius * 2;
                else
                    pos.Z = distance;

                //pos.Z = 0;

                ActiveClipmap.Update(pos);
                EvaluateOperations(); // Enqueue operations from this clipmap.
            }

            ActiveFace = -1;
        }
        public void CloseAll()
        {
            m_parallelSyncPoint.Reset();

            // Clear physics
            foreach (var sector in PhysicsSectors.Values)
            {
                sector.EnablePhysics(false);

                if (sector.LodLevel == -1 && !sector.IsPendingLodSwitch)
                    m_sectorsClosing.Add(sector);
            }
            m_sectorsWithPhysics.Clear();

            // Clear graphics
            for (int index = 0; index < m_clipmaps.Length; index++)
            {
                ActiveFace = index;
                (ActiveClipmap = m_clipmaps[index]).Clear();
                EvaluateOperations();
            }

            ActiveFace = -1;
            ActiveClipmap = null;

            foreach (var sector in m_sectorsClosing)
            {
                if (sector.HasParallelWorkPending)
                    sector.DoParallelWork();

                if (sector.HasSerialWorkPending)
                    sector.DoSerialWork();

                sector.Close();
            }

            m_sectorsClosing.Clear();
            m_sectorsToWorkParallel.Clear();
            m_sectorsToWorkSerial.Clear();

            m_parallelSyncPoint.Set();
        }