private bool FindMaterial(IMyStorage storage, byte[] findMaterial)
        {
            if (findMaterial.Length == 0)
            {
                return(false);
            }

            var oldCache = new MyStorageData();

            oldCache.Resize(storage.Size);
            storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 2, Vector3I.Zero, storage.Size - 1);
            //MyAPIGateway.Utilities.ShowMessage("check", string.Format("SizeLinear {0}  {1}.", oldCache.SizeLinear, oldCache.StepLinear));

            Vector3I p;

            for (p.Z = 0; p.Z < storage.Size.Z; ++p.Z)
            {
                for (p.Y = 0; p.Y < storage.Size.Y; ++p.Y)
                {
                    for (p.X = 0; p.X < storage.Size.X; ++p.X)
                    {
                        var content  = oldCache.Content(ref p);
                        var material = oldCache.Material(ref p);

                        if (content > 0 && findMaterial.Contains(material))
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
Exemple #2
0
        public static MyVoxelMaterialDefinition GetMaterialAt(this IMyStorage self, ref Vector3I voxelCoords)
        {
            MyVoxelMaterialDefinition def;

            MyStorageDataCache cache = new MyStorageDataCache();

            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);
        }
        public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials)
        {
            // change range so normal can be computed at edges (expand by 1 in all directions)
            voxelStart -= 1;
            voxelEnd   += 1;
            m_cache.Resize(voxelStart, voxelEnd);
            storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd);
            if (!m_cache.ContainsIsoSurface())
            {
                return(null);
            }

            if (generateMaterials)
            {
                storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, lod, ref voxelStart, ref voxelEnd);
            }
            else
            {
                m_cache.ClearMaterials(0);
            }
            var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod);

            ProfilerShort.Begin("Dual Contouring");
            unsafe
            {
                fixed(byte *voxels = m_cache.Data)
                {
                    var size3d = m_cache.Size3D;

                    Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z);
                    IsoMesher.Calculate(size3d.X, (VoxelData *)voxels, m_buffer);
                }
            }
            ProfilerShort.End();

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

            ProfilerShort.Begin("Geometry post-processing");
            {
                var vertexCellOffset = voxelStart - AffectedRangeOffset;
                var positions        = m_buffer.Positions.GetInternalArray();
                var vertexCells      = m_buffer.Cells.GetInternalArray();
                for (int i = 0; i < m_buffer.VerticesCount; i++)
                {
                    var min = -Vector3.One;
                    var max = Vector3.One;
                    //   Debug.Assert(positions[i].IsInsideInclusive(ref min, ref max));
                    vertexCells[i] += vertexCellOffset;
                }

                float numCellsHalf = 0.5f * (m_cache.Size3D.X - 3);
                m_buffer.PositionOffset = (vertexCellOffset + numCellsHalf) * voxelSize;
                m_buffer.PositionScale  = new Vector3(numCellsHalf * voxelSize);
            }
            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 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.HasFlags(MyVoxelRequestFlags.EmptyContent) || request.HasFlags(MyVoxelRequestFlags.FullContent)
                    || (!request.HasFlags(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);
                    }
                }
                
                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.HasFlags(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);
                ProfilerShort.End();

                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();
                    var ambients = m_buffer.Ambient.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);
                        Debug.Assert(ambients[i] >= 0 && ambients[i] <= 1);
                    }

                    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 MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck)
        {
            m_resultVerticesCounter  = 0;
            m_resultTrianglesCounter = 0;
            m_edgeVertexCalcCounter++;
            m_temporaryVoxelsCounter++;

            CalcPolygCubeSize(lod, storage.Size);

            m_voxelStart = voxelStart;
            //voxelStart = voxelStart;
            //voxelEnd = voxelEnd;
            var ssize = storage.Size;

            m_cache.Resize(voxelStart, voxelEnd);

            // Load content first, check it if it contains isosurface, early exit if it doesn't.
            storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd);

            if (!m_cache.ContainsIsoSurface())
            {
                return(null);
            }

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

            ProfilerShort.Begin("Marching cubes");
            {
                //  Size of voxel or cell (in meters) and size of voxel map / voxel cells
                ComputeSizeAndOrigin(lod, storage.Size);


                var      start  = Vector3I.Zero;
                var      end    = voxelEnd - voxelStart - 3;
                Vector3I coord0 = start;


                for (var it = new Vector3I.RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out coord0))
                {
                    int cubeIndex = 0;
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 1;
                    }
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 2;
                    }
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 4;
                    }
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 8;
                    }
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 16;
                    }
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 32;
                    }
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 64;
                    }
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL)
                    {
                        cubeIndex |= 128;
                    }

                    //  Cube is entirely in/out of the surface
                    if (MyMarchingCubesConstants.EdgeTable[cubeIndex] == 0)
                    {
                        continue;
                    }

                    //  We can get this voxel content right from cache (not using GetVoxelContent method), because after CopyVoxelContents these array must be filled. But only content, not material, normal, etc.
                    Vector3I tempVoxelCoord0 = ComputeTemporaryVoxelData(m_cache, ref coord0, cubeIndex, lod);

                    //  Create the triangles
                    CreateTriangles(ref coord0, cubeIndex, ref tempVoxelCoord0);
                }
            }
            ProfilerShort.End();


            double numCellsHalf     = 0.5f * (m_cache.Size3D.X);
            var    voxelSize        = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod);
            var    vertexCellOffset = voxelStart - AffectedRangeOffset;

            IMyIsoMesherOutputBuffer isomesh = new MyIsoMesh();


            for (int i = 0; i < m_resultVerticesCounter; i++)
            {
                var pos = (m_resultVertices[i].Position - (Vector3)storage.Size / 2) / storage.Size;
                m_resultVertices[i].Position      = pos;
                m_resultVertices[i].PositionMorph = pos;
                m_resultVertices[i].NormalMorph   = m_resultVertices[i].Normal;
                m_resultVertices[i].MaterialMorph = m_resultVertices[i].Material;
                m_resultVertices[i].AmbientMorph  = m_resultVertices[i].Ambient;
            }

            for (int i = 0; i < m_resultVerticesCounter; i++)
            {
                isomesh.WriteVertex(ref m_resultVertices[i].Cell, ref m_resultVertices[i].Position, ref m_resultVertices[i].Normal, (byte)m_resultVertices[i].Material, m_resultVertices[i].Ambient);
            }

            for (int i = 0; i < m_resultTrianglesCounter; i++)
            {
                isomesh.WriteTriangle(m_resultTriangles[i].VertexIndex0, m_resultTriangles[i].VertexIndex1, m_resultTriangles[i].VertexIndex2);
            }

            var mIsoMesh = (MyIsoMesh)isomesh;

            mIsoMesh.PositionOffset = storage.Size / 2;
            mIsoMesh.PositionScale  = storage.Size;
            mIsoMesh.CellStart      = voxelStart;
            mIsoMesh.CellEnd        = voxelEnd;

            var vertexCells = mIsoMesh.Cells.GetInternalArray();

            for (int i = 0; i < mIsoMesh.VerticesCount; i++)
            {
                vertexCells[i] += vertexCellOffset;
            }

            return((MyIsoMesh)isomesh);
        }
        private void ProcessCell(MyStorageData cache, IMyStorage storage, Vector3I cell, long detectorId)
        {
            //bool m_miningDebug = false;

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

            Vector3I vector3I         = cell << 3;
            Vector3I lodVoxelRangeMax = vector3I + 7;

            // Advice cache because of performance issues
            var flag = MyVoxelRequestFlags.ContentCheckedDeep;

            Stopwatch stopwatch = Stopwatch.StartNew();

            storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, vector3I, lodVoxelRangeMax, ref flag);
            stopwatch.Stop();

            int readingTime = (int)((stopwatch.ElapsedTicks * 1000000) / Stopwatch.Frequency);

            if (readingTime > 1000)
            {
                int changeAmount = (int)(readingTime / 1000);

                if (MyAPIGateway.Physics.ServerSimulationRatio < 1.00f)
                {
                    sleepTimer += changeAmount * 100;
                }
                else
                {
                    sleepTimer = Math.Max(sleepTimer - 1, 1);
                }

                MyAPIGateway.Parallel.Sleep(sleepTimer);
            }

            //if (m_miningDebug)
            //Logging.Instance.WriteLine($"ProcessCell.ReadRange(1) took {(stopwatch.ElapsedTicks * 1000000)/Stopwatch.Frequency} microseconds");

            if (cache.ContainsVoxelsAboveIsoLevel())
            {
                //Stopwatch stopwatch2 = Stopwatch.StartNew();
                storage.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, vector3I, lodVoxelRangeMax, ref flag);
                //stopwatch2.Stop();

                //if (m_miningDebug)
                //Logging.Instance.WriteLine($"ProcessCell.ReadRange(2) took {(stopwatch2.ElapsedTicks * 1000000)/Stopwatch.Frequency} microseconds");

                Vector3I p = default(Vector3I);
                p.Z = 0;
                while (p.Z < 8)
                {
                    p.Y = 0;
                    while (p.Y < 8)
                    {
                        p.X = 0;
                        while (p.X < 8)
                        {
                            int linearIdx = cache.ComputeLinear(ref p);

                            if (cache.Content(linearIdx) > 127)
                            {
                                byte b = cache.Material(linearIdx);

                                if (HasFilterUpgrade)
                                {
                                    var voxelDefinition = MyDefinitionManager.Static.GetVoxelMaterialDefinition(b);

                                    if (voxelDefinition != null && voxelDefinition.MinedOre != null)
                                    {
                                        foreach (string mat in OreListSelected)
                                        {
                                            if (voxelDefinition.MinedOre.ToLower() == mat.ToLower())
                                            {
                                                Materials.AddMaterial(b, vector3I + p);
                                                break;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        Materials.AddMaterial(b, vector3I + p);
                                    }
                                }
                                else
                                {
                                    Materials.AddMaterial(b, vector3I + p);
                                }
                            }
                            p.X++;
                        }
                        p.Y++;
                    }
                    p.Z++;
                }
            }
        }
        private bool FindMaterial(IMyStorage storage, byte[] findMaterial)
        {
            if (findMaterial.Length == 0)
                return false;

            var oldCache = new MyStorageDataCache();
            oldCache.Resize(storage.Size);
            storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 2, Vector3I.Zero, storage.Size - 1);
            //MyAPIGateway.Utilities.ShowMessage("check", string.Format("SizeLinear {0}  {1}.", oldCache.SizeLinear, oldCache.StepLinear));

            Vector3I p;
            for (p.Z = 0; p.Z < storage.Size.Z; ++p.Z)
                for (p.Y = 0; p.Y < storage.Size.Y; ++p.Y)
                    for (p.X = 0; p.X < storage.Size.X; ++p.X)
                    {
                        var content = oldCache.Content(ref p);
                        var material = oldCache.Material(ref p);

                        if (content > 0 && findMaterial.Contains(material))
                        {
                            return true;
                        }
                    }
            return false;
        }
        public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck, bool adviceCache = false)
        {

            m_resultVerticesCounter = 0;
            m_resultTrianglesCounter = 0;
            m_edgeVertexCalcCounter++;
            m_temporaryVoxelsCounter++;            

            CalcPolygCubeSize(lod, storage.Size);

            m_voxelStart = voxelStart;
            //voxelStart = voxelStart;
            //voxelEnd = voxelEnd;
            var ssize = storage.Size;
            m_cache.Resize(voxelStart, voxelEnd);

            // Load content first, check it if it contains isosurface, early exit if it doesn't.
            storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd);

            if (!m_cache.ContainsIsoSurface())
                return null;

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

            ProfilerShort.Begin("Marching cubes");
            {
                //  Size of voxel or cell (in meters) and size of voxel map / voxel cells
                ComputeSizeAndOrigin(lod, storage.Size);


                var start = Vector3I.Zero;
                var end = voxelEnd - voxelStart - 3;
                Vector3I coord0 = start;


                for (var it = new Vector3I_RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out coord0))
                {
                    int cubeIndex = 0;
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 1;
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 2;
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 4;
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 8;
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 16;
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 32;
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 64;
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 128;

                    //  Cube is entirely in/out of the surface
                    if (MyMarchingCubesConstants.EdgeTable[cubeIndex] == 0)
                    {
                        continue;
                    }

                    //  We can get this voxel content right from cache (not using GetVoxelContent method), because after CopyVoxelContents these array must be filled. But only content, not material, normal, etc.
                    Vector3I tempVoxelCoord0 = ComputeTemporaryVoxelData(m_cache, ref coord0, cubeIndex, lod);

                    //  Create the triangles
                    CreateTriangles(ref coord0, cubeIndex, ref tempVoxelCoord0);
                }
            }
            ProfilerShort.End();


            double numCellsHalf = 0.5f * (m_cache.Size3D.X);
            var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod);
            var vertexCellOffset = voxelStart - AffectedRangeOffset;

            IMyIsoMesherOutputBuffer isomesh = new MyIsoMesh();


            for (int i = 0; i < m_resultVerticesCounter; i++)
            {
                var pos = (m_resultVertices[i].Position - (Vector3)storage.Size / 2) / storage.Size;                
                m_resultVertices[i].Position = pos;
                m_resultVertices[i].PositionMorph = pos;
                m_resultVertices[i].NormalMorph = m_resultVertices[i].Normal;
                m_resultVertices[i].MaterialMorph = m_resultVertices[i].Material;
                m_resultVertices[i].AmbientMorph = m_resultVertices[i].Ambient;
            }

            for (int i = 0; i < m_resultVerticesCounter; i++)
            {
                isomesh.WriteVertex(ref m_resultVertices[i].Cell, ref m_resultVertices[i].Position, ref m_resultVertices[i].Normal, (byte)m_resultVertices[i].Material, m_resultVertices[i].Ambient);
            }

            for (int i = 0; i < m_resultTrianglesCounter; i++)
            {
                isomesh.WriteTriangle(m_resultTriangles[i].VertexIndex0, m_resultTriangles[i].VertexIndex1, m_resultTriangles[i].VertexIndex2);
            }

            var mIsoMesh = (MyIsoMesh)isomesh;
            mIsoMesh.PositionOffset = storage.Size / 2;
            mIsoMesh.PositionScale = storage.Size;
            mIsoMesh.CellStart = voxelStart;
            mIsoMesh.CellEnd = voxelEnd;

            var vertexCells = mIsoMesh.Cells.GetInternalArray();
            for (int i = 0; i < mIsoMesh.VerticesCount; i++)
            {
                vertexCells[i] += vertexCellOffset;
            }

            return (MyIsoMesh)isomesh;
        }
Exemple #10
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);
            }
        }
Exemple #11
0
        private unsafe void ProcessCell(MyStorageData cache, IMyStorage storage, Vector3I cell, long detectorId)
        {
            Vector3I lodVoxelRangeMin = cell << 3;
            Vector3I lodVoxelRangeMax = (Vector3I)(lodVoxelRangeMin + 7);

            storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 2, lodVoxelRangeMin, lodVoxelRangeMax);
            if (cache.ContainsVoxelsAboveIsoLevel())
            {
                Vector3I            vectori3;
                MyVoxelRequestFlags preciseOrePositions = MyVoxelRequestFlags.PreciseOrePositions;
                storage.ReadRange(cache, MyStorageDataTypeFlags.Material, 2, lodVoxelRangeMin, lodVoxelRangeMax, ref preciseOrePositions);
                MaterialPositionData[] materialData = MaterialData;
                vectori3.Z = 0;
                while (vectori3.Z < 8)
                {
                    vectori3.Y = 0;
                    while (true)
                    {
                        if (vectori3.Y >= 8)
                        {
                            int *numPtr4 = (int *)ref vectori3.Z;
                            numPtr4[0]++;
                            break;
                        }
                        vectori3.X = 0;
                        while (true)
                        {
                            if (vectori3.X >= 8)
                            {
                                int *numPtr3 = (int *)ref vectori3.Y;
                                numPtr3[0]++;
                                break;
                            }
                            int linearIdx = cache.ComputeLinear(ref vectori3);
                            if (cache.Content(linearIdx) > 0x7f)
                            {
                                byte     index      = cache.Material(linearIdx);
                                Vector3D vectord    = ((vectori3 + lodVoxelRangeMin) * 4f) + 2f;
                                Vector3 *vectorPtr1 = (Vector3 *)ref materialData[index].Sum;
                                vectorPtr1[0] += vectord;
                                int *numPtr1 = (int *)ref materialData[index].Count;
                                numPtr1[0]++;
                            }
                            int *numPtr2 = (int *)ref vectori3.X;
                            numPtr2[0]++;
                        }
                    }
                }
                MyEntityOreDeposit item = null;
                for (int i = 0; i < materialData.Length; i++)
                {
                    if (materialData[i].Count != 0)
                    {
                        MyVoxelMaterialDefinition voxelMaterialDefinition = MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)i);
                        if ((voxelMaterialDefinition != null) && voxelMaterialDefinition.IsRare)
                        {
                            if (item == null)
                            {
                                item = new MyEntityOreDeposit(this.VoxelMap, cell, detectorId);
                            }
                            MyEntityOreDeposit.Data data = new MyEntityOreDeposit.Data {
                                Material             = voxelMaterialDefinition,
                                AverageLocalPosition = (Vector3)Vector3D.Transform((materialData[i].Sum / ((float)materialData[i].Count)) - this.VoxelMap.SizeInMetresHalf, Quaternion.CreateFromRotationMatrix(this.VoxelMap.WorldMatrix))
                            };
                            item.Materials.Add(data);
                        }
                    }
                }
                if (item != null)
                {
                    this.m_result.Add(item);
                }
                else
                {
                    this.m_emptyCells.Add(cell);
                }
                Array.Clear(materialData, 0, materialData.Length);
            }
        }
Exemple #12
0
        public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient)
        {
            // change range so normal can be computed at edges (expand by 1 in all directions)
            voxelStart -= 1;
            voxelEnd   += 1;
            m_cache.Resize(voxelStart, voxelEnd);
            storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd);
            if (!m_cache.ContainsIsoSurface())
            {
                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)
            {
                m_cache.ClearMaterials(0);
            }

            IsoMesher mesher = new IsoMesher();

            ProfilerShort.Begin("Dual Contouring");
            unsafe
            {
                fixed(byte *voxels = m_cache.Data)
                {
                    var size3d = m_cache.Size3D;

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

            if (generateMaterials)
            {
                using (MyVoxelMaterialRequestHelper.StartContouring())
                {
                    storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, lod, ref voxelStart, ref voxelEnd);
                    bool hasOcclusionHint = false;
                    FixCacheMaterial(voxelStart, voxelEnd);
                    unsafe
                    {
                        fixed(byte *voxels = m_cache.Data)
                        {
                            var size3d = m_cache.Size3D;

                            Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z);
                            mesher.CalculateMaterials(size3d.X, (VoxelData *)voxels, hasOcclusionHint);
                        }
                    }
                }
            }
            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();
                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));
                }

                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 MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials)
        {
            // change range so normal can be computed at edges (expand by 1 in all directions)
            voxelStart -= 1;
            voxelEnd += 1;
            m_cache.Resize(voxelStart, voxelEnd);
            storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd);
            if (!m_cache.ContainsIsoSurface())
            {
                return null;
            }

            if (generateMaterials)
            {
                storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, lod, ref voxelStart, ref voxelEnd);
            }
            else
            {
                m_cache.ClearMaterials(0);
            }
            var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod);

            ProfilerShort.Begin("Dual Contouring");
            unsafe
            {
                fixed (byte* voxels = m_cache.Data)
                {
                    var size3d = m_cache.Size3D;
                    Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z);
                    IsoMesher.Calculate(size3d.X, (VoxelData*)voxels, m_buffer);
                }
            }
            ProfilerShort.End();

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

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

                double numCellsHalf = 0.5 * (m_cache.Size3D.X - 3);
                m_buffer.PositionOffset = ((Vector3D)vertexCellOffset + numCellsHalf) * (double)voxelSize;
                m_buffer.PositionScale = new Vector3((float)(numCellsHalf * voxelSize));
            }
            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;
        }
        private void ProcessCell(MyStorageData cache, IMyStorage storage, Vector3I cell)
        {
            var min = cell << MyOreDetectorComponent.CELL_SIZE_IN_VOXELS_BITS;
            var max = min + (MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS - 1);

            storage.PinAndExecute(() =>
            {
                storage.ReadRange(cache, MyStorageDataTypeFlags.Content, MyOreDetectorComponent.QUERY_LOD, min, max);
                if (!cache.ContainsVoxelsAboveIsoLevel())
                {
                    return;
                }

                storage.ReadRange(cache, MyStorageDataTypeFlags.Material, MyOreDetectorComponent.QUERY_LOD, min, max);
            });

            var      materialData = MaterialData;
            Vector3I c;

            for (c.Z = 0; c.Z < MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS; ++c.Z)
            {
                for (c.Y = 0; c.Y < MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS; ++c.Y)
                {
                    for (c.X = 0; c.X < MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS; ++c.X)
                    {
                        int i = cache.ComputeLinear(ref c);
                        if (cache.Content(i) > MyVoxelDataConstants.IsoLevel)
                        {
                            const float VOXEL_SIZE      = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << MyOreDetectorComponent.QUERY_LOD);
                            const float VOXEL_SIZE_HALF = VOXEL_SIZE * 0.5f;
                            var         material        = cache.Material(i);

                            Vector3D localPos = (c + min) * VOXEL_SIZE + VOXEL_SIZE_HALF;
                            materialData[material].Sum   += localPos;
                            materialData[material].Count += 1;

                            var      pos = Vector3.Transform(localPos - VoxelMap.SizeInMetresHalf, Quaternion.CreateFromRotationMatrix(VoxelMap.WorldMatrix));
                            Vector3D worldpos;
                            MyVoxelCoordSystems.LocalPositionToWorldPosition((VoxelMap.PositionComp.GetPosition() - (Vector3D)VoxelMap.StorageMin), ref pos, out worldpos);

                            if (materialData[material].Positions == null)
                            {
                                materialData[material].Positions = new List <Vector3D>();
                            }
                            materialData[material].Positions.Add(worldpos);
                        }
                    }
                }
            }

            MyEntityOreDeposit result = null;

            for (int materialIdx = 0; materialIdx < materialData.Length; ++materialIdx)
            {
                if (materialData[materialIdx].Count == 0)
                {
                    continue;
                }

                var material = MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)materialIdx);
                if (material != null && material.IsRare)
                {
                    if (result == null)
                    {
                        result = new MyEntityOreDeposit(VoxelMap, cell);
                    }

                    result.Materials.Add(new MyEntityOreDeposit.Data()
                    {
                        Material             = material,
                        AverageLocalPosition = Vector3D.Transform((materialData[materialIdx].Sum / materialData[materialIdx].Count - VoxelMap.SizeInMetresHalf), Quaternion.CreateFromRotationMatrix(VoxelMap.WorldMatrix)),
                        Positions            = materialData[materialIdx].Positions,
                    });
                }
            }

            if (result != null)
            {
                m_result.Add(result);
            }
            else
            {
                m_emptyCells.Add(cell);
            }

            Array.Clear(materialData, 0, materialData.Length);

            return;
        }