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;
            }
        }
Esempio n. 2
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);
        }
Esempio n. 3
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 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, -1);
                        }
                    }
                }
            }
            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;
        }