internal MyVoxelPhysicsBody(MyVoxelMap voxelMap): base(voxelMap, RigidBodyFlag.RBF_STATIC)
        {
            m_voxelMap = voxelMap;
            Vector3I storageSize = m_voxelMap.Size;
            Vector3I numCels = storageSize >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            m_cellsOffset = m_voxelMap.StorageMin >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;

            HkUniformGridShape shape = new HkUniformGridShape(
                new HkUniformGridShapeArgs()
                {
                    CellsCount = numCels,
                    CellSize = MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_METRES,
                    CellOffset = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF,
                    CellExpand = MyVoxelConstants.VOXEL_SIZE_IN_METRES,
                });
            shape.SetShapeRequestHandler(RequestShapeBlocking);

            CreateFromCollisionObject(shape, -m_voxelMap.SizeInMetresHalf, m_voxelMap.WorldMatrix, collisionFilter: MyPhysics.StaticCollisionLayer);
            shape.Base.RemoveReference();

            if (ENABLE_AABB_PHANTOM)
            {
                m_aabbPhantom = new Havok.HkpAabbPhantom(new BoundingBox(Vector3.Zero, m_voxelMap.SizeInMetres), 0);
                m_aabbPhantom.CollidableAdded = AabbPhantom_CollidableAdded;
                m_aabbPhantom.CollidableRemoved = AabbPhantom_CollidableRemoved;
            }

            if (MyFakes.ENABLE_PHYSICS_HIGH_FRICTION)
                Friction = 0.65f;

            MaterialType = Sandbox.Common.MyMaterialType.ROCK;
        }
 public MyVoxelPrecalcTaskItem(MyLodTypeEnum type, MyVoxelMap voxelMap, MyVoxelGeometry.CellData cache, Vector3I voxelStart)
 {
     Type = type;
     VoxelMap = voxelMap;
     Cache = cache;
     VoxelStart = voxelStart;
 }
 IMyVoxelMap IMyVoxelMaps.CreateVoxelMap(string storageName, IMyStorage storage, Vector3D position,long voxelMapId)
 {
     var voxelMap = new MyVoxelMap();
     voxelMap.EntityId = voxelMapId;
     voxelMap.Init(storageName, storage as Sandbox.Engine.Voxels.IMyStorage, position);
     MyEntities.Add(voxelMap);
     return voxelMap;
 }
        public void CutVoxelMap(MyVoxelMap voxelMap)
        {
            if (voxelMap == null)
                return;

            CopyVoxelMap(voxelMap);
            voxelMap.SyncObject.SendCloseRequest();
            Deactivate();
        }
 public void CopyVoxelMap(MyVoxelMap voxelMap)
 {
     if (voxelMap == null)
         return;
     m_copiedVoxelMaps.Clear();
     m_copiedVoxelMapOffsets.Clear();
     CopyVoxelMapInternal(voxelMap);
     Activate();
 }
 public void Begin(MyVoxelMap voxelMap, ref Vector3I cellCoord)
 {
     VoxelMap = voxelMap;
     CellCoord = cellCoord;
     Center = voxelMap.GetRenderCellPositionAbsolute(ref cellCoord) + MyVoxelConstants.RENDER_CELL_SIZE_IN_METRES_HALF;
     Contains = true;
     m_positionScale = MyVoxelCacheRender.CellVertexPositionScale;
     m_positionOffset = MyVoxelCacheRender.CellVertexPositionOffset(ref cellCoord);
     MyVoxelCacheCellRenderHelper.Begin();
 }
        public MyVoxelNavigationMesh(MyVoxelMap voxelMap, MyNavmeshCoordinator coordinator, Func<long> timestampFunction)
            : base(coordinator.Links, 16, timestampFunction)
        {
            m_voxelMap = voxelMap;
            m_cellSize = m_voxelMap.SizeInMetres / m_voxelMap.Storage.Geometry.CellsCount * (1 << NAVMESH_LOD);

            m_processedCells = new MyVector3ISet();
            m_markedForAddition = new MyVector3ISet();
            m_toAdd = new MyBinaryStructHeap<float, Vector3I>(128);

            m_connectionHelper = new MyVoxelConnectionHelper();
            m_navmeshCoordinator = coordinator;
            m_higherLevel = new MyHighLevelGroup(this, coordinator.HighLevelLinks, timestampFunction);
            m_higherLevelHelper = new MyVoxelHighLevelHelper(this);

            m_debugCellEdges = new Dictionary<ulong, List<DebugDrawEdge>>();

            voxelMap.Storage.RangeChanged += OnStorageChanged;
        }
        public static void PaintInShape(
            MyVoxelMap voxelMap,
            MyShape shape,
            byte materialIdx,
            bool updateSync = false)
        {
            Profiler.Begin("MyVoxelGenerator::PaintInShape()");

            if (voxelMap == null)
            {
                return;
            }

            if (updateSync && Sync.IsServer)
            {
                shape.SendPaintRequest(voxelMap.SyncObject, materialIdx);
            }

            Vector3I minCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMin());
            Vector3I maxCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMax());
            voxelMap.FixVoxelCoord(ref minCorner);
            voxelMap.FixVoxelCoord(ref maxCorner);

            m_cache.Resize(ref minCorner, ref maxCorner);
            voxelMap.Storage.ReadRange(m_cache, false, true, MyVoxelGeometry.GetLodIndex(MyLodTypeEnum.LOD0), ref minCorner, ref maxCorner);

            Vector3I tempVoxelCoord;
            for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++)
            for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++)
            for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++)
            {
                var relPos = tempVoxelCoord - minCorner;
                m_cache.Material(ref relPos, materialIdx); // set material
            }

            Profiler.End();
        }
        public static MyVoxelCacheCellRender GetCell(MyVoxelMap voxelMap, ref Vector3I renderCellCoord, MyLodTypeEnum cellHashType)
        {
            MyVoxelCacheCellRender ret = GetCellFromCache(voxelMap.VoxelMapId, ref renderCellCoord, cellHashType);

            if (ret == null)
            {
                ret = LoadCell(voxelMap, ref renderCellCoord, cellHashType);
            }

            if (ret != null)
            {
                UpdateCell(voxelMap.VoxelMapId, ref renderCellCoord, cellHashType);
            }

            return ret;
        }
        private void RemoveVoxelMap(MyVoxelMap map)
        {
            map.Save = true;
            map.RangeChanged -= m_voxelMap_RangeChangedDelegate;

            if (m_voxelMaps.ContainsKey(map))
            {
                var item = m_voxelMaps[map];
                m_sector.EnableItem(item, false);
                m_voxelMaps.Remove(map);
            }
            else
            {
                Debug.Fail("Voxel map was no longer tracked");
            }
        }
        void InsertVoxelMap()
        {
            MatrixD worldMatrix = MatrixD.CreateWorld(MySector.MainCamera.Position + 25 * MySector.MainCamera.ForwardVector, MySector.MainCamera.ForwardVector, MySector.MainCamera.UpVector);
            //m_voxelMap = MyWorldGenerator.AddAsteroidPrefab("DeformedSphere2_64x64x64", worldMatrix.Translation, "Test");


            string[] vms = new string[]
                {
                    "small_horse_overhang",
                    //"small_largestone",
                    //"small_mediumstone",
                    "small_overhang_flat",
                    //"small_smallstone"
                };


            Matrix wm = Matrix.CreateRotationX(-MathHelper.PiOver2);
            
           // for (int i = 0; i < vms.Length; i++)
            {
             //   wm.Translation = worldMatrix.Translation;

                var name = vms[0];
                var fileName = MyWorldGenerator.GetVoxelPrefabPath(name);
                var storage = Sandbox.Engine.Voxels.MyStorageBase.Load(fileName);
                m_voxelMap = MyWorldGenerator.AddVoxelMap(name, storage, worldMatrix);


                //m_voxelMap = Sandbox.Game.World.MyWorldGenerator.AddAsteroidPrefab(vms[0], worldMatrix, "Test");
                m_voxelMap.IsStaticForCluster = false;
             //   m_voxelMap.WorldMatrix = wm;

               // worldMatrix.Translation += new Vector3D(100, 0, 0);
            }

        }
        private void ChangeClipboardPreview(bool visible)
        {
            if (m_copiedVoxelMaps.Count == 0 || !visible)
            {
                foreach (var voxelMap in m_previewVoxelMaps)
                {
                    MyEntities.EnableEntityBoundingBoxDraw(voxelMap, false);
                    if (m_shouldMarkForClose)
                        voxelMap.Close();
                }
                m_previewVoxelMaps.Clear();
                m_visible = false;
                return;
            }

            MyEntities.RemapObjectBuilderCollection(m_copiedVoxelMaps);

            for (int i = 0; i < m_copiedVoxelMaps.Count; ++i)
            {
                var voxelMapOb = m_copiedVoxelMaps[i];
                var storage = m_copiedStorages[i];

                MyVoxelBase previewVoxelMap = null;

                if (voxelMapOb is MyObjectBuilder_VoxelMap)
                {
                    previewVoxelMap = new MyVoxelMap();
                }
                if (voxelMapOb is MyObjectBuilder_Planet)
                {
                    m_planetMode = true;
                    IsActive = visible;
                    m_visible = visible;
                    continue;
                }

                var pos = voxelMapOb.PositionAndOrientation.Value.Position;
                previewVoxelMap.Init(voxelMapOb, storage);
                previewVoxelMap.BeforePaste();

                DisablePhysicsRecursively(previewVoxelMap);
                MakeTransparent(previewVoxelMap);
                MyEntities.Add(previewVoxelMap);
                previewVoxelMap.PositionLeftBottomCorner = m_pastePosition - previewVoxelMap.Storage.Size * 0.5f;
                previewVoxelMap.PositionComp.SetPosition(m_pastePosition);
                previewVoxelMap.Save = false;

                m_previewVoxelMaps.Add(previewVoxelMap);

                IsActive = visible;
                m_visible = visible;
                m_shouldMarkForClose = true;
            }


        }
        private void OnCutAsteroidConfirm(MyVoxelMap targetVoxelMap)
        {
            Debug.Assert(targetVoxelMap != null);

            //Check if entity wasn't deleted by someone else during waiting
            if (MyEntities.EntityExists(targetVoxelMap.EntityId))
            {
                DeactivateCopyPaste(true);
                DeactivateCopyPasteFloatingObject(true);
                targetVoxelMap.SyncObject.SendCloseRequest();
            }
        }
        public static MyVoxelMap AddVoxelMap(string storageName, MyStorageBase storage, MatrixD worldMatrix, long entityId=0, bool lazyPhysics = false)
        {
            ProfilerShort.Begin("AddVoxelMap");

            var voxelMap = new MyVoxelMap();
            if (entityId != 0)
            {
                voxelMap.EntityId = entityId;
            }
            voxelMap.DelayRigidBodyCreation = lazyPhysics;
            voxelMap.Init(storageName, storage, worldMatrix);
            MyEntities.Add(voxelMap);
            MyEntities.RaiseEntityCreated(voxelMap);

            ProfilerShort.End();
            return voxelMap;
        }
        public static void FillInShape(
            MyVoxelMap voxelMap,
            MyShape shape,
            out float voxelsCountInPercent,
            byte materialIdx,
            float fillRatio = 1,
            bool updateSync = false,
            bool onlyCheck = false)
        {
            Profiler.Begin("MyVoxelGenerator::FillInShape()");

            if (voxelMap == null)
            {
                voxelsCountInPercent = 0f;
                return;
            }

            if (updateSync && Sync.IsServer)
            {
                shape.SendFillRequest(voxelMap.SyncObject, materialIdx, fillRatio);
            }

            int originalSum = 0;
            int filledSum   = 0;

            Vector3I minCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMin() - MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * 1.01f);
            Vector3I maxCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMax() + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * 1.01f);
            voxelMap.FixVoxelCoord(ref minCorner);
            voxelMap.FixVoxelCoord(ref maxCorner);

            m_cache.Resize(ref minCorner, ref maxCorner);
            voxelMap.Storage.ReadRange(m_cache, true, true, MyVoxelGeometry.GetLodIndex(MyLodTypeEnum.LOD0), ref minCorner, ref maxCorner);

            Vector3I tempVoxelCoord;
            for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++)
            for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++)
            for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++)
            {
                var relPos   = tempVoxelCoord - minCorner; // get original amount
                var original = m_cache.Content(ref relPos);

                if (original == MyVoxelConstants.VOXEL_CONTENT_FULL) // if there is nothing to add
                    continue;

                var vpos   = voxelMap.GetVoxelPositionAbsolute(ref tempVoxelCoord);
                var volume = shape.GetVolume(ref vpos);

                if (volume <= 0f) // there is nothing to fill
                    continue;

                m_cache.Material(ref relPos, materialIdx); // set material

                var maxFill = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                var toFill  = (int)(maxFill * fillRatio);

                if (original > maxFill)
                    maxFill = original;

                var newVal = MathHelper.Clamp(original + toFill, 0, maxFill);

                if (!onlyCheck)
                    m_cache.Content(ref relPos, (byte)newVal);

                originalSum += original;
                filledSum += original + newVal;
            }

            if (filledSum > 0 && !onlyCheck)
            {
                voxelMap.Storage.WriteRange(m_cache, true, true, ref minCorner, ref maxCorner);
                voxelMap.InvalidateCache(minCorner - 1, maxCorner + 1);
            }
            voxelsCountInPercent = (originalSum > 0f) ? (float)filledSum / (float)originalSum : 0f;
            Profiler.End();
        }
 private void MakeVisible(MyVoxelMap voxelMap)
 {
     voxelMap.Render.Transparency = 0f;
 }
 private void MakeTransparent(MyVoxelMap voxelMap)
 {
     voxelMap.Render.Transparency = MyGridConstants.BUILDER_TRANSPARENCY;
 }
 private void MakeTransparent(MyVoxelMap voxelMap)
 {
     voxelMap.Render.Transparency = MyGridConstants.BUILDER_TRANSPARENCY;
 }
        private void CopyVoxelMapInternal(MyVoxelMap toCopy)
        {
            m_copiedVoxelMaps.Add((MyObjectBuilder_VoxelMap)toCopy.GetObjectBuilder(true));
            if (m_copiedVoxelMaps.Count == 1)
            {
                MatrixD pasteMatrix = GetPasteMatrix();
                Vector3D dragPointGlobal = toCopy.WorldMatrix.Translation;

                m_dragPointToPositionLocal = Vector3D.TransformNormal(toCopy.PositionComp.GetPosition() - dragPointGlobal, toCopy.PositionComp.WorldMatrixNormalizedInv);
                m_dragDistance = (float)(dragPointGlobal - pasteMatrix.Translation).Length();
            }
            m_copiedVoxelMapOffsets.Add(toCopy.WorldMatrix.Translation - m_copiedVoxelMaps[0].PositionAndOrientation.Value.Position);
        }
 private void MakeVisible(MyVoxelMap voxelMap)
 {
     voxelMap.Render.Transparency = 0f;
 }
        private static MyVoxelCacheCellRender LoadCell(MyVoxelMap voxelMap, ref Vector3I renderCellCoord, MyLodTypeEnum cellHashType)
        {
            Profiler.Begin("AddCell");

            MyVoxelCacheCellRender ret = AddCell(voxelMap.VoxelMapId, ref renderCellCoord, cellHashType);
            ret.Begin(voxelMap, ref renderCellCoord);
            ret.CellHashType = cellHashType;

            Profiler.End();

            if (cellHashType == MyLodTypeEnum.LOD0)
            {
                Profiler.Begin("LOD0 - queue cells");
                m_dataCellsQueue.Clear();

                //  Create normal (LOD0) version
                for (int dataX = 0; dataX < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataX++)
                {
                    for (int dataY = 0; dataY < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataY++)
                    {
                        for (int dataZ = 0; dataZ < MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS; dataZ++)
                        {
                            //  Don't precalculate this cells now. Store it in queue and calculate all cells at once by MyVoxelPrecalc.PrecalcQueue()
                            Vector3I dataCellCoord =
                                new Vector3I(
                                    renderCellCoord.X * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataX,
                                    renderCellCoord.Y * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataY,
                                    renderCellCoord.Z * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS + dataZ);
                            MyVoxelGeometry.CellData cachedDataCell = voxelMap.Geometry.GetCellLater(MyLodTypeEnum.LOD0, ref dataCellCoord);
                            if (cachedDataCell != null)
                            {
                                m_dataCellsQueue.Add(cachedDataCell);
                            }
                        }
                    }
                }

                Profiler.BeginNextBlock("LOD0 - PrecalcQueue");

                //  Precalculate all queued data cells in parallel threads - using multiple cores if possible.
                MyVoxelPrecalc.PrecalcQueue();

                Profiler.BeginNextBlock("LOD0 - AddTriangles");
                ret.AddTriangles(m_dataCellsQueue);
                Profiler.End();
            }
            else if (cellHashType == MyLodTypeEnum.LOD1)
            {
                Profiler.Begin("LOD1 - PrecalcImmediatelly");

                m_helperLodCachedDataCell.Reset();

                //  Create LOD1 render cell
                MyVoxelPrecalc.PrecalcImmediatelly(
                    new MyVoxelPrecalcTaskItem(
                        MyLodTypeEnum.LOD1,
                        voxelMap,
                        m_helperLodCachedDataCell,
                        new Vector3I(
                            renderCellCoord.X * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS,
                            renderCellCoord.Y * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS,
                            renderCellCoord.Z * MyVoxelConstants.RENDER_CELL_SIZE_IN_GEOMETRY_CELLS)));


                Profiler.BeginNextBlock("LOD1 - AddTriangles");
                m_dataCellsQueue.Clear();
                m_dataCellsQueue.Add(m_helperLodCachedDataCell);
                ret.AddTriangles(m_dataCellsQueue);
                Profiler.End();
            }
            else
            {
                throw new InvalidBranchException();
            }

            ret.End();

            return ret;
        }
        static void SpawnAsteroidConfirmedSuccess(ref SpawnAsteroidConfirmedMsg msg, MyNetworkClient sender)
        {
            MyStorageBase storage;
            SpawnAsteroidMsg asteroid = msg.AsteroidDetails;

            string storageName;
            using (MyRandom.Instance.PushSeed(asteroid.RandomSeed))
            {
                if (!asteroid.IsProcedural)
                {
                    var storageNameBase = asteroid.StorageName ?? (asteroid.Asteroid + "-" + asteroid.RandomSeed);
                    storageName = MakeStorageName(storageNameBase);
                    storage = CreateAsteroidStorage(asteroid.Asteroid, asteroid.RandomSeed);
                }
                else
                {
                    var storageNameBase = asteroid.StorageName ?? "ProcAsteroid" + "-" + asteroid.RandomSeed + "r" + asteroid.ProceduralRadius;
                    storageName = MakeStorageName(storageNameBase);
                    storage = CreateProceduralAsteroidStorage(asteroid.RandomSeed, asteroid.ProceduralRadius, 0.03f);
                }
            }

            var pastedVoxelMap = new MyVoxelMap();
            pastedVoxelMap.EntityId = msg.EntityId;
            pastedVoxelMap.Init(storageName, storage, asteroid.Position - storage.Size * 0.5f);
            MyEntities.Add(pastedVoxelMap);
        }
        //  Remove cell - after voxels were changed, etc.
        public static void RemoveCell(MyVoxelMap voxelMap, ref Vector3I cellCoord, MyLodTypeEnum cellHashType)
        {
            Int64 key = MySession.Static.VoxelMaps.GetCellHashCode(voxelMap.VoxelMapId, ref cellCoord, cellHashType);

            //  If cell is in cache, we remove it from dictionary and move it to the beginning of priority linked list
            LinkedListNode<MyVoxelCacheCellRender> ret;
            if (m_cellsByCoordinate.TryGetValue(key, out ret) == true)
            {
                m_cellsByCoordinate.Remove(key);

                ret.Value.Reset();

                //  Move it to the beginning of priority linked list
                Debug.Assert(Thread.CurrentThread == MySandboxGame.Static.UpdateThread);
                m_priority.Remove(ret);
                m_priority.AddFirst(ret);

                VRageRender.MyRenderProxy.InvalidateRenderVoxelCell(voxelMap.GetRenderObjectID(ref cellCoord), (VRageRender.MyLodTypeEnum)(int)cellHashType);
            }
        }
        public static void MakeCrater(MyVoxelMap voxelMap, BoundingSphere sphere, Vector3 normal, MyVoxelMaterialDefinition material, ref bool changed, out Vector3I minChanged, out Vector3I maxChanged)
        {
            Profiler.Begin("MakeCrater");
            Vector3I minCorner = voxelMap.GetVoxelCoordinateFromMeters(sphere.Center - (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES));
            Vector3I maxCorner = voxelMap.GetVoxelCoordinateFromMeters(sphere.Center + (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES));

            voxelMap.FixVoxelCoord(ref minCorner);
            voxelMap.FixVoxelCoord(ref maxCorner);

            //  We are tracking which voxels were changed, so we can invalidate only needed cells in the cache
            minChanged = maxCorner;
            maxChanged = minCorner;
            Profiler.Begin("Reading cache");
            m_cache.Resize(ref minCorner, ref maxCorner);
            voxelMap.Storage.ReadRange(m_cache, true, true, MyVoxelGeometry.GetLodIndex(MyLodTypeEnum.LOD0), ref minCorner, ref maxCorner);
            Profiler.End();

            Profiler.Begin("Changing cache");
            int removedVoxelContent = 0;
            Vector3I tempVoxelCoord;
            Vector3I cachePos;
            for (tempVoxelCoord.Z = minCorner.Z, cachePos.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, ++cachePos.Z)
            {
                for (tempVoxelCoord.Y = minCorner.Y, cachePos.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, ++cachePos.Y)
                {
                    for (tempVoxelCoord.X = minCorner.X, cachePos.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, ++cachePos.X)
                    {
                        bool cellChanged = false;
                        Vector3 voxelPosition = voxelMap.GetVoxelPositionAbsolute(ref tempVoxelCoord);

                        float addDist = (voxelPosition - sphere.Center).Length();
                        float addDiff = addDist - sphere.Radius;

                        byte newContent;
                        if (addDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                        }
                        else if (addDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            newContent = MyVoxelConstants.VOXEL_CONTENT_FULL;
                        }
                        else
                        {
                            //  This formula will work even if diff is positive or negative
                            newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - addDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                        }

                        byte originalContent = m_cache.Content(ref cachePos);

                        if (newContent > originalContent && originalContent > 0)
                        {
                            if (material != null)
                            {
                                m_cache.Material(ref cachePos, material.Index);
                            }

                            cellChanged = true;
                            m_cache.Content(ref cachePos, newContent);
                        }

                        float delDist = (voxelPosition - (sphere.Center + sphere.Radius * 0.7f * normal)).Length();
                        float delDiff = delDist - sphere.Radius;

                        byte contentToRemove;
                        if (delDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                        }
                        else if (delDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)
                        {
                            contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL;
                        }
                        else
                        {
                            //  This formula will work even if diff is positive or negative
                            contentToRemove = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - delDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                        }

                        originalContent = m_cache.Content(ref cachePos);

                        if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                        {
                            cellChanged = true;

                            int newVal = originalContent - contentToRemove;
                            if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                                newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                            m_cache.Content(ref cachePos, (byte)newVal);

                            removedVoxelContent += originalContent - newVal;
                        }

                        float setDist = (voxelPosition - (sphere.Center - sphere.Radius * 0.5f * normal)).Length();
                        float setDiff = setDist - sphere.Radius / 4f;

                        if (setDiff <= MyVoxelConstants.VOXEL_SIZE_IN_METRES * 1.5f)  // could be VOXEL_SIZE_IN_METRES_HALF, but we want to set material in empty cells correctly
                        {
                            byte indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_FULL;
                            if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)  // outside
                            {
                                indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_EMPTY;
                            }
                            else if (setDiff >= -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)  // boundary
                            {
                                indestructibleContentToSet = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - setDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL);
                            }

                            MyVoxelMaterialDefinition originalMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref cachePos));

                            // Change the material: 
                            // - always on boundaries between material and nothing
                            // - smoothly on inner boundaries
                            MyVoxelMaterialDefinition newMaterial = material;
                            if (setDiff > 0)
                            {
                                byte content = m_cache.Content(ref cachePos);
                                if (content == MyVoxelConstants.VOXEL_CONTENT_FULL)
                                    newMaterial = originalMaterial;
                                if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF && content != MyVoxelConstants.VOXEL_CONTENT_EMPTY)  // set material behind boundary only for empty voxels
                                    newMaterial = originalMaterial;
                            }

                            if (originalMaterial == newMaterial)
                            {
                                continue;
                            }

                            m_cache.Material(ref cachePos, newMaterial.Index);
                            cellChanged = true;
                        }

                        float dist = (voxelPosition - sphere.Center).Length();
                        float diff = dist - sphere.Radius;

                        if (diff <= 0f)
                        {
                            originalContent = m_cache.Content(ref cachePos);
                            if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                            {
                                bool result = m_cache.WrinkleVoxelContent(ref cachePos, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE);
                                if (cellChanged == false) cellChanged = result;
                            }
                        }

                        if (cellChanged)
                        {
                            if (tempVoxelCoord.X < minChanged.X) minChanged.X = tempVoxelCoord.X;
                            if (tempVoxelCoord.Y < minChanged.Y) minChanged.Y = tempVoxelCoord.Y;
                            if (tempVoxelCoord.Z < minChanged.Z) minChanged.Z = tempVoxelCoord.Z;
                            if (tempVoxelCoord.X > maxChanged.X) maxChanged.X = tempVoxelCoord.X;
                            if (tempVoxelCoord.Y > maxChanged.Y) maxChanged.Y = tempVoxelCoord.Y;
                            if (tempVoxelCoord.Z > maxChanged.Z) maxChanged.Z = tempVoxelCoord.Z;
                            changed = true;
                        }
                    }
                }
            }
            Profiler.End();

            if (changed)
            {
                Profiler.Begin("RemoveSmallVoxelsUsingChachedVoxels");
                RemoveSmallVoxelsUsingChachedVoxels();
                Profiler.BeginNextBlock("Writing cache");
                voxelMap.Storage.WriteRange(m_cache, true, true, ref minCorner, ref maxCorner);
                Profiler.End();
            }

            Profiler.End();
        }
        //  Remove cell for voxels specified be min/max corner. Used after explosion when we want to remove a lot of voxels/cell from cache.
        //  This is efficient method, because it doesn't invalidate cache after every voxel change.
        //  Method knows that adjacent cells need to be removed too (because of MCA), so it invalidates them too.
        public static void RemoveCellForVoxels(MyVoxelMap voxelMap, Vector3I minVoxel, Vector3I maxVoxel)
        {
            //  Calculate voxel for boundary things...
            minVoxel -= MyVoxelPrecalc.InvalidatedRangeInflate;
            maxVoxel += MyVoxelPrecalc.InvalidatedRangeInflate;
            if (maxVoxel.X > voxelMap.SizeMinusOne.X) maxVoxel.X = voxelMap.SizeMinusOne.X;
            if (maxVoxel.Y > voxelMap.SizeMinusOne.Y) maxVoxel.Y = voxelMap.SizeMinusOne.Y;
            if (maxVoxel.Z > voxelMap.SizeMinusOne.Z) maxVoxel.Z = voxelMap.SizeMinusOne.Z;

            //  Min/max cell
            Vector3I minCell = voxelMap.GetVoxelRenderCellCoordinate(ref minVoxel);
            Vector3I maxCell = voxelMap.GetVoxelRenderCellCoordinate(ref maxVoxel);

            //  Invalidate cells
            Vector3I tempCellCoord;
            for (tempCellCoord.X = minCell.X; tempCellCoord.X <= maxCell.X; tempCellCoord.X++)
            {
                for (tempCellCoord.Y = minCell.Y; tempCellCoord.Y <= maxCell.Y; tempCellCoord.Y++)
                {
                    for (tempCellCoord.Z = minCell.Z; tempCellCoord.Z <= maxCell.Z; tempCellCoord.Z++)
                    {
                        RemoveCell(voxelMap, ref tempCellCoord, MyLodTypeEnum.LOD0);
                        RemoveCell(voxelMap, ref tempCellCoord, MyLodTypeEnum.LOD1);
                    }
                }
            }
        }
        public static void CutOutShape(
            MyVoxelMap voxelMap,
            MyShape shape,
            out float voxelsCountInPercent,
            out MyVoxelMaterialDefinition voxelMaterial,
            float removeRatio = 1,
            Dictionary<MyVoxelMaterialDefinition, int> exactCutOutMaterials = null,
            bool updateSync = true,
            bool onlyCheck = false)
        {
            Profiler.Begin("MyVoxelGenerator::CutOutShape()");

            if (updateSync && Sync.IsServer)
            {
                shape.SendCutOutRequest(voxelMap.SyncObject, removeRatio);
            }

            int originalSum = 0;
            int removedSum  = 0;

            Vector3I minCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMin());
            Vector3I maxCorner = voxelMap.GetVoxelCoordinateFromMeters(shape.GetMax());
            voxelMap.FixVoxelCoord(ref minCorner);
            voxelMap.FixVoxelCoord(ref maxCorner);

            var cacheMin = minCorner - 1;
            var cacheMax = maxCorner + 1;
            voxelMap.FixVoxelCoord(ref cacheMin);
            voxelMap.FixVoxelCoord(ref cacheMax);
            m_cache.Resize(ref cacheMin, ref cacheMax);
            voxelMap.Storage.ReadRange(m_cache, true, true, MyVoxelGeometry.GetLodIndex(MyLodTypeEnum.LOD0), ref cacheMin, ref cacheMax);

            {
                Vector3I exactCenter = voxelMap.GetVoxelCoordinateFromMeters(shape.GetCenter());
                exactCenter -= cacheMin;
                exactCenter = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D-1);
                voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter));
            }

            Vector3I tempVoxelCoord;
            for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++)
            for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++)
            for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++)
            {
                var relPos   = tempVoxelCoord - cacheMin; // get original amount
                var original = m_cache.Content(ref relPos);

                if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove
                    continue;

                var vpos   = voxelMap.GetVoxelPositionAbsolute(ref tempVoxelCoord);
                var volume = shape.GetVolume(ref vpos);

                if (volume == 0f) // if there is no intersection
                    continue;

                var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                var voxelMat  = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos));
                var toRemove  = (int)(maxRemove * removeRatio * voxelMat.DamageRatio);
                if (voxelMap.Storage is MyCellStorage)
                {
                    if (toRemove < MyCellStorage.Quantizer.GetMinimumQuantizableValue())
                        toRemove = MyCellStorage.Quantizer.GetMinimumQuantizableValue();
                }
                var newVal    = MathHelper.Clamp(original - toRemove, 0, maxRemove);
                var removed   = Math.Abs(original - newVal);

                if (!onlyCheck)
                    m_cache.Content(ref relPos, (byte)newVal);

                originalSum += original;
                removedSum  += removed;

                if (exactCutOutMaterials != null)
                {
                    int value = 0;
                    exactCutOutMaterials.TryGetValue(voxelMat, out value);
                    value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed);
                    exactCutOutMaterials[voxelMat] = value;
                }
            }

            if (removedSum > 0 && !onlyCheck)
            {
                //  Clear all small voxel that may have been created during explosion. They can be created even outside the range of
                //  explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the
                //  explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we
                //  will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove
                //  B voxels too.
                //!! TODO AR & MK : check if this is needed !!
                RemoveSmallVoxelsUsingChachedVoxels();

                voxelMap.Storage.WriteRange(m_cache, true, false, ref cacheMin, ref cacheMax);
                voxelMap.InvalidateCache(cacheMin, cacheMax);
            }
            voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f;
            Profiler.End();
        }
 /// <summary>
 /// Adds the vertices from the physical body (rock) that is inside the given OBB
 /// </summary>
 /// <param name="voxelMap"></param>
 /// <param name="border"></param>
 /// <param name="originPosition"></param>
 /// <param name="obb"></param>
 /// <param name="bbList"></param>
 private void AddVoxelVertices(MyVoxelMap voxelMap, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> bbList)
 {
     AddVoxelMesh(voxelMap, voxelMap.Storage, null, border, originPosition, obb, bbList);
 }
 public static MyVoxelMap AddVoxelMap(string storageName, MyStorageBase storage, Vector3 positionMinCorner, long entityId = 0)
 {
     var voxelMap = new MyVoxelMap();
     voxelMap.EntityId = entityId;
     voxelMap.Init(storageName, storage, positionMinCorner);
     MyEntities.Add(voxelMap);
     return voxelMap;
 }
        /// <summary>
        /// Finds closest object (grid or voxel map) for placement of blocks .
        /// </summary>
        public bool FindClosestPlacementObject(out MyCubeGrid closestGrid, out MyVoxelMap closestVoxelMap)
        {
            closestGrid = null;
            closestVoxelMap = null;

            if (MySession.ControlledEntity == null) return false;

            m_hitInfo = null;

            LineD line = new LineD(IntersectionStart, IntersectionStart + IntersectionDirection * IntersectionDistance);

            MyPhysics.CastRay(line.From, line.To, m_tmpHitList, MyPhysics.ObjectDetectionCollisionLayer);
            // Remove character hits.

            m_tmpHitList.RemoveAll(delegate(MyPhysics.HitInfo hitInfo)
            {
                return (hitInfo.HkHitInfo.GetHitEntity() == MySession.ControlledEntity.Entity);
            });

            if (m_tmpHitList.Count == 0)
                return false;

            var hit = m_tmpHitList[0];
            closestGrid = hit.HkHitInfo.GetHitEntity() as MyCubeGrid;
            if (closestGrid != null)
            {
                m_hitInfo = hit;
            }

            if (MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL)
            {
                closestVoxelMap = hit.HkHitInfo.GetHitEntity() as MyVoxelMap;
                if (closestVoxelMap != null)
                    m_hitInfo = hit;
            }

            return closestGrid != null || closestVoxelMap != null;
        }
        private void RegisterVoxelMap(int item, MyVoxelMap voxelMap)
        {
            voxelMap.Save = false;
            voxelMap.RangeChanged += m_voxelMap_RangeChangedDelegate;
            m_voxelMaps[voxelMap] = item;

            MyEntityReferenceComponent component;
            if (!voxelMap.Components.TryGet(out component))
            {
                voxelMap.Components.Add(component = new MyEntityReferenceComponent());
            }

            DisableOtherItemsInVMap(voxelMap);

            component.Ref();
        }
        static void SpawnAsteroid(SpawnAsteroidInfo asteroidInfo)
        {
            if (MySession.Static.CreativeMode || MyEventContext.Current.IsLocallyInvoked || MySession.Static.HasPlayerAdminRights(MyEventContext.Current.Sender.Value))
            {
                MyStorageBase storage;
                string storageName;
                using (MyRandom.Instance.PushSeed(asteroidInfo.RandomSeed))
                {
                    if (!asteroidInfo.IsProcedural)
                    {
                        var storageNameBase = asteroidInfo.Asteroid + "-" + asteroidInfo.RandomSeed;
                        storageName = MakeStorageName(storageNameBase);
                        storage = CreateAsteroidStorage(asteroidInfo.Asteroid, asteroidInfo.RandomSeed);
                    }
                    else
                    {
                        var storageNameBase = "ProcAsteroid" + "-" + asteroidInfo.RandomSeed + "r" + asteroidInfo.ProceduralRadius;
                        storageName = MakeStorageName(storageNameBase);
                        storage = CreateProceduralAsteroidStorage(asteroidInfo.RandomSeed, asteroidInfo.ProceduralRadius, 0.03f);
                    }
                }

                var pastedVoxelMap = new MyVoxelMap();
                pastedVoxelMap.CreatedByUser = true;
                pastedVoxelMap.Save = true;
                pastedVoxelMap.AsteroidName = asteroidInfo.Asteroid;
                pastedVoxelMap.Init(storageName, storage, asteroidInfo.Position - storage.Size * 0.5f);
                MyEntities.Add(pastedVoxelMap);
                MyEntities.RaiseEntityCreated(pastedVoxelMap);
            }
        }
Beispiel #32
0
        public void SetTargetVoxel(Vector3D pos, MyVoxelMap voxelMap)
        {
            UnsetTarget();

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref pos, out m_targetInVoxelCoord);
            SetMTargetPosition(pos);
            m_currentTarget = MyAiTargetEnum.VOXEL;
        }