public static void GetMaterialContent(this VRage.Game.Voxels.IMyStorage self, ref Vector3I voxelCoords, out byte material, out byte content)
        {
            MyStorageData myStorageData = new MyStorageData(MyStorageDataTypeFlags.ContentAndMaterial);

            myStorageData.Resize(Vector3I.One);
            myStorageData.ClearMaterials(0);
            self.ReadRange(myStorageData, MyStorageDataTypeFlags.ContentAndMaterial, 0, voxelCoords, voxelCoords);

            material = myStorageData.Material(0);
            content  = myStorageData.Content(0);
        }
示例#2
0
        public static MyVoxelMaterialDefinition GetMaterialAt_R(this IMyStorage self, ref Vector3I voxelCoords)
        {
            MyVoxelMaterialDefinition def;

            var cache = new MyStorageData();

            cache.Resize(Vector3I.One);
            cache.ClearMaterials(0);

            self.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, voxelCoords, voxelCoords);

            def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(cache.Material(0));

            return(def);
        }
示例#3
0
        public static MyVoxelMaterialDefinition GetMaterialAt(this IMyStorage self, ref Vector3D localCoords)
        {
            MyVoxelMaterialDefinition def;

            Vector3I voxelCoords = Vector3D.Floor(localCoords / MyVoxelConstants.VOXEL_SIZE_IN_METRES);

            MyStorageData cache = new MyStorageData();

            cache.Resize(Vector3I.One);
            cache.ClearMaterials(0);

            self.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref voxelCoords, ref voxelCoords);

            def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(cache.Material(0));

            return(def);
        }
示例#4
0
        public bool ChangeMaterials(byte[] materialChangeFrom, byte[] materialChangeTo)
        {
            int rewrites = 0;

            if (materialChangeFrom != null && materialChangeTo != null)
            {
                int maxIndex = Math.Min(materialChangeFrom.Length, materialChangeTo.Length);
                if (maxIndex > 0)
                {
                    Vector3I minCorner = Vector3I.Zero;
                    Vector3I maxCorner = this.Size - 1;

                    MyStorageData cache = new MyStorageData();
                    cache.Resize(this.Size);
                    cache.ClearMaterials(0);

                    this.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref minCorner, ref maxCorner);
                    byte[] data = cache[MyStorageDataTypeEnum.Material];
                    int    i, j;
                    for (i = 0; i < data.Length; i++)
                    {
                        if (data[i] > 0)
                        {
                            for (j = 0; j < maxIndex; j++)
                            {
                                if (data[i] == materialChangeFrom[j])
                                {
                                    data[i] = materialChangeTo[j];
                                    rewrites++;
                                    break;
                                }
                            }
                        }
                    }
                    if (rewrites > 0)
                    {
                        this.WriteRange(cache, MyStorageDataTypeFlags.Material, ref minCorner, ref maxCorner);
                    }
                }
            }
            return(rewrites > 0);
        }
示例#5
0
        public static void CutOutShapeWithProperties(
            MyVoxelBase voxelMap,
            MyShape shape,
            out float voxelsCountInPercent,
            out MyVoxelMaterialDefinition voxelMaterial,
            Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null,
            bool updateSync          = false,
            bool onlyCheck           = false,
            bool applyDamageMaterial = false,
            bool onlyApplyMaterial   = false)
        {
            if (MySession.Static.EnableVoxelDestruction == false)
            {
                voxelsCountInPercent = 0;
                voxelMaterial        = null;
                return;
            }

            ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()");

            int  originalSum = 0;
            int  removedSum  = 0;
            bool materials   = exactCutOutMaterials != null;

            // Bring the shape into voxel space.
            var oldTranmsform = shape.Transformation;
            var newTransf     = oldTranmsform * voxelMap.PositionComp.WorldMatrixInvScaled;

            newTransf.Translation += voxelMap.SizeInMetresHalf;
            shape.Transformation   = newTransf;

            // This boundary should now be in our local space
            var bbox = shape.GetWorldBoundaries();

            Vector3I minCorner, maxCorner;

            ComputeShapeBounds(voxelMap, ref bbox, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner);

            bool readMaterial = exactCutOutMaterials != null || applyDamageMaterial;

            var cacheMin = minCorner - 1;
            var cacheMax = maxCorner + 1;

            //try on making the read/write cell alligned see MyOctreeStorage.WriteRange - Micro octree leaf

            /*const int SHIFT = 4;
             * const int REM = (1 << SHIFT) - 1;
             * const int MASK = ~REM;
             * cacheMin &= MASK;
             * cacheMax = (cacheMax + REM) & MASK;*/

            voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
            voxelMap.Storage.ClampVoxelCoord(ref cacheMax);
            m_cache.Resize(cacheMin, cacheMax);
            m_cache.ClearMaterials(0);

            // Advise that the read content shall be cached
            MyVoxelRequestFlags flags = MyVoxelRequestFlags.AdviseCache;

            voxelMap.Storage.ReadRange(m_cache, readMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax, ref flags);

            Vector3I center;

            if (materials)
            {
                center        = m_cache.Size3D / 2;
                voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref center));
            }
            else
            {
                center        = (cacheMin + cacheMax) / 2;
                voxelMaterial = voxelMap.Storage.GetMaterialAt(ref center);
            }

            MyVoxelMaterialDefinition voxelMat = null;

            ProfilerShort.Begin("Main loop");
            Vector3I pos;

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

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

                        Vector3D spos   = (Vector3D)(pos - voxelMap.StorageMin) * MyVoxelConstants.VOXEL_SIZE_IN_METRES;
                        var      volume = shape.GetVolume(ref spos);

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

                        var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                        var toRemove  = maxRemove;                        // (int)(maxRemove * voxelMat.DamageRatio);
                        var newVal    = Math.Max(original - toRemove, 0); //MathHelper.Clamp(original - toRemove, 0, original-maxRemove);
                        var removed   = original - newVal;

                        if (!onlyCheck && !onlyApplyMaterial)
                        {
                            m_cache.Content(lin, (byte)newVal);
                        }

                        originalSum += original;
                        removedSum  += removed;

                        if (readMaterial)
                        {
                            voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(lin));
                        }

                        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 (applyDamageMaterial && voxelMat.HasDamageMaterial && !onlyCheck)
                        {
                            m_cache.Material(lin, voxelMat.DamagedMaterialId);
                        }
                    }
                }
            }

            if (removedSum > 0 && updateSync && Sync.IsServer)
            {
                shape.SendDrillCutOutRequest(voxelMap, applyDamageMaterial);
            }

            ProfilerShort.BeginNextBlock("Write");


            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();

                var dataTypeFlags = applyDamageMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content;
                if (MyFakes.LOG_NAVMESH_GENERATION)
                {
                    MyAIComponent.Static.Pathfinding.VoxelPathfinding.DebugLog.LogStorageWrite(voxelMap, m_cache, dataTypeFlags, cacheMin, cacheMax);
                }
                voxelMap.Storage.WriteRange(m_cache, dataTypeFlags, ref cacheMin, ref cacheMax);
            }
            ProfilerShort.End();


            voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f;

            shape.Transformation = oldTranmsform;

            if (removedSum > 0)
            {
                OnVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, shape);
            }

            ProfilerShort.End();
        }
        private static MyStorageBase Compatibility_LoadCellStorage(int fileVersion, Stream stream)
        {
            //  Size of this voxel map (in voxels)
            Vector3I tmpSize;
            tmpSize.X = stream.ReadInt32();
            tmpSize.Y = stream.ReadInt32();
            tmpSize.Z = stream.ReadInt32();
            var storage = new MyOctreeStorage(null, tmpSize);

            //  Size of data cell in voxels. Has to be the same as current size specified by our constants.
            Vector3I cellSize;
            cellSize.X = stream.ReadInt32();
            cellSize.Y = stream.ReadInt32();
            cellSize.Z = stream.ReadInt32();
            Trace.Assert(cellSize.X == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                         cellSize.Y == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                         cellSize.Z == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS);

            Vector3I cellsCount = tmpSize / cellSize;

            Dictionary<byte, MyVoxelMaterialDefinition> mappingTable = null;
            if (fileVersion == STORAGE_TYPE_VERSION_CELL)
            {
                // loading material names->index mappings
                mappingTable = Compatibility_LoadMaterialIndexMapping(stream);
            }
            else if (fileVersion == 1)
            {
                // material name->index mappings were not saved in this version
            }

            var startCoord = Vector3I.Zero;
            var endCoord = new Vector3I(MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);

            var cache = new MyStorageData();
            cache.Resize(Vector3I.Zero, endCoord);
            Vector3I cellCoord;
            for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++)
            {
                for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++)
                {
                    for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++)
                    {
                        MyVoxelRangeType cellType = (MyVoxelRangeType)stream.ReadByteNoAlloc();

                        //  Cell's are FULL by default, therefore we don't need to change them
                        switch (cellType)
                        {
                            case MyVoxelRangeType.EMPTY: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_EMPTY); break;
                            case MyVoxelRangeType.FULL: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_FULL); break;
                            case MyVoxelRangeType.MIXED:
                                Vector3I v;
                                for (v.X = 0; v.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.X++)
                                {
                                    for (v.Y = 0; v.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Y++)
                                    {
                                        for (v.Z = 0; v.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Z++)
                                        {
                                            cache.Content(ref v, stream.ReadByteNoAlloc());
                                        }
                                    }
                                }
                                break;
                        }
                        startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS;
                        endCoord = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);
                        storage.WriteRange(cache, MyStorageDataTypeFlags.Content, ref startCoord, ref endCoord);
                    }
                }
            }

            try
            { // In case materials are not saved, catch any exceptions caused by this.
                // Read materials and indestructible
                for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++)
                {
                    for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++)
                    {
                        for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++)
                        {
                            bool isSingleMaterial = stream.ReadByteNoAlloc() == 1;
                            MyVoxelMaterialDefinition material = null;

                            if (isSingleMaterial)
                            {
                                material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable);
                                cache.ClearMaterials(material.Index);
                            }
                            else
                            {
                                byte indestructibleContent;
                                Vector3I voxelCoordInCell;
                                for (voxelCoordInCell.X = 0; voxelCoordInCell.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.X++)
                                {
                                    for (voxelCoordInCell.Y = 0; voxelCoordInCell.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Y++)
                                    {
                                        for (voxelCoordInCell.Z = 0; voxelCoordInCell.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Z++)
                                        {
                                            material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable);
                                            indestructibleContent = stream.ReadByteNoAlloc();
                                            cache.Material(ref voxelCoordInCell, material.Index);
                                        }
                                    }
                                }
                            }
                            startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS;
                            endCoord = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);
                            storage.WriteRange(cache, MyStorageDataTypeFlags.Material, ref startCoord, ref endCoord);
                        }
                    }
                }
            }
            catch (EndOfStreamException ex)
            {
                MySandboxGame.Log.WriteLine(ex);
            }

            return storage;
        }
示例#7
0
        private static MyStorageBase Compatibility_LoadCellStorage(int fileVersion, Stream stream)
        {
            //  Size of this voxel map (in voxels)
            Vector3I tmpSize;

            tmpSize.X = stream.ReadInt32();
            tmpSize.Y = stream.ReadInt32();
            tmpSize.Z = stream.ReadInt32();
            var storage = new MyOctreeStorage(null, tmpSize);

            //  Size of data cell in voxels. Has to be the same as current size specified by our constants.
            Vector3I cellSize;

            cellSize.X = stream.ReadInt32();
            cellSize.Y = stream.ReadInt32();
            cellSize.Z = stream.ReadInt32();
#if !XB1
            Trace.Assert(cellSize.X == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                         cellSize.Y == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                         cellSize.Z == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS);
#else // XB1
            System.Diagnostics.Debug.Assert(cellSize.X == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                                            cellSize.Y == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS &&
                                            cellSize.Z == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS);
#endif // XB1

            Vector3I cellsCount = tmpSize / cellSize;

            Dictionary <byte, MyVoxelMaterialDefinition> mappingTable = null;
            if (fileVersion == STORAGE_TYPE_VERSION_CELL)
            {
                // loading material names->index mappings
                mappingTable = Compatibility_LoadMaterialIndexMapping(stream);
            }
            else if (fileVersion == 1)
            {
                // material name->index mappings were not saved in this version
            }

            var startCoord = Vector3I.Zero;
            var endCoord   = new Vector3I(MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);

            var cache = new MyStorageData();
            cache.Resize(Vector3I.Zero, endCoord);
            Vector3I cellCoord;
            for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++)
            {
                for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++)
                {
                    for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++)
                    {
                        MyVoxelRangeType cellType = (MyVoxelRangeType)stream.ReadByteNoAlloc();

                        //  Cell's are FULL by default, therefore we don't need to change them
                        switch (cellType)
                        {
                        case MyVoxelRangeType.EMPTY: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_EMPTY); break;

                        case MyVoxelRangeType.FULL: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_FULL); break;

                        case MyVoxelRangeType.MIXED:
                            Vector3I v;
                            for (v.X = 0; v.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.X++)
                            {
                                for (v.Y = 0; v.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Y++)
                                {
                                    for (v.Z = 0; v.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Z++)
                                    {
                                        cache.Content(ref v, stream.ReadByteNoAlloc());
                                    }
                                }
                            }
                            break;
                        }
                        startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS;
                        endCoord   = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);
                        storage.WriteRange(cache, MyStorageDataTypeFlags.Content, ref startCoord, ref endCoord);
                    }
                }
            }

            try
            { // In case materials are not saved, catch any exceptions caused by this.
                // Read materials and indestructible
                for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++)
                {
                    for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++)
                    {
                        for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++)
                        {
                            bool isSingleMaterial = stream.ReadByteNoAlloc() == 1;
                            MyVoxelMaterialDefinition material = null;

                            if (isSingleMaterial)
                            {
                                material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable);
                                cache.ClearMaterials(material.Index);
                            }
                            else
                            {
                                byte     indestructibleContent;
                                Vector3I voxelCoordInCell;
                                for (voxelCoordInCell.X = 0; voxelCoordInCell.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.X++)
                                {
                                    for (voxelCoordInCell.Y = 0; voxelCoordInCell.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Y++)
                                    {
                                        for (voxelCoordInCell.Z = 0; voxelCoordInCell.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Z++)
                                        {
                                            material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable);
                                            indestructibleContent = stream.ReadByteNoAlloc();
                                            cache.Material(ref voxelCoordInCell, material.Index);
                                        }
                                    }
                                }
                            }
                            startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS;
                            endCoord   = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1);
                            storage.WriteRange(cache, MyStorageDataTypeFlags.Material, ref startCoord, ref endCoord);
                        }
                    }
                }
            }
            catch (EndOfStreamException ex)
            {
                MySandboxGame.Log.WriteLine(ex);
            }

            return(storage);
        }
示例#8
0
        public bool ChangeMaterials(byte[] materialChangeFrom, byte[] materialChangeTo)
        {
            int rewrites = 0;
            if (materialChangeFrom != null && materialChangeTo != null)
            {
                int maxIndex = Math.Min(materialChangeFrom.Length, materialChangeTo.Length);
                if (maxIndex > 0)
                {
                    Vector3I minCorner = Vector3I.Zero;
                    Vector3I maxCorner = this.Size-1;

                    MyStorageData cache = new MyStorageData();
                    cache.Resize(this.Size);
                    cache.ClearMaterials(0);

                    this.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref minCorner, ref maxCorner);
                    byte[] data = cache[MyStorageDataTypeEnum.Material];
                    int i, j;
                    for (i = 0; i < data.Length; i++)
                    {
                        if (data[i] > 0)
                        {
                            for (j = 0; j < maxIndex; j++)
                            {
                                if (data[i] == materialChangeFrom[j])
                                {
                                    data[i] = materialChangeTo[j];
                                    rewrites++;
                                    break;
                                }
                            }
                        }
                    }
                    if (rewrites > 0) this.WriteRange(cache, MyStorageDataTypeFlags.Material, ref minCorner, ref maxCorner);
                }
            }
            return (rewrites > 0);
        }
示例#9
0
        public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck = false)
        {
            // change range so normal can be computed at edges (expand by 1 in all directions)
            voxelStart -= 1;
            voxelEnd   += 1;

            if (storage == null)
            {
                return(null);
            }

            using (storage.Pin())
            {
                if (storage.Closed)
                {
                    return(null);
                }

                MyVoxelRequestFlags request = MyVoxelRequestFlags.ContentChecked; // | (doNotCheck ? MyVoxelRequestFlags.DoNotCheck : 0);
                //if (lod == 0 && generateMaterials) request |= MyVoxelRequestFlags.AdviseCache;

                bool readAmbient = false;

                if (generateMaterials && storage.DataProvider != null && storage.DataProvider.ProvidesAmbient)
                {
                    readAmbient = true;
                }

                m_cache.Resize(voxelStart, voxelEnd);
                if (readAmbient)
                {
                    m_cache.StoreOcclusion = true;
                }

                storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd, ref request);

                if (request.HasFlag(MyVoxelRequestFlags.EmptyContent) || request.HasFlag(MyVoxelRequestFlags.FullContent) ||
                    (!request.HasFlag(MyVoxelRequestFlags.ContentChecked) && !m_cache.ContainsIsoSurface()))
                {
                    //if(generateMaterials && lod == 0) Debugger.Break();
                    //storage.DebugDrawChunk(voxelStart, voxelEnd);
                    return(null);
                }

                var    center           = (storage.Size / 2) * MyVoxelConstants.VOXEL_SIZE_IN_METRES;
                var    voxelSize        = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod);
                var    vertexCellOffset = voxelStart - AffectedRangeOffset;
                double numCellsHalf     = 0.5 * (m_cache.Size3D.X - 3);
                var    posOffset        = ((Vector3D)vertexCellOffset + numCellsHalf) * (double)voxelSize;

                if (generateMaterials)
                {
                    // 255 is the new black
                    m_cache.ClearMaterials(255);
                }

                if (readAmbient)
                {
                    m_cache.Clear(MyStorageDataTypeEnum.Occlusion, 0);
                }

                IsoMesher mesher = new IsoMesher();
                ProfilerShort.Begin("Dual Contouring");
                unsafe
                {
                    fixed(byte *content = m_cache[MyStorageDataTypeEnum.Content])
                    fixed(byte *material = m_cache[MyStorageDataTypeEnum.Material])
                    {
                        var size3d = m_cache.Size3D;

                        Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z);
                        mesher.Calculate(size3d.X, content, material, m_buffer, useAmbient, posOffset - center);
                    }
                }
                ProfilerShort.End();

                if (generateMaterials)
                {
                    request = 0;

                    request |= MyVoxelRequestFlags.SurfaceMaterial;
                    request |= MyVoxelRequestFlags.ConsiderContent;

                    var req = readAmbient ? MyStorageDataTypeFlags.Material | MyStorageDataTypeFlags.Occlusion : MyStorageDataTypeFlags.Material;

                    storage.ReadRange(m_cache, req, lod, ref voxelStart, ref voxelEnd, ref request);

                    FixCacheMaterial(voxelStart, voxelEnd);
                    unsafe
                    {
                        fixed(byte *content = m_cache[MyStorageDataTypeEnum.Content])
                        fixed(byte *material = m_cache[MyStorageDataTypeEnum.Material])
                        {
                            int materialOverride = request.HasFlag(MyVoxelRequestFlags.OneMaterial) ? m_cache.Material(0) : -1;
                            var size3d           = m_cache.Size3D;

                            Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z);

                            if (readAmbient)
                                fixed(byte *ambient = m_cache[MyStorageDataTypeEnum.Occlusion])
                                mesher.CalculateMaterials(size3d.X, content, material, ambient, materialOverride);
                            else
                            {
                                mesher.CalculateMaterials(size3d.X, content, material, null, materialOverride);
                            }
                        }
                    }
                }
                else
                {
                    m_cache.ClearMaterials(0);
                }

                mesher.Finish(m_buffer);

                if (m_buffer.VerticesCount == 0 || m_buffer.Triangles.Count == 0)
                {
                    return(null);
                }

                ProfilerShort.Begin("Geometry post-processing");
                {
                    var positions   = m_buffer.Positions.GetInternalArray();
                    var vertexCells = m_buffer.Cells.GetInternalArray();
                    var materials   = m_buffer.Materials.GetInternalArray();
                    for (int i = 0; i < m_buffer.VerticesCount; i++)
                    {
                        Debug.Assert(positions[i].IsInsideInclusive(ref Vector3.MinusOne, ref Vector3.One));
                        vertexCells[i] += vertexCellOffset;
                        Debug.Assert(vertexCells[i].IsInsideInclusive(voxelStart + 1, voxelEnd - 1));
                        Debug.Assert(materials[i] != MyVoxelConstants.NULL_MATERIAL);
                    }

                    m_buffer.PositionOffset = posOffset;
                    m_buffer.PositionScale  = new Vector3((float)(numCellsHalf * voxelSize));
                    m_buffer.CellStart      = voxelStart + 1;
                    m_buffer.CellEnd        = voxelEnd - 1;
                }
                ProfilerShort.End();

                // Replace filled mesh with new one.
                // This way prevents allocation of meshes which then end up empty.
                var buffer = m_buffer;
                m_buffer = new MyIsoMesh();
                return(buffer);
            }
        }
        public static MyVoxelMaterialDefinition GetMaterialAt(this IMyStorage self, ref Vector3I voxelCoords)
        {
            MyVoxelMaterialDefinition def;

            MyStorageData cache = new MyStorageData();
            cache.Resize(Vector3I.One);
            cache.ClearMaterials(0);

            self.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref voxelCoords, ref voxelCoords);

            def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(cache.Material(0));

            return def;
        }
        public static MyVoxelMaterialDefinition GetMaterialAt(this IMyStorage self, ref Vector3D localCoords)
        {
            MyVoxelMaterialDefinition def;

            Vector3I voxelCoords = Vector3D.Floor(localCoords / MyVoxelConstants.VOXEL_SIZE_IN_METRES);

            MyStorageData cache = new MyStorageData();
            cache.Resize(Vector3I.One);
            cache.ClearMaterials(0);

            self.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref voxelCoords, ref voxelCoords);

            def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(cache.Material(0));

            return def;
        }
        private bool IsValidVoxelTarget(NaniteMiningItem target, IMyEntity entity)
        {
            if (entity == null)
            {
                return(false);
            }

            byte         material2 = 0;
            float        amount = 0;
            IMyVoxelBase voxel = entity as IMyVoxelBase;
            Vector3D     targetMin = target.Position;
            Vector3D     targetMax = target.Position;
            Vector3I     minVoxel, maxVoxel;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMin, out minVoxel);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMax, out maxVoxel);

            MyVoxelBase voxelBase = voxel as MyVoxelBase;

            minVoxel += voxelBase.StorageMin;
            maxVoxel += voxelBase.StorageMin;

            voxel.Storage.ClampVoxel(ref minVoxel);
            voxel.Storage.ClampVoxel(ref maxVoxel);

            MyStorageData cache = new MyStorageData();

            cache.Resize(minVoxel, maxVoxel);
            var flag = MyVoxelRequestFlags.AdviseCache;

            cache.ClearContent(0);
            cache.ClearMaterials(0);

            byte original = 0;

            voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, minVoxel, maxVoxel, ref flag);

            original  = cache.Content(0);
            material2 = cache.Material(0);

            if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY)
            {
                Logging.Instance.WriteLine("[Mining] Content is empty!", 2);
                MyAPIGateway.Utilities.InvokeOnGameThread(() =>
                                                          { AddMinedPosition(target); });
                return(false);
            }

            Logging.Instance.WriteLine($"[Mining] Material: SizeLinear: {cache.SizeLinear}, Size3D: {cache.Size3D}, AboveISO: {cache.ContainsVoxelsAboveIsoLevel()}", 2);
            cache.Content(0, 0);

            var voxelMat = target.Definition;

            target.Amount = CalculateAmount(voxelMat, original * 8f);

            Logging.Instance.WriteLine($"[Mining] Removing: {target.Position} ({material2} {amount})", 2);

            if (material2 == 0)
            {
                Logging.Instance.WriteLine("[Mining] Material is 0", 2);
                MyAPIGateway.Utilities.InvokeOnGameThread(() =>
                                                          { AddMinedPosition(target); });
                return(false);
            }

            if (target.Amount == 0f)
            {
                Logging.Instance.WriteLine("[Mining] Amount is 0", 2);
                MyAPIGateway.Utilities.InvokeOnGameThread(() =>
                                                          { AddMinedPosition(target); });
                return(false);
            }

            return(true);
        }
示例#13
0
        public static void RemoveVoxelContent(long voxelId, Vector3D position, out byte materialRemoved, out float amountOfMaterial)
        {
            materialRemoved  = 0;
            amountOfMaterial = 0f;

            IMyEntity entity;

            if (!MyAPIGateway.Entities.TryGetEntityById(voxelId, out entity))
            {
                return;
            }

            var      voxel = entity as IMyVoxelBase;
            var      targetMin = position;
            var      targetMax = position;
            Vector3I minVoxel, maxVoxel;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMin, out minVoxel);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMax, out maxVoxel);

            MyVoxelBase voxelBase = voxel as MyVoxelBase;

            minVoxel += voxelBase.StorageMin;
            maxVoxel += voxelBase.StorageMin + 1;

            voxel.Storage.ClampVoxel(ref minVoxel);
            voxel.Storage.ClampVoxel(ref maxVoxel);

            MyStorageData cache = new MyStorageData();

            cache.Resize(minVoxel, maxVoxel);
            var flag = MyVoxelRequestFlags.AdviseCache;

            cache.ClearContent(0);
            cache.ClearMaterials(0);

            byte original = 0;
            byte material = 0;

            // I don't really think pinning is necessary since I'm in the main thread, but this hasn't been working for awhile, so I'll keep it here.
            voxel.Storage.PinAndExecute(() =>
            {
                voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, minVoxel, maxVoxel, ref flag);

                // Grab content and material
                original = cache.Content(0);
                material = cache.Material(0);

                if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                {
                    //Logging.Instance.WriteLine(string.Format("Content is empty"));
                    return;
                }

                // Remove Content
                Logging.Instance.WriteLine($"Material: SizeLinear: {cache.SizeLinear}, Size3D: {cache.Size3D}, AboveISO: {cache.ContainsVoxelsAboveIsoLevel()}");
                cache.Content(0, 0);
                voxel.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, minVoxel, maxVoxel);
            });

            // Calculate Material Mined
            var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material);

            materialRemoved  = material;
            amountOfMaterial = CalculateAmount(voxelMat, original * 3.9f);

            // This will sync the clients.  Apparently voxel writes do not sync, lovely.
            if (Sync.IsServer)
            {
                VoxelRemovalData data = new VoxelRemovalData();
                data.VoxelID  = voxelId;
                data.Position = position;
                MyAPIGateway.Multiplayer.SendMessageToOthers(8969, ASCIIEncoding.ASCII.GetBytes(MyAPIGateway.Utilities.SerializeToXML(data)));
            }
        }
示例#14
0
        private void ReadVoxel(IMyVoxelBase voxel, Vector3D position, Dictionary <Vector3D, NaniteMiningItem> targets, HashSet <string> allowedOreList = null)
        {
            var m_cache = new MyStorageData();
            NaniteShapeSphere shapeSphere = new NaniteShapeSphere();

            shapeSphere.Center = position;
            shapeSphere.Radius = NaniteConstructionManager.Settings.MiningRadius / 2;

            //NaniteShapeCapsule shapeCapsule = new NaniteShapeCapsule();
            //shapeCapsule.A = positionA;
            //shapeCapsule.B = positionB;
            //shapeCapsule.Radius = NaniteConstructionManager.Settings.MiningRadius;

            Vector3I minCorner, maxCorner, numCells;

            GetVoxelShapeDimensions(voxel, shapeSphere, out minCorner, out maxCorner, out numCells);

            var cacheMin = minCorner - 1;
            var cacheMax = maxCorner + 1;

            //bool bRareOnly = true;
            //if (allowedOreList != null && allowedOreList.Contains("Stone"))
            //    bRareOnly = false;

            m_cache.Resize(cacheMin, cacheMax);
            m_cache.ClearContent(0);
            m_cache.ClearMaterials(0);
            var flags = MyVoxelRequestFlags.AdviseCache;

            voxel.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, cacheMin, cacheMax, ref flags);

            //voxel.Storage.PinAndExecute(() =>
            {
                Vector3I pos;
                for (pos.X = minCorner.X; pos.X <= maxCorner.X; ++pos.X)
                {
                    for (pos.Y = minCorner.Y; pos.Y <= maxCorner.Y; ++pos.Y)
                    {
                        for (pos.Z = minCorner.Z; pos.Z <= maxCorner.Z; ++pos.Z)
                        {
                            // get original amount
                            var relPos = pos - cacheMin;
                            var lin    = m_cache.ComputeLinear(ref relPos);

                            //var relPos = pos - cacheMin; // Position of voxel in local space
                            var original = m_cache.Content(lin); // Content at this position

                            if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                            {
                                continue;
                            }

                            var      material = m_cache.Material(lin); // Material at this position
                            Vector3D vpos;
                            MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref pos, out vpos);
                            if (targets.ContainsKey(vpos))
                            {
                                continue;
                            }

                            /*
                             * var volume = shapeSphere.GetVolume(ref vpos);
                             * if (volume == 0f) // Shape and voxel do not intersect at this position, so continue
                             *  continue;
                             */

                            // Pull information about voxel required for later processing
                            var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material);
                            //if ((bRareOnly && voxelMat.IsRare) || !bRareOnly)
                            //if(voxelMat.IsRare)
                            if (allowedOreList != null)// || (allowedOreList == null && bRareOnly && voxelMat.IsRare))
                            {
                                if (allowedOreList != null && !allowedOreList.Contains(voxelMat.MinedOre))
                                {
                                    continue;
                                }


                                NaniteMiningItem miningItem = new NaniteMiningItem();
                                miningItem.Position      = vpos;
                                miningItem.VoxelMaterial = material;
                                miningItem.VoxelId       = voxel.EntityId;
                                miningItem.Amount        = original; // * 3.9f;
                                miningItem.MiningHammer  = this;
                                targets.Add(vpos, miningItem);
                                //count++;
                            }

                            //m_cache.Content(lin, 0);
                            //m_cache.Material(lin, 0);
                        }
                    }
                }


                //voxel.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, cacheMin, cacheMax);
            };

            /*
             * int count = 0;
             * for (var itCells = new Vector3I_RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
             * {
             *  Vector3I cellMinCorner, cellMaxCorner;
             *  GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);
             *
             *  var cacheMin = cellMinCorner - 1;
             *  var cacheMax = cellMaxCorner + 1;
             *  voxel.Storage.ClampVoxel(ref cacheMin);
             *  voxel.Storage.ClampVoxel(ref cacheMax);
             *
             *  m_cache.Resize(cacheMin, cacheMax);
             *  voxel.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, cacheMin, cacheMax);
             *
             *  for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
             *  {
             *      var relPos = it.Current - cacheMin; // Position of voxel in local space
             *      var original = m_cache.Content(ref relPos); // Content at this position
             *      var material = m_cache.Material(ref relPos); // Material at this position
             *
             *      if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY)
             *          continue;
             *
             *      Vector3D vpos;
             *      MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref it.Current, out vpos);
             *      if (targets.ContainsKey(vpos))
             *          continue;
             *
             *      var volume = shapeSphere.GetVolume(ref vpos);
             *      if (volume == 0f) // Shape and voxel do not intersect at this position, so continue
             *          continue;
             *
             *      // Pull information about voxel required for later processing
             *      var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos));
             *      //if ((bRareOnly && voxelMat.IsRare) || !bRareOnly)
             *      //if(voxelMat.IsRare)
             *      if (allowedOreList != null)// || (allowedOreList == null && bRareOnly && voxelMat.IsRare))
             *      {
             *          if (allowedOreList != null && !allowedOreList.Contains(voxelMat.MinedOre))
             *              continue;
             *
             *          NaniteMiningItem miningItem = new NaniteMiningItem();
             *          miningItem.Position = vpos;
             *          miningItem.VoxelMaterial = material;
             *          miningItem.VoxelId = voxel.EntityId;
             *          miningItem.Amount = original; // * 3.9f;
             *          miningItem.MiningHammer = this;
             *          targets.Add(vpos, miningItem);
             *          count++;
             *      }
             *  }
             * }
             */

            //Logging.Instance.WriteLine(string.Format("Voxels Read: {0} - {1}", voxel.GetType().Name, count));
        }
示例#15
0
        public unsafe MyStorageBase Compatibility_LoadCellStorage(int fileVersion, Stream stream)
        {
            Vector3I vectori;
            Vector3I vectori2;
            Vector3I vectori6;

            vectori.X = stream.ReadInt32();
            vectori.Y = stream.ReadInt32();
            vectori.Z = stream.ReadInt32();
            MyOctreeStorage storage = new MyOctreeStorage(null, vectori);

            vectori2.X = stream.ReadInt32();
            vectori2.Y = stream.ReadInt32();
            vectori2.Z = stream.ReadInt32();
            Vector3I vectori3 = (Vector3I)(vectori / vectori2);
            Dictionary <byte, MyVoxelMaterialDefinition> mapping = null;

            if (fileVersion == 2)
            {
                mapping = this.Compatibility_LoadMaterialIndexMapping(stream);
            }
            else
            {
                int num2 = fileVersion;
            }
            Vector3I      zero   = Vector3I.Zero;
            Vector3I      end    = new Vector3I(7);
            MyStorageData source = new MyStorageData(MyStorageDataTypeFlags.All);

            source.Resize(Vector3I.Zero, end);
            vectori6.X = 0;
            while (vectori6.X < vectori3.X)
            {
                vectori6.Y = 0;
                while (true)
                {
                    if (vectori6.Y >= vectori3.Y)
                    {
                        int *numPtr6 = (int *)ref vectori6.X;
                        numPtr6[0]++;
                        break;
                    }
                    vectori6.Z = 0;
                    while (true)
                    {
                        if (vectori6.Z >= vectori3.Z)
                        {
                            int *numPtr5 = (int *)ref vectori6.Y;
                            numPtr5[0]++;
                            break;
                        }
                        MyVoxelContentConstitution constitution = (MyVoxelContentConstitution)stream.ReadByteNoAlloc();
                        switch (constitution)
                        {
                        case MyVoxelContentConstitution.Empty:
                            source.ClearContent(0);
                            break;

                        case MyVoxelContentConstitution.Full:
                            source.ClearContent(0xff);
                            break;

                        case MyVoxelContentConstitution.Mixed:
                            Vector3I vectori7;
                            vectori7.X = 0;
                            while (vectori7.X < 8)
                            {
                                vectori7.Y = 0;
                                while (true)
                                {
                                    if (vectori7.Y >= 8)
                                    {
                                        int *numPtr3 = (int *)ref vectori7.X;
                                        numPtr3[0]++;
                                        break;
                                    }
                                    vectori7.Z = 0;
                                    while (true)
                                    {
                                        if (vectori7.Z >= 8)
                                        {
                                            int *numPtr2 = (int *)ref vectori7.Y;
                                            numPtr2[0]++;
                                            break;
                                        }
                                        source.Content(ref vectori7, stream.ReadByteNoAlloc());
                                        int *numPtr1 = (int *)ref vectori7.Z;
                                        numPtr1[0]++;
                                    }
                                }
                            }
                            break;

                        default:
                            break;
                        }
                        zero = vectori6 * 8;
                        storage.WriteRange(source, MyStorageDataTypeFlags.Content, zero, (Vector3I)(zero + 7), true, false);
                        int *numPtr4 = (int *)ref vectori6.Z;
                        numPtr4[0]++;
                    }
                }
            }
            try
            {
                vectori6.X = 0;
                while (vectori6.X < vectori3.X)
                {
                    vectori6.Y = 0;
                    while (true)
                    {
                        if (vectori6.Y >= vectori3.Y)
                        {
                            int *numPtr12 = (int *)ref vectori6.X;
                            numPtr12[0]++;
                            break;
                        }
                        vectori6.Z = 0;
                        while (true)
                        {
                            if (vectori6.Z >= vectori3.Z)
                            {
                                int *numPtr11 = (int *)ref vectori6.Y;
                                numPtr11[0]++;
                                break;
                            }
                            MyVoxelMaterialDefinition definition = null;
                            if (stream.ReadByteNoAlloc() == 1)
                            {
                                source.ClearMaterials(this.Compatibility_LoadCellVoxelMaterial(stream, mapping).Index);
                            }
                            else
                            {
                                Vector3I vectori8;
                                vectori8.X = 0;
                                while (vectori8.X < 8)
                                {
                                    vectori8.Y = 0;
                                    while (true)
                                    {
                                        if (vectori8.Y >= 8)
                                        {
                                            int *numPtr9 = (int *)ref vectori8.X;
                                            numPtr9[0]++;
                                            break;
                                        }
                                        vectori8.Z = 0;
                                        while (true)
                                        {
                                            if (vectori8.Z >= 8)
                                            {
                                                int *numPtr8 = (int *)ref vectori8.Y;
                                                numPtr8[0]++;
                                                break;
                                            }
                                            definition = this.Compatibility_LoadCellVoxelMaterial(stream, mapping);
                                            stream.ReadByteNoAlloc();
                                            source.Material(ref vectori8, definition.Index);
                                            int *numPtr7 = (int *)ref vectori8.Z;
                                            numPtr7[0]++;
                                        }
                                    }
                                }
                            }
                            zero = vectori6 * 8;
                            storage.WriteRange(source, MyStorageDataTypeFlags.Material, zero, (Vector3I)(zero + 7), true, false);
                            int *numPtr10 = (int *)ref vectori6.Z;
                            numPtr10[0]++;
                        }
                    }
                }
            }
            catch (EndOfStreamException exception)
            {
                MySandboxGame.Log.WriteLine(exception);
            }
            return(storage);
        }