void VRage.ModAPI.IMyStorage.ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, Vector3I lodVoxelRangeMin, Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags)
        {
            if ((uint)lodIndex >= (uint)MyCellCoord.MAX_LOD_COUNT)
                return;

            ReadRange(target, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);
        }
        public static MyStorageData GetVoxelCacheInSphere(this IMyVoxelBase Voxel, BoundingSphereD Sphere, out Vector3I refCorner, out Vector3I refMaxCorner)
        {
            if (Voxel == null)
            {
                throw new ArgumentNullException(nameof(Voxel));
            }
            if (Voxel.Storage == null)
            {
                throw new ArgumentException("Voxel.Storage is null");
            }

            BoundingBoxD SphereBound = VoxelHelpers.GetWorldBoundariesForSphere(Sphere);
            Vector3I     minCorner, maxCorner;

            Voxel.MyVoxelGenerator_ComputeShapeBounds(ref SphereBound, out minCorner, out maxCorner);
            Vector3I minCorner1 = minCorner - 1;
            Vector3I maxCorner1 = maxCorner + 1;

            Voxel.Storage_ClampVoxelCoord(ref minCorner1, 1);
            Voxel.Storage_ClampVoxelCoord(ref maxCorner1, 1);
            MyStorageData cache = new MyStorageData(MyStorageDataTypeFlags.ContentAndMaterial);

            cache.Resize(minCorner1, maxCorner1);
            MyVoxelRequestFlags myVoxelRequestFlags = MyVoxelRequestFlags.AdviseCache | MyVoxelRequestFlags.ConsiderContent;

            Voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, minCorner1, maxCorner1, ref myVoxelRequestFlags);
            refCorner    = minCorner1;
            refMaxCorner = maxCorner1;
            return(cache);
        }
Example #3
0
        public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags)
        {
            ProfilerShort.Begin(GetType().Name + ".ReadRange");
            try
            {
                const int SUBRANGE_SIZE_SHIFT = 3;
                const int SUBRANGE_SIZE       = 1 << SUBRANGE_SIZE_SHIFT;
                var       threshold           = new Vector3I(SUBRANGE_SIZE);
                var       rangeSize           = lodVoxelRangeMax - lodVoxelRangeMin + 1;
                if ((dataToRead & MyStorageDataTypeFlags.Content) != 0)
                {
                    target.ClearContent(0);
                }

                if ((rangeSize.X <= threshold.X &&
                     rangeSize.Y <= threshold.Y &&
                     rangeSize.Z <= threshold.Z) || !MyFakes.ENABLE_SPLIT_VOXEL_READ_QUERIES)
                {
                    using (m_lock.AcquireSharedUsing())
                    {
                        ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);
                    }
                }
                else
                {
                    // These optimizations don't work when splitting the range.
                    requestFlags &= ~(MyVoxelRequestFlags.OneMaterial | MyVoxelRequestFlags.ContentChecked);
                    MyVoxelRequestFlags flags = requestFlags;

                    // splitting to smaller ranges to make sure the lock is not held for too long, preventing write on update thread
                    // subranges could be aligned to multiple of their size for possibly better performance
                    var steps = (rangeSize - 1) >> SUBRANGE_SIZE_SHIFT;
                    for (var it = new Vector3I.RangeIterator(ref Vector3I.Zero, ref steps); it.IsValid(); it.MoveNext())
                    {
                        flags = requestFlags;
                        var offset = it.Current << SUBRANGE_SIZE_SHIFT;
                        var min    = lodVoxelRangeMin + offset;
                        var max    = min + SUBRANGE_SIZE - 1;
                        Vector3I.Min(ref max, ref lodVoxelRangeMax, out max);
                        Debug.Assert(min.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax));
                        Debug.Assert(max.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax));
                        using (m_lock.AcquireSharedUsing())
                        {
                            ReadRangeInternal(target, ref offset, dataToRead, lodIndex, ref min, ref max, ref flags);
                        }
                    }

                    // If the storage is consistent this should be fine.
                    requestFlags = flags;
                }
            }
            finally
            {
                ProfilerShort.End();
            }
        }
Example #4
0
 public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
 {
     using (voxelMap.Pin())
     {
         if (!voxelMap.MarkedForClose)
         {
             Vector3I vectori;
             Vector3I maxCorner;
             Vector3I minCorner;
             GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori);
             if (m_cache == null)
             {
                 m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
             }
             Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref vectori);
             while (true)
             {
                 Vector3I vectori2;
                 Vector3I vectori3;
                 if (!it.IsValid())
                 {
                     MySandboxGame.Static.Invoke(delegate {
                         if (voxelMap.Storage != null)
                         {
                             voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All);
                         }
                     }, "PaintInShape notify");
                     break;
                 }
                 GetCellCorners(ref minCorner, ref maxCorner, ref it, out vectori2, out vectori3);
                 m_cache.Resize(vectori2, vectori3);
                 MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent;
                 voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, vectori2, vectori3, ref considerContent);
                 Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori2, ref vectori3);
                 while (true)
                 {
                     Vector3D vectord;
                     if (!iterator2.IsValid())
                     {
                         voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, vectori2, vectori3, false, true);
                         it.MoveNext();
                         break;
                     }
                     Vector3I p = iterator2.Current - vectori2;
                     MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref iterator2.Current, out vectord);
                     if ((shape.GetVolume(ref vectord) > 0.5f) && (m_cache.Material(ref p) != 0xff))
                     {
                         m_cache.Material(ref p, materialIdx);
                     }
                     iterator2.MoveNext();
                 }
             }
         }
     }
 }
        private void ReadDatForChunk(VoxelChunk chunk, MyStorageDataTypeFlags data)
        {
            var rangeStart = chunk.Coords << VoxelChunk.SizeBits;
            var rangeEnd   = ((chunk.Coords + 1) << VoxelChunk.SizeBits) - 1;

            MyStorageData storage = chunk.MakeData();

            MyVoxelRequestFlags flags = 0;

            ReadRangeInternal(storage, ref Vector3I.Zero, data, 0, ref rangeStart, ref rangeEnd, ref flags);

            chunk.Cached |= data;
        }
Example #6
0
        void IMyOctreeLeafNode.ReadRange(MyStorageData target, MyStorageDataTypeFlags types, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod, ref MyVoxelRequestFlags flags)
        {
            var lodShift = m_cell.Lod - lodIndex;
            var leafMinInLod = m_cell.CoordInLod << lodShift;
            var min = minInLod + leafMinInLod;
            var max = maxInLod + leafMinInLod;
            AssertRangeIsInside(lodIndex, ref min, ref max);
            ProfilerShort.Begin("MyProviderLeaf.ReadRange");
            MyVoxelDataRequest req = new MyVoxelDataRequest() {
                Target = target,
                Offset = writeOffset,
                Lod = lodIndex,
                minInLod = min,
                maxInLod = max,
                RequestFlags = flags,
                RequestedData = types
            };

            m_provider.ReadRange(ref req);
            flags = req.Flags;
            ProfilerShort.End();
        }
Example #7
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);
            }
        }
        protected override void ReadRangeInternal(MyStorageData target, ref Vector3I targetWriteOffset,
            MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelCoordStart, ref Vector3I lodVoxelCoordEnd, ref MyVoxelRequestFlags flags)
        {
            bool hasLod = lodIndex <= (m_treeHeight + LeafLodCount);
            Debug.Assert(dataToRead != MyStorageDataTypeFlags.None);

            MyVoxelRequestFlags cflags = 0;
            MyVoxelRequestFlags mflags = 0;

            if ((dataToRead & MyStorageDataTypeFlags.Content) != 0)
            {
                if (hasLod)
                {
                    cflags = flags;
                    ReadRange(target, ref targetWriteOffset, MyStorageDataTypeFlags.Content,
                        m_treeHeight, m_contentNodes, m_contentLeaves, lodIndex, ref lodVoxelCoordStart, ref lodVoxelCoordEnd, ref cflags);
                }
            }

            if ((dataToRead.Requests(MyStorageDataTypeEnum.Material) || dataToRead.Requests(MyStorageDataTypeEnum.Occlusion))
                && !cflags.HasFlag(MyVoxelRequestFlags.MaterialForContent | MyVoxelRequestFlags.EmptyContent))
            {
                if (hasLod)
                {
                    mflags = flags;
                    ReadRange(target, ref targetWriteOffset, dataToRead.Without(MyStorageDataTypeEnum.Content),
                        m_treeHeight, m_materialNodes, m_materialLeaves, lodIndex, ref lodVoxelCoordStart, ref lodVoxelCoordEnd, ref mflags);
                }
            }

            // Material and content flags are safe to merge
            flags = cflags | mflags;
        }
        public static List <Vector3I> GetVoxelPointsInSphere(this IMyVoxelBase Voxel, BoundingSphereD Sphere, out MyStorageData cache)
        {
            if (Voxel == null)
            {
                throw new ArgumentNullException(nameof(Voxel));
            }
            if (Voxel.Storage == null)
            {
                throw new ArgumentException("Voxel.Storage is null");
            }

            List <Vector3I> VoxelPoints = new List <Vector3I>();
            MyVoxelBase     myVoxel     = (Voxel as MyVoxelBase);

            BoundingBoxD SphereBound = VoxelHelpers.GetWorldBoundariesForSphere(Sphere);
            Vector3      CoordsSystemOutValue;

            MyVoxelCoordSystems.WorldPositionToLocalPosition(Sphere.Center, Voxel.PositionComp.WorldMatrix, Voxel.PositionComp.WorldMatrixInvScaled, myVoxel.SizeInMetresHalf, out CoordsSystemOutValue);
            Vector3I VoxelInSphereCenter = new Vector3I(CoordsSystemOutValue / 1f) + myVoxel.StorageMin;

            // --- I don't know what exactly this vector magic does, this was salvaged from the game's source ---
            // The only idea I have is that from the engine's perspective, every asteroid and planet consist of
            // voxel points (or just "voxels") which are 1 m^3 (2x2x2 small ship blocks) cubes aligned to
            // the world's XYZ axes, which may have different "filling" levels from 0 (empty) to 255.
            // The smooth surfaces we see on asteroids are a result of postprocessing of semi-filled voxel cubes
            // on the outer edges of voxel maps, though this post-processing also affects physics (e.g. collisions).
            // Voxels, like cube grids, have their local coordinate systems, which are built relative to the voxel map's
            // left bottom corner. If you want to find or work with a specific voxel point at a given world position,
            // you have to convert the world coordinates to the voxel map's local coordinates,
            // which can be done using the whitelisted static class
            /// <see cref="MyVoxelCoordSystems"/>
            Vector3I minCorner, maxCorner;

            Voxel.MyVoxelGenerator_ComputeShapeBounds(ref SphereBound, out minCorner, out maxCorner);
            Vector3I minCorner1 = minCorner - 1;
            Vector3I maxCorner1 = maxCorner + 1;

            Voxel.Storage_ClampVoxelCoord(ref minCorner1, 1);
            Voxel.Storage_ClampVoxelCoord(ref maxCorner1, 1);
            cache = new MyStorageData(MyStorageDataTypeFlags.ContentAndMaterial);
            cache.Resize(minCorner1, maxCorner1);
            MyVoxelRequestFlags myVoxelRequestFlags = MyVoxelRequestFlags.AdviseCache | MyVoxelRequestFlags.ConsiderContent;

            Voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, minCorner1, maxCorner1, ref myVoxelRequestFlags);
            // ---

            Vector3I voxelpoint;

            voxelpoint.X = minCorner.X;
            while (voxelpoint.X <= maxCorner.X)
            {
                voxelpoint.Y = minCorner.Y;
                while (voxelpoint.Y <= maxCorner.Y)
                {
                    voxelpoint.Z = minCorner.Z;
                    while (voxelpoint.Z <= maxCorner.Z)
                    {
                        if (Vector3D.DistanceSquared(VoxelInSphereCenter, voxelpoint) <= Sphere.Radius * Sphere.Radius && cache.Content(ref voxelpoint) > 0)
                        {
                            VoxelPoints.Add(voxelpoint);
                        }
                        voxelpoint.Z++;
                    }
                    voxelpoint.Y++;
                }
                voxelpoint.X++;
            }

            return(VoxelPoints);
        }
Example #10
0
        void VRage.ModAPI.IMyStorage.ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, Vector3I lodVoxelRangeMin, Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags)
        {
            if ((uint)lodIndex >= (uint)MyCellCoord.MAX_LOD_COUNT)
            {
                return;
            }

            ReadRange(target, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);
        }
Example #11
0
        public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax)
        {
            MyVoxelRequestFlags flags = 0;

            ReadRange(target, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref flags);
        }
Example #12
0
 protected abstract void ReadRangeInternal(MyStorageData target, ref Vector3I targetWriteRange, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags);
Example #13
0
 public static void FillInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
 {
     using (voxelMap.Pin())
     {
         if (!voxelMap.MarkedForClose)
         {
             Vector3I vectori;
             Vector3I maxCorner;
             Vector3I minCorner;
             ulong    num = 0UL;
             GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori);
             minCorner = Vector3I.Max(Vector3I.One, minCorner);
             maxCorner = Vector3I.Max(minCorner, maxCorner - Vector3I.One);
             if (m_cache == null)
             {
                 m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
             }
             Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref vectori);
             while (true)
             {
                 Vector3I vectori2;
                 Vector3I vectori3;
                 if (!it.IsValid())
                 {
                     if (num > 0L)
                     {
                         BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
                         MySandboxGame.Static.Invoke(delegate {
                             if (voxelMap.Storage != null)
                             {
                                 voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All);
                                 NotifyVoxelChanged(MyVoxelBase.OperationType.Fill, voxelMap, ref cutOutBox);
                             }
                         }, "FillInShape Notify");
                     }
                     break;
                 }
                 GetCellCorners(ref minCorner, ref maxCorner, ref it, out vectori2, out vectori3);
                 Vector3I originalValue = vectori3;
                 voxelMap.Storage.ClampVoxelCoord(ref vectori2, 0);
                 voxelMap.Storage.ClampVoxelCoord(ref vectori3, 0);
                 ClampingInfo info  = CheckForClamping(vectori2, vectori2);
                 ClampingInfo info2 = CheckForClamping(originalValue, vectori3);
                 m_cache.Resize(vectori2, vectori3);
                 MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent;
                 voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, vectori2, vectori3, ref considerContent);
                 ulong num2 = 0UL;
                 Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori2, ref vectori3);
                 while (true)
                 {
                     if (!iterator2.IsValid())
                     {
                         if (num2 > 0L)
                         {
                             RemoveSmallVoxelsUsingChachedVoxels();
                             voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.All, vectori2, vectori3, false, true);
                         }
                         num += num2;
                         it.MoveNext();
                         break;
                     }
                     Vector3I p    = iterator2.Current - vectori2;
                     byte     num3 = m_cache.Content(ref p);
                     if ((num3 != 0xff) || (m_cache.Material(ref p) != materialIdx))
                     {
                         if ((((iterator2.Current.X == vectori2.X) && info.X) || (((iterator2.Current.X == vectori3.X) && info2.X) || (((iterator2.Current.Y == vectori2.Y) && info.Y) || (((iterator2.Current.Y == vectori3.Y) && info2.Y) || ((iterator2.Current.Z == vectori2.Z) && info.Z))))) || ((iterator2.Current.Z == vectori3.Z) && info2.Z))
                         {
                             if (num3 != 0)
                             {
                                 m_cache.Material(ref p, materialIdx);
                             }
                         }
                         else
                         {
                             Vector3D vectord;
                             MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref iterator2.Current, out vectord);
                             float volume = shape.GetVolume(ref vectord);
                             if (volume > 0f)
                             {
                                 long num6 = Math.Max(num3, (int)(volume * 255f));
                                 m_cache.Content(ref p, (byte)num6);
                                 if (num6 != 0)
                                 {
                                     m_cache.Material(ref p, materialIdx);
                                 }
                                 num2 += ((ulong)num6) - num3;
                             }
                         }
                     }
                     iterator2.MoveNext();
                 }
             }
         }
     }
 }
Example #14
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);
            }
        }
Example #15
0
 public static unsafe 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, bool skipCache = false)
 {
     if ((!MySession.Static.EnableVoxelDestruction || ((voxelMap == null) || (voxelMap.Storage == null))) || (shape == null))
     {
         voxelsCountInPercent = 0f;
         voxelMaterial        = null;
     }
     else
     {
         Vector3I vectori3;
         Vector3I vectori4;
         Vector3I maxCorner;
         Vector3I minCorner;
         int      num            = 0;
         int      num2           = 0;
         MatrixD  transformation = shape.Transformation;
         MatrixD  xd2            = transformation * voxelMap.PositionComp.WorldMatrixInvScaled;
         MatrixD *xdPtr1         = (MatrixD *)ref xd2;
         xdPtr1.Translation  += voxelMap.SizeInMetresHalf;
         shape.Transformation = xd2;
         BoundingBoxD worldBoundaries = shape.GetWorldBoundaries();
         ComputeShapeBounds(voxelMap, ref worldBoundaries, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner);
         bool     flag       = (exactCutOutMaterials != null) | applyDamageMaterial;
         Vector3I voxelCoord = minCorner - 1;
         Vector3I vectori2   = (Vector3I)(maxCorner + 1);
         voxelMap.Storage.ClampVoxelCoord(ref voxelCoord, 1);
         voxelMap.Storage.ClampVoxelCoord(ref vectori2, 1);
         if (m_cache == null)
         {
             m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
         }
         m_cache.Resize(voxelCoord, vectori2);
         MyVoxelRequestFlags requestFlags = (skipCache ? ((MyVoxelRequestFlags)0) : MyVoxelRequestFlags.AdviseCache) | (flag ? MyVoxelRequestFlags.ConsiderContent : ((MyVoxelRequestFlags)0));
         voxelMap.Storage.ReadRange(m_cache, flag ? MyStorageDataTypeFlags.All : MyStorageDataTypeFlags.Content, 0, voxelCoord, vectori2, ref requestFlags);
         if (exactCutOutMaterials != null)
         {
             vectori3      = (Vector3I)(m_cache.Size3D / 2);
             voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref vectori3));
         }
         else
         {
             vectori3      = (Vector3I)((voxelCoord + vectori2) / 2);
             voxelMaterial = voxelMap.Storage.GetMaterialAt(ref vectori3);
         }
         MyVoxelMaterialDefinition key = null;
         vectori4.X = minCorner.X;
         while (vectori4.X <= maxCorner.X)
         {
             vectori4.Y = minCorner.Y;
             while (true)
             {
                 if (vectori4.Y > maxCorner.Y)
                 {
                     int *numPtr3 = (int *)ref vectori4.X;
                     numPtr3[0]++;
                     break;
                 }
                 vectori4.Z = minCorner.Z;
                 while (true)
                 {
                     if (vectori4.Z > maxCorner.Z)
                     {
                         int *numPtr2 = (int *)ref vectori4.Y;
                         numPtr2[0]++;
                         break;
                     }
                     Vector3I p         = vectori4 - voxelCoord;
                     int      linearIdx = m_cache.ComputeLinear(ref p);
                     byte     num4      = m_cache.Content(linearIdx);
                     if (num4 != 0)
                     {
                         Vector3D voxelPosition = (Vector3D)((vectori4 - voxelMap.StorageMin) * 1.0);
                         float    volume        = shape.GetVolume(ref voxelPosition);
                         if (volume != 0f)
                         {
                             int num7 = Math.Max(num4 - ((int)(volume * 255f)), 0);
                             int num8 = num4 - num7;
                             if ((num4 / 10) != (num7 / 10))
                             {
                                 if (!onlyCheck && !onlyApplyMaterial)
                                 {
                                     m_cache.Content(linearIdx, (byte)num7);
                                 }
                                 num  += num4;
                                 num2 += num8;
                                 byte materialIndex = m_cache.Material(linearIdx);
                                 if (num7 == 0)
                                 {
                                     m_cache.Material(linearIdx, 0xff);
                                 }
                                 if (materialIndex != 0xff)
                                 {
                                     if (flag)
                                     {
                                         key = MyDefinitionManager.Static.GetVoxelMaterialDefinition(materialIndex);
                                     }
                                     if (exactCutOutMaterials != null)
                                     {
                                         int num10;
                                         exactCutOutMaterials.TryGetValue(key, out num10);
                                         exactCutOutMaterials[key] = num10 + (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? ((int)(num8 * 3.9f)) : num8);
                                     }
                                 }
                             }
                         }
                     }
                     int *numPtr1 = (int *)ref vectori4.Z;
                     numPtr1[0]++;
                 }
             }
         }
         if ((((num2 > 0) & updateSync) && Sync.IsServer) && !onlyCheck)
         {
             shape.SendDrillCutOutRequest(voxelMap, applyDamageMaterial);
         }
         if ((num2 > 0) && !onlyCheck)
         {
             RemoveSmallVoxelsUsingChachedVoxels();
             MyStorageDataTypeFlags all = MyStorageDataTypeFlags.All;
             if (MyFakes.LOG_NAVMESH_GENERATION && (MyAIComponent.Static.Pathfinding != null))
             {
                 MyAIComponent.Static.Pathfinding.GetPathfindingLog().LogStorageWrite(voxelMap, m_cache, all, voxelCoord, vectori2);
             }
             voxelMap.Storage.WriteRange(m_cache, all, voxelCoord, vectori2, false, skipCache);
         }
         voxelsCountInPercent = (num > 0f) ? (((float)num2) / ((float)num)) : 0f;
         if (num2 > 0)
         {
             BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
             MySandboxGame.Static.Invoke(delegate {
                 if (voxelMap.Storage != null)
                 {
                     voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All);
                     NotifyVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, ref cutOutBox);
                 }
             }, "CutOutShapeWithProperties notify");
         }
         shape.Transformation = transformation;
     }
 }
Example #16
0
 public static unsafe void ChangeMaterialsInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx, bool[] materialsToChange)
 {
     if ((voxelMap != null) && (shape != null))
     {
         using (voxelMap.Pin())
         {
             if (!voxelMap.MarkedForClose)
             {
                 Vector3I vectori;
                 Vector3I vectori2;
                 Vector3I vectori5;
                 MatrixD  xd     = shape.Transformation * voxelMap.PositionComp.WorldMatrixInvScaled;
                 MatrixD *xdPtr1 = (MatrixD *)ref xd;
                 xdPtr1.Translation  += voxelMap.SizeInMetresHalf;
                 shape.Transformation = xd;
                 BoundingBoxD worldBoundaries = shape.GetWorldBoundaries();
                 ComputeShapeBounds(voxelMap, ref worldBoundaries, Vector3.Zero, voxelMap.Storage.Size, out vectori, out vectori2);
                 Vector3I voxelCoord = vectori - 1;
                 Vector3I vectori4   = (Vector3I)(vectori2 + 1);
                 voxelMap.Storage.ClampVoxelCoord(ref voxelCoord, 1);
                 voxelMap.Storage.ClampVoxelCoord(ref vectori4, 1);
                 if (m_cache == null)
                 {
                     m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
                 }
                 m_cache.Resize(voxelCoord, vectori4);
                 MyVoxelRequestFlags requestFlags = MyVoxelRequestFlags.AdviseCache | MyVoxelRequestFlags.ConsiderContent;
                 voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, voxelCoord, vectori4, ref requestFlags);
                 vectori5.X = vectori.X;
                 while (vectori5.X <= vectori2.X)
                 {
                     vectori5.Y = vectori.Y;
                     while (true)
                     {
                         if (vectori5.Y > vectori2.Y)
                         {
                             int *numPtr3 = (int *)ref vectori5.X;
                             numPtr3[0]++;
                             break;
                         }
                         vectori5.Z = vectori.Z;
                         while (true)
                         {
                             if (vectori5.Z > vectori2.Z)
                             {
                                 int *numPtr2 = (int *)ref vectori5.Y;
                                 numPtr2[0]++;
                                 break;
                             }
                             Vector3I p         = vectori5 - vectori;
                             int      linearIdx = m_cache.ComputeLinear(ref p);
                             byte     index     = m_cache.Material(linearIdx);
                             if (materialsToChange[index])
                             {
                                 Vector3D vectord;
                                 MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref vectori5, out vectord);
                                 if ((shape.GetVolume(ref vectord) > 0.5f) && (m_cache.Material(ref p) != 0xff))
                                 {
                                     m_cache.Material(ref p, materialIdx);
                                 }
                             }
                             int *numPtr1 = (int *)ref vectori5.Z;
                             numPtr1[0]++;
                         }
                     }
                 }
             }
         }
     }
 }
Example #17
0
 public static void CutOutShape(MyVoxelBase voxelMap, MyShape shape, bool voxelHand = false)
 {
     if (MySession.Static.EnableVoxelDestruction || MySession.Static.HighSimulationQuality)
     {
         using (voxelMap.Pin())
         {
             if (!voxelMap.MarkedForClose)
             {
                 Vector3I vectori;
                 Vector3I maxCorner;
                 Vector3I minCorner;
                 GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori);
                 ulong num = 0UL;
                 if (m_cache == null)
                 {
                     m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
                 }
                 Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref vectori);
                 while (true)
                 {
                     Vector3I vectori2;
                     Vector3I vectori3;
                     if (!it.IsValid())
                     {
                         if (num > 0L)
                         {
                             BoundingBoxD cutOutBox = shape.GetWorldBoundaries();
                             MySandboxGame.Static.Invoke(delegate {
                                 if (voxelMap.Storage != null)
                                 {
                                     voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All);
                                     NotifyVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, ref cutOutBox);
                                 }
                             }, "CutOutShape notify");
                         }
                         break;
                     }
                     GetCellCorners(ref minCorner, ref maxCorner, ref it, out vectori2, out vectori3);
                     Vector3I voxelCoord = vectori2 - 1;
                     Vector3I vectori5   = (Vector3I)(vectori3 + 1);
                     voxelMap.Storage.ClampVoxelCoord(ref voxelCoord, 1);
                     voxelMap.Storage.ClampVoxelCoord(ref vectori5, 1);
                     ulong num2 = 0UL;
                     m_cache.Resize(voxelCoord, vectori5);
                     MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent;
                     voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, voxelCoord, vectori5, ref considerContent);
                     Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori2, ref vectori3);
                     while (true)
                     {
                         if (!iterator2.IsValid())
                         {
                             if (num2 > 0L)
                             {
                                 RemoveSmallVoxelsUsingChachedVoxels();
                                 voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.All, voxelCoord, vectori5, false, true);
                             }
                             num += num2;
                             it.MoveNext();
                             break;
                         }
                         Vector3I p    = iterator2.Current - voxelCoord;
                         byte     num3 = m_cache.Content(ref p);
                         if (num3 != 0)
                         {
                             Vector3D vectord;
                             MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref iterator2.Current, out vectord);
                             float volume = shape.GetVolume(ref vectord);
                             if (volume != 0f)
                             {
                                 int   num5 = Math.Min((int)(255f - (volume * 255f)), num3);
                                 ulong num6 = (ulong)Math.Abs((int)(num3 - num5));
                                 m_cache.Content(ref p, (byte)num5);
                                 if (num5 == 0)
                                 {
                                     m_cache.Material(ref p, 0xff);
                                 }
                                 num2 += num6;
                             }
                         }
                         iterator2.MoveNext();
                     }
                 }
             }
         }
     }
 }
        private unsafe void ReadRange(
            MyStorageData target,
            ref Vector3I targetWriteOffset,
            MyStorageDataTypeFlags types,
            int treeHeight,
            Dictionary<UInt64, MyOctreeNode> nodes,
            Dictionary<UInt64, IMyOctreeLeafNode> leaves,
            int lodIndex,
            ref Vector3I minInLod,
            ref Vector3I maxInLod,
            ref MyVoxelRequestFlags flags)
        {
            int stackIdx = 0;
            int stackSize = MySparseOctree.EstimateStackSize(treeHeight);
            MyCellCoord* stack = stackalloc MyCellCoord[stackSize];
            MyCellCoord data = new MyCellCoord(treeHeight + LeafLodCount, ref Vector3I.Zero);
            stack[stackIdx++] = data;
            MyCellCoord cell = new MyCellCoord();

            var octreeType = types.Requests(MyStorageDataTypeEnum.Content) ? MyStorageDataTypeEnum.Content : MyStorageDataTypeEnum.Material;

            FillOutOfBounds(target, octreeType, ref targetWriteOffset, lodIndex, minInLod, maxInLod);

            while (stackIdx > 0)
            {
                Debug.Assert(stackIdx <= stackSize);
                data = stack[--stackIdx];

                cell.Lod = Math.Max(data.Lod - LeafLodCount, 0);
                cell.CoordInLod = data.CoordInLod;

                int lodDiff;
                IMyOctreeLeafNode leaf;
                if (leaves.TryGetValue(cell.PackId64(), out leaf))
                {
                    lodDiff = data.Lod - lodIndex;
                    var rangeMinInDataLod = minInLod >> lodDiff;
                    var rangeMaxInDataLod = maxInLod >> lodDiff;
                    if (data.CoordInLod.IsInsideInclusive(ref rangeMinInDataLod, ref rangeMaxInDataLod))
                    {
                        var nodePosInLod = data.CoordInLod << lodDiff;
                        var writeOffset = nodePosInLod - minInLod;
                        Vector3I.Max(ref writeOffset, ref Vector3I.Zero, out writeOffset);
                        writeOffset += targetWriteOffset;
                        var lodSizeMinusOne = new Vector3I((1 << lodDiff) - 1);

                        Vector3I minInLeaf = minInLod - nodePosInLod;
                        Vector3I maxInLeaf = maxInLod - nodePosInLod;
                        if (!minInLeaf.IsInsideInclusive(Vector3I.Zero, lodSizeMinusOne) || !maxInLeaf.IsInsideInclusive(Vector3I.Zero, lodSizeMinusOne))
                        {
                            minInLeaf = Vector3I.Clamp(minInLod - nodePosInLod, Vector3I.Zero, lodSizeMinusOne);
                            maxInLeaf = Vector3I.Clamp(maxInLod - nodePosInLod, Vector3I.Zero, lodSizeMinusOne);
                            // No Optimizations when not reading entirelly from the provider because the octree can't take it.
                            flags &= MyVoxelRequestFlags.SurfaceMaterial;
                        }


                        leaf.ReadRange(target, types, ref writeOffset, lodIndex, ref minInLeaf, ref maxInLeaf, ref flags);
                        // Occlusion is not stored in tree, we just read from provider
                        if (!leaf.ReadOnly && types.Requests(MyStorageDataTypeEnum.Occlusion))
                        {
                            minInLeaf += nodePosInLod;
                            maxInLeaf += nodePosInLod;
                            ReadFromProvider(target, MyStorageDataTypeFlags.Occlusion, ref writeOffset, lodIndex, ref minInLeaf, ref maxInLeaf, ref flags);
                        }
                    }
                    continue;
                }

                cell.Lod -= 1;
                lodDiff = data.Lod - 1 - lodIndex;

                MyOctreeNode node;
                if (nodes.TryGetValue(cell.PackId64(), out node) == false)
                {
                    Debug.Fail("invalid querry for node");
                    continue;
                }
                var min = minInLod >> lodDiff;
                var max = maxInLod >> lodDiff;
                var nodePositionInChild = data.CoordInLod << 1;
                min -= nodePositionInChild;
                max -= nodePositionInChild;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    Vector3I childPosRelative;
                    ComputeChildCoord(i, out childPosRelative);
                    if (!childPosRelative.IsInsideInclusive(ref min, ref max))
                        continue;
                    if (lodIndex < data.Lod && node.HasChild(i))
                    {
                        Debug.Assert(stackIdx < stackSize);
                        stack[stackIdx++] = new MyCellCoord(data.Lod - 1, nodePositionInChild + childPosRelative);
                    }
                    else
                    {
                        // No Optimizations when not reading entirelly from the provider because the octree can't take it.
                        flags &= MyVoxelRequestFlags.SurfaceMaterial;

                        var childMin = nodePositionInChild + childPosRelative;
                        childMin <<= lodDiff;
                        var writeOffset = childMin - minInLod;
                        Vector3I.Max(ref writeOffset, ref Vector3I.Zero, out writeOffset);
                        writeOffset += targetWriteOffset;
                        var nodeData = node.GetData(i);
                        if (lodDiff == 0)
                        {
                            target.Set(octreeType, ref writeOffset, nodeData);
                        }
                        else
                        {
                            var childMax = childMin + ((1 << lodDiff) - 1);
                            Vector3I.Max(ref childMin, ref minInLod, out childMin);
                            Vector3I.Min(ref childMax, ref maxInLod, out childMax);
                            for (int z = childMin.Z; z <= childMax.Z; ++z)
                            for (int y = childMin.Y; y <= childMax.Y; ++y)
                            for (int x = childMin.X; x <= childMax.X; ++x)
                            {
                                Vector3I write = writeOffset;
                                write.X += x - childMin.X;
                                write.Y += y - childMin.Y;
                                write.Z += z - childMin.Z;
                                target.Set(octreeType, ref write, nodeData);
                            }
                        }
                    }
                }
            }
        }
        private void ReadFromProvider(MyStorageData target, MyStorageDataTypeFlags types, ref Vector3I writeOffset, int lodIndex, ref Vector3I min, ref Vector3I max, ref MyVoxelRequestFlags flags)
        {
            ProfilerShort.Begin("MyProviderLeaf.ReadRange");
            MyVoxelDataRequest req = new MyVoxelDataRequest()
            {
                Target = target,
                Offset = writeOffset,
                Lod = lodIndex,
                minInLod = min,
                maxInLod = max,
                RequestFlags = flags,
                RequestedData = types
            };

            DataProvider.ReadRange(ref req);
            flags = req.Flags;
            ProfilerShort.End();
        }
        public bool GetVoxelContent(IMyVoxelBase voxel, Vector3D position, out byte content, out byte material, MyStorageData cache = null, Vector3D?endpoint = null, MyVoxelRequestFlags flags = 0)
        {
            if (endpoint == null)
            {
                endpoint = position;
            }

            content  = 0;
            material = 0;

            if (voxel == null || voxel.Storage == null)
            {
                return(false);
            }

            if (cache == null)
            {
                cache = new MyStorageData();
            }

            var      targetMin = position;
            Vector3D targetMax = endpoint.Value;
            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);

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

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

            return(cache.ContainsVoxelsAboveIsoLevel());
        }
Example #21
0
 protected abstract void ReadRangeInternal(MyStorageData target, ref Vector3I targetWriteRange, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags);
 public static bool HasFlags(this MyVoxelRequestFlags self, MyVoxelRequestFlags other)
 {
     return (self & other) == other;
 }
 public static bool HasFlags(this MyVoxelRequestFlags self, MyVoxelRequestFlags other)
 {
     return((self & other) == other);
 }
Example #24
0
        public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags)
        {
            ProfilerShort.Begin(GetType().Name + ".ReadRange");

            if ((dataToRead & MyStorageDataTypeFlags.Content) != 0)
            {
                target.ClearContent(0);
            }

            if (requestFlags.HasFlags(MyVoxelRequestFlags.AdviseCache) && lodIndex == 0 && CachedWrites)
            {
                ReadRangeAdviseCache(target, dataToRead, ref lodVoxelRangeMin, ref lodVoxelRangeMax);
                ProfilerShort.End();
                return;
            }

            if (CachedWrites && lodIndex <= VoxelChunk.SizeBits && m_cachedChunks.Count > 0)
            {
                // read occlusion separate
                if (dataToRead.Requests(MyStorageDataTypeEnum.Occlusion))
                {
                    using (m_storageLock.AcquireSharedUsing())
                        ReadRangeInternal(target, ref Vector3I.Zero, MyStorageDataTypeFlags.Occlusion, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);

                    dataToRead ^= MyStorageDataTypeFlags.Occlusion;
                }

                if (m_tmpChunks == null)
                {
                    m_tmpChunks = new List <VoxelChunk>();
                }

                var lodDiff = VoxelChunk.SizeBits - lodIndex;

                // We fetch which chunks overlap our current range from the chunk tree, then we read all data from storage and apply those changes
                var querybb = new BoundingBox(lodVoxelRangeMin << lodIndex, lodVoxelRangeMax << lodIndex);

                using (m_cacheLock.AcquireSharedUsing())
                    m_cacheMap.OverlapAllBoundingBox(ref querybb, m_tmpChunks, 0, false);

                if (m_tmpChunks.Count > 0)
                {
                    var chunkMin = lodVoxelRangeMin >> lodDiff;
                    var chunkMax = lodVoxelRangeMax >> lodDiff;

                    bool readFromStorage = false;

                    if ((chunkMax - chunkMin + 1).Size > m_tmpChunks.Count)
                    {
                        using (m_storageLock.AcquireSharedUsing())
                            ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);
                        readFromStorage = true;
                    }

                    for (int i = 0; i < m_tmpChunks.Count; ++i)
                    {
                        var chunk = m_tmpChunks[i];
                        var pos   = chunk.Coords;

                        var celPos = pos << lodDiff;

                        var lodCkStart = pos << lodDiff;
                        lodCkStart = Vector3I.Max(lodCkStart, lodVoxelRangeMin);

                        var targetOffset = lodCkStart - lodVoxelRangeMin;

                        var lodCkEnd = ((pos + 1) << lodDiff) - 1;
                        lodCkEnd = Vector3I.Min(lodCkEnd, lodVoxelRangeMax);

                        lodCkStart -= celPos;
                        lodCkEnd   -= celPos;

                        if ((chunk.Cached & dataToRead) != dataToRead && !readFromStorage)
                        {
                            using (m_storageLock.AcquireSharedUsing())
                                if ((chunk.Cached & dataToRead) != dataToRead)
                                {
                                    ReadDatForChunk(chunk, dataToRead);
                                }
                        }

                        using (chunk.Lock.AcquireSharedUsing())
                            chunk.ReadLod(target, !readFromStorage ? dataToRead : dataToRead & chunk.Cached, ref targetOffset, lodIndex, ref lodCkStart, ref lodCkEnd);
                    }

                    m_tmpChunks.Clear();
                    ProfilerShort.End();
                    return;
                }
            }

            // all else
            using (m_storageLock.AcquireSharedUsing())
                ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);

            ProfilerShort.End();
        }
 void IMyOctreeLeafNode.ReadRange(MyStorageData target, MyStorageDataTypeFlags types, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod, ref MyVoxelRequestFlags flags)
 {
     m_octree.ReadRange(target, m_dataType, ref writeOffset, lodIndex, ref minInLod, ref maxInLod);
 }
Example #26
0
        private static unsafe void MakeCraterInternal(MyVoxelBase voxelMap, ref BoundingSphereD sphere, ref Vector3 direction, MyVoxelMaterialDefinition material)
        {
            Vector3I vectori;
            Vector3I vectori2;
            Vector3I vectori5;
            Vector3  vector        = Vector3.Normalize(sphere.Center - voxelMap.RootVoxel.WorldMatrix.Translation);
            Vector3D worldPosition = sphere.Center - ((sphere.Radius - 1.0) * 1.2999999523162842);
            Vector3D vectord2      = sphere.Center + ((sphere.Radius + 1.0) * 1.2999999523162842);

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref worldPosition, out vectori);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref vectord2, out vectori2);
            voxelMap.Storage.ClampVoxelCoord(ref vectori, 1);
            voxelMap.Storage.ClampVoxelCoord(ref vectori2, 1);
            Vector3I lodVoxelRangeMin = (Vector3I)(vectori + voxelMap.StorageMin);
            Vector3I lodVoxelRangeMax = (Vector3I)(vectori2 + voxelMap.StorageMin);
            bool     flag             = false;

            if (m_cache == null)
            {
                m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
            }
            m_cache.Resize(vectori, vectori2);
            MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent;

            voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, lodVoxelRangeMin, lodVoxelRangeMax, ref considerContent);
            int      num         = 0;
            Vector3I p           = (Vector3I)((vectori2 - vectori) / 2);
            byte     materialIdx = m_cache.Material(ref p);
            float    num3        = 1f - Vector3.Dot(vector, direction);
            Vector3  vector2     = ((Vector3)sphere.Center) - ((vector * ((float)sphere.Radius)) * 1.1f);
            float    num4        = (float)(sphere.Radius * 1.5);
            float    num5        = num4 * num4;
            float    num6        = 0.5f * ((2f * num4) + 0.5f);
            float    num7        = 0.5f * ((-2f * num4) + 0.5f);
            Vector3  vector3     = (vector2 + ((vector * ((float)sphere.Radius)) * (0.7f + num3))) + ((direction * ((float)sphere.Radius)) * 0.65f);
            float    radius      = (float)sphere.Radius;
            float    num9        = radius * radius;
            float    num10       = 0.5f * ((2f * radius) + 0.5f);
            float    num11       = 0.5f * ((-2f * radius) + 0.5f);
            Vector3  vector4     = (vector2 + ((vector * ((float)sphere.Radius)) * num3)) + ((direction * ((float)sphere.Radius)) * 0.3f);
            float    num12       = (float)(sphere.Radius * 0.10000000149011612);
            float    num13       = num12 * num12;
            float    num14       = 0.5f * ((2f * num12) + 0.5f);

            vectori5.Z = vectori.Z;
            p.Z        = 0;
            goto TR_003C;
TR_0005:
            int *numPtr1 = (int *)ref vectori5.X;

            numPtr1[0]++;
            int *numPtr2 = (int *)ref p.X;

            numPtr2[0]++;
TR_0036:
            while (true)
            {
                Vector3D vectord3;
                byte     num18;
                if (vectori5.X > vectori2.X)
                {
                    int *numPtr3 = (int *)ref vectori5.Y;
                    numPtr3[0]++;
                    int *numPtr4 = (int *)ref p.Y;
                    numPtr4[0]++;
                    break;
                }
                MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref vectori5, out vectord3);
                byte num15 = m_cache.Content(ref p);
                if (num15 != 0xff)
                {
                    byte  num22;
                    float num20 = (float)(vectord3 - vector2).LengthSquared();
                    float num21 = num20 - num5;
                    if (num21 > num6)
                    {
                        num22 = 0;
                    }
                    else if (num21 < num7)
                    {
                        num22 = 0xff;
                    }
                    else
                    {
                        float num23 = (float)Math.Sqrt((num20 + num5) - ((2f * num4) * Math.Sqrt((double)num20)));
                        if (num21 < 0f)
                        {
                            num23 = -num23;
                        }
                        num22 = (byte)(127f - ((num23 / 0.5f) * 127f));
                    }
                    if (num22 > num15)
                    {
                        if (material != null)
                        {
                            m_cache.Material(ref p, materialIdx);
                        }
                        flag = true;
                        m_cache.Content(ref p, num22);
                    }
                }
                float num16 = (float)(vectord3 - vector3).LengthSquared();
                float num17 = num16 - num9;
                if (num17 > num10)
                {
                    num18 = 0;
                }
                else if (num17 < num11)
                {
                    num18 = 0xff;
                }
                else
                {
                    float num24 = (float)Math.Sqrt((num16 + num9) - ((2f * radius) * Math.Sqrt((double)num16)));
                    if (num17 < 0f)
                    {
                        num24 = -num24;
                    }
                    num18 = (byte)(127f - ((num24 / 0.5f) * 127f));
                }
                num15 = m_cache.Content(ref p);
                if ((num15 > 0) && (num18 > 0))
                {
                    flag = true;
                    int num25 = num15 - num18;
                    if (num25 < 0)
                    {
                        num25 = 0;
                    }
                    m_cache.Content(ref p, (byte)num25);
                    num += num15 - num25;
                }
                float num19 = ((float)(vectord3 - vector4).LengthSquared()) - num13;
                if (num19 <= 1.5f)
                {
                    MyVoxelMaterialDefinition voxelMaterialDefinition = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref p));
                    MyVoxelMaterialDefinition objB = material;
                    if (num19 > 0f)
                    {
                        byte num26 = m_cache.Content(ref p);
                        if (num26 == 0xff)
                        {
                            objB = voxelMaterialDefinition;
                        }
                        if ((num19 >= num14) && (num26 != 0))
                        {
                            objB = voxelMaterialDefinition;
                        }
                    }
                    if (ReferenceEquals(voxelMaterialDefinition, objB))
                    {
                        goto TR_0005;
                    }
                    else
                    {
                        m_cache.Material(ref p, objB.Index);
                        flag = true;
                    }
                }
                if ((((((float)(vectord3 - vector2).LengthSquared()) - num5) <= 0f) && (m_cache.Content(ref p) > 0)) && m_cache.WrinkleVoxelContent(ref p, 0.5f, 0.45f))
                {
                    flag = true;
                }
                goto TR_0005;
            }
TR_0039:
            while (true)
            {
                if (vectori5.Y > vectori2.Y)
                {
                    int *numPtr5 = (int *)ref vectori5.Z;
                    numPtr5[0]++;
                    int *numPtr6 = (int *)ref p.Z;
                    numPtr6[0]++;
                    break;
                }
                vectori5.X = vectori.X;
                p.X        = 0;
                goto TR_0036;
            }
TR_003C:
            while (true)
            {
                if (vectori5.Z <= vectori2.Z)
                {
                    vectori5.Y = vectori.Y;
                    p.Y        = 0;
                    break;
                }
                if (flag)
                {
                    RemoveSmallVoxelsUsingChachedVoxels();
                    vectori = (Vector3I)(vectori + voxelMap.StorageMin);
                    voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.All, vectori, (Vector3I)(vectori2 + voxelMap.StorageMin), true, false);
                    MyShapeSphere sphere1 = new MyShapeSphere();
                    sphere1.Center = sphere.Center;
                    sphere1.Radius = (float)(sphere.Radius * 1.5);
                    BoundingBoxD worldBoundaries = sphere1.GetWorldBoundaries();
                    NotifyVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, ref worldBoundaries);
                }
                return;
            }
            goto TR_0039;
        }
Example #27
0
        void IMyOctreeLeafNode.ReadRange(MyStorageData target, MyStorageDataTypeFlags types, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod, ref MyVoxelRequestFlags flags)
        {
            int                num     = this.m_cell.Lod - lodIndex;
            Vector3I           vectori = this.m_cell.CoordInLod << num;
            MyVoxelDataRequest request = new MyVoxelDataRequest {
                Target        = target,
                Offset        = writeOffset,
                Lod           = lodIndex,
                MinInLod      = (Vector3I)(minInLod + vectori),
                MaxInLod      = (Vector3I)(maxInLod + vectori),
                RequestFlags  = flags,
                RequestedData = types
            };

            this.m_provider.ReadRange(ref request, false);
            flags = request.Flags;
        }
Example #28
0
        public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags)
        {
            ProfilerShort.Begin(GetType().Name + ".ReadRange");

            if ((dataToRead & MyStorageDataTypeFlags.Content) != 0)
            {
                target.ClearContent(0);
            }

            if (requestFlags.HasFlags(MyVoxelRequestFlags.AdviseCache) && lodIndex == 0 && CachedWrites)
            {
                ReadRangeAdviseCache(target, dataToRead, ref lodVoxelRangeMin, ref lodVoxelRangeMax);
                ProfilerShort.End();
                return;
            }

            if (CachedWrites && lodIndex <= VoxelChunk.SizeBits && m_cachedChunks.Count > 0)
            {
                // read occlusion separate
                if (dataToRead.Requests(MyStorageDataTypeEnum.Occlusion))
                {
                    using (m_storageLock.AcquireSharedUsing())
                        ReadRangeInternal(target, ref Vector3I.Zero, MyStorageDataTypeFlags.Occlusion, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);

                    dataToRead ^= MyStorageDataTypeFlags.Occlusion;
                }

                if (m_tmpChunks == null) m_tmpChunks = new List<VoxelChunk>();

                var lodDiff = VoxelChunk.SizeBits - lodIndex;

                // We fetch which chunks overlap our current range from the chunk tree, then we read all data from storage and apply those changes
                var querybb = new BoundingBox(lodVoxelRangeMin << lodIndex, lodVoxelRangeMax << lodIndex);

                using (m_cacheLock.AcquireSharedUsing())
                    m_cacheMap.OverlapAllBoundingBox(ref querybb, m_tmpChunks, 0, false);

                if (m_tmpChunks.Count > 0)
                {
                    var chunkMin = lodVoxelRangeMin >> lodDiff;
                    var chunkMax = lodVoxelRangeMax >> lodDiff;

                    bool readFromStorage = false;

                    if ((chunkMax - chunkMin + 1).Size > m_tmpChunks.Count)
                    {
                        using (m_storageLock.AcquireSharedUsing())
                            ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);
                        readFromStorage = true;
                    }

                    for (int i = 0; i < m_tmpChunks.Count; ++i)
                    {
                        var chunk = m_tmpChunks[i];
                        var pos = chunk.Coords;

                        var celPos = pos << lodDiff;

                        var lodCkStart = pos << lodDiff;
                        lodCkStart = Vector3I.Max(lodCkStart, lodVoxelRangeMin);

                        var targetOffset = lodCkStart - lodVoxelRangeMin;

                        var lodCkEnd = ((pos + 1) << lodDiff) - 1;
                        lodCkEnd = Vector3I.Min(lodCkEnd, lodVoxelRangeMax);

                        lodCkStart -= celPos;
                        lodCkEnd -= celPos;

                        if ((chunk.Cached & dataToRead) != dataToRead && !readFromStorage)
                        {
                            using (m_storageLock.AcquireSharedUsing())
                                if ((chunk.Cached & dataToRead) != dataToRead)
                                    ReadDatForChunk(chunk, dataToRead);
                        }

                        using (chunk.Lock.AcquireSharedUsing())
                            chunk.ReadLod(target, !readFromStorage ? dataToRead : dataToRead & chunk.Cached, ref targetOffset, lodIndex, ref lodCkStart, ref lodCkEnd);
                    }

                    m_tmpChunks.Clear();
                    ProfilerShort.End();
                    return;
                }
            }

            // all else
            using (m_storageLock.AcquireSharedUsing())
                ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);

            ProfilerShort.End();
        }
 void IMyOctreeLeafNode.ReadRange(MyStorageData target, MyStorageDataTypeFlags types, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod, ref MyVoxelRequestFlags flags)
 {
     m_octree.ReadRange(target, m_dataType, ref writeOffset, lodIndex, ref minInLod, ref maxInLod);
 }
            public override void Draw()
            {
                base.Draw();

                if (MySession.Static == null)
                {
                    return;
                }

                if (m_showVoxelProbe)
                {
                    float halfSize = m_probeSize * .5f;
                    float lodSize  = 1 << m_probeLod;

                    if (m_moveProbe)
                    {
                        m_probePosition = MySector.MainCamera.Position + MySector.MainCamera.ForwardVector * m_probeSize * 3;
                    }

                    BoundingBox  bb;
                    BoundingBoxD bbp; // Box used for drawing and finding the probe and drawing

                    bb  = new BoundingBox(m_probePosition - halfSize, m_probePosition + halfSize);
                    bbp = (BoundingBoxD)bb;

                    m_voxels.Clear();
                    MyGamePruningStructure.GetAllVoxelMapsInBox(ref bbp, m_voxels);

                    MyVoxelBase map      = null;
                    double      distance = double.PositiveInfinity;

                    foreach (var vox in m_voxels)
                    {
                        var d = Vector3D.Distance(vox.WorldMatrix.Translation, m_probePosition);
                        if (d < distance)
                        {
                            distance = d;
                            map      = vox;
                        }
                    }

                    ContainmentType cont = ContainmentType.Disjoint;

                    if (map != null)
                    {
                        map = map.RootVoxel;

                        Vector3 localPos = Vector3.Transform(m_probePosition, map.PositionComp.WorldMatrixInvScaled);
                        localPos += map.SizeInMetresHalf;

                        // Create similar bounding box in storage space
                        bb = new BoundingBox(localPos - halfSize, localPos + halfSize);

                        m_probedVoxel = map;

                        Section("Probing {1}: {0}", map.StorageName, map.GetType().Name);
                        Text("Probe mode: {0}", m_mode);

                        if (m_mode == ProbeMode.Intersect)
                        {
                            Text("Local Pos: {0}", localPos);
                            Text("Probe Size: {0}", m_probeSize);
                            cont = map.Storage.Intersect(ref bb, false);
                            Text("Result: {0}", cont.ToString());
                            bbp = (BoundingBoxD)bb;
                        }
                        else
                        {
                            Vector3I min = Vector3I.Floor(bb.Min / lodSize + .5f);
                            Vector3I max = min + ((int)m_probeSize >> m_probeLod) - 1;

                            bbp = new BoundingBoxD(min << m_probeLod, (max + 1) << m_probeLod);
                            bbp.Translate(new Vector3D(-.5));

                            Text("Probe Size: {0}({1})", (max - min).X + 1, m_probeSize);
                            Text("Probe LOD: {0}", m_probeLod);

                            var requestData           = (MyStorageDataTypeEnum)(int)m_mode;
                            MyVoxelRequestFlags flags = MyVoxelRequestFlags.ContentChecked;

                            m_target.Resize(max - min + 1);
                            m_target.Clear(MyStorageDataTypeEnum.Content, 0);
                            m_target.Clear(MyStorageDataTypeEnum.Material, 0);
                            map.Storage.ReadRange(m_target, (MyStorageDataTypeFlags)(1 << (int)requestData), m_probeLod, ref min, ref max, ref flags);

                            if (requestData == MyStorageDataTypeEnum.Content)
                            {
                                if (flags.HasFlag(MyVoxelRequestFlags.EmptyContent))
                                {
                                    cont = ContainmentType.Disjoint;
                                }
                                else if (flags.HasFlag(MyVoxelRequestFlags.FullContent))
                                {
                                    cont = ContainmentType.Contains;
                                }
                                else
                                {
                                    int val = m_target.ValueWhenAllEqual(requestData);
                                    if (val == -1)
                                    {
                                        cont = ContainmentType.Intersects;
                                    }
                                    else if (val >= MyVoxelConstants.VOXEL_ISO_LEVEL)
                                    {
                                        cont = ContainmentType.Contains;
                                    }
                                    else
                                    {
                                        cont = ContainmentType.Disjoint;
                                    }
                                }

                                DrawContentsInfo(m_target);
                            }
                            else
                            {
                                cont = ContainmentType.Disjoint;
                                DrawMaterialsInfo(m_target);
                            }

                            Text(Color.Yellow, 1.5f, "Voxel Editing:");
                            Text("Value to set (Ctrl+Mousewheel): {0}", m_valueToSet);
                            if (m_probeLod != 0)
                            {
                                Text(Color.Red, "Writing to storage is only possible when probe is set to LOD 0");
                            }
                            else
                            {
                                Text("Use primary mouse button to set.");
                                Text("Position/Extents: {0}/{1}", bbp.Min, bbp.Extents);

                                if (MyInput.Static.IsLeftMousePressed())
                                {
                                    if (requestData == MyStorageDataTypeEnum.Content)
                                    {
                                        m_target.BlockFillContent(Vector3I.Zero, m_target.Size3D - Vector3I.One, m_valueToSet);
                                    }
                                    else
                                    {
                                        m_target.BlockFillMaterial(Vector3I.Zero, m_target.Size3D - Vector3I.One, m_valueToSet);
                                    }

                                    map.Storage.WriteRange(m_target, (MyStorageDataTypeFlags)(1 << (int)requestData), ref min, ref max);
                                }
                            }
                        }
                    }
                    else
                    {
                        Section("No Voxel Found");
                        Text("Probe mode: {0}", m_mode);
                        Text("Probe Size: {0}", m_probeSize);
                    }

                    Color c = ColorForContainment(cont);
                    if (map != null)
                    {
                        bbp = bbp.Translate(-map.SizeInMetresHalf);
                        MyOrientedBoundingBoxD oobb = new MyOrientedBoundingBoxD(bbp, map.WorldMatrix);
                        MyRenderProxy.DebugDrawOBB(oobb, c, 0.5f, true, false);
                    }
                    else
                    {
                        MyRenderProxy.DebugDrawAABB(bbp, c, 0.5f, 1.0f, true);
                    }
                }
            }
Example #31
0
        void IMyOctreeLeafNode.ReadRange(MyStorageData target, MyStorageDataTypeFlags types, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod, ref MyVoxelRequestFlags flags)
        {
            var lodShift     = m_cell.Lod - lodIndex;
            var leafMinInLod = m_cell.CoordInLod << lodShift;
            var min          = minInLod + leafMinInLod;
            var max          = maxInLod + leafMinInLod;

            AssertRangeIsInside(lodIndex, ref min, ref max);
            ProfilerShort.Begin("MyProviderLeaf.ReadRange");
            MyVoxelDataRequest req = new MyVoxelDataRequest()
            {
                Target        = target,
                Offset        = writeOffset,
                Lod           = lodIndex,
                minInLod      = min,
                maxInLod      = max,
                RequestFlags  = flags,
                RequestedData = types
            };

            m_provider.ReadRange(ref req);
            flags = req.Flags;
            ProfilerShort.End();
        }
Example #32
0
        internal void ReadContentRange(ref MyVoxelDataRequest req)
        {
            if (Closed)
            {
                return;
            }

            float lodVoxelSize = (1 << req.Lod) * MyVoxelConstants.VOXEL_SIZE_IN_METRES;

            Vector3I min = req.minInLod;
            Vector3I max = req.maxInLod;

            ProfilerShort.Begin("Distance field computation");
            try
            {
                Vector3I v             = min;
                Vector3  localPos      = v * lodVoxelSize - m_translation;
                Vector3  localPosStart = localPos;

                BoundingBox request = new BoundingBox(localPos, localPos + (max - min) * lodVoxelSize);
                request.Inflate(lodVoxelSize);

                MyVoxelRequestFlags flags = 0;

                ContainmentType cont = ContainmentType.Intersects;

                bool intersects;

                if (!req.Flags.HasFlags(MyVoxelRequestFlags.DoNotCheck))
                {
                    BoundingSphere sphere = new BoundingSphere(
                        Vector3.Zero,
                        OuterRadius + lodVoxelSize);

                    sphere.Intersects(ref request, out intersects);
                    if (!intersects)
                    {
                        cont = ContainmentType.Disjoint;
                        goto end;
                    }

                    sphere.Radius = InnerRadius - lodVoxelSize;

                    ContainmentType ct;
                    sphere.Contains(ref request, out ct);
                    if (ct == ContainmentType.Contains)
                    {
                        cont = ct;
                        goto end;
                    }

                    cont = IntersectBoundingBoxInternal(ref request, lodVoxelSize);
                    if (cont != ContainmentType.Intersects)
                    {
                        goto end;
                    }
                }


                bool hit = false;

                // store request history
                EnqueueHistory(req);

                // Setup cache for current map;
                PrepareCache();

                var writeOffsetLoc = req.Offset - min;
                for (v.Z = min.Z; v.Z <= max.Z; ++v.Z)
                {
                    for (v.Y = min.Y; v.Y <= max.Y; ++v.Y)
                    {
                        v.X = min.X;
                        var write2 = v + writeOffsetLoc;
                        var write  = req.Target.ComputeLinear(ref write2);
                        for (; v.X <= max.X; ++v.X)
                        {
                            float signedDist = SignedDistanceLocal(localPos, lodVoxelSize) / lodVoxelSize;

                            var  fillRatio = MathHelper.Clamp(-signedDist, -1f, 1f) * 0.5f + 0.5f;
                            byte content   = (byte)(fillRatio * MyVoxelConstants.VOXEL_CONTENT_FULL);

                            if (content != 0)
                            {
                                hit = true;
                            }
                            req.Target.Content(write, content);
                            write      += req.Target.StepLinear;
                            localPos.X += lodVoxelSize;
                        }
                        localPos.Y += lodVoxelSize;
                        localPos.X  = localPosStart.X;
                    }
                    localPos.Z += lodVoxelSize;
                    localPos.Y  = localPosStart.Y;
                }

                if (!hit)
                {
                    PruningStats.Miss();
                }
                else
                {
                    PruningStats.Hit();
                }
                CullStats.Miss();
                return;

                end :;
                CullStats.Hit();

                if (cont == ContainmentType.Disjoint)
                {
                    if (req.RequestFlags.HasFlags(MyVoxelRequestFlags.ContentChecked))
                    {
                        flags |= MyVoxelRequestFlags.EmptyContent | MyVoxelRequestFlags.ContentCheckedDeep | MyVoxelRequestFlags.ContentChecked;
                    }
                    else
                    {
                        req.Target.BlockFillContent(req.Offset, req.Offset + max - min, MyVoxelConstants.VOXEL_CONTENT_EMPTY);
                    }
                }
                else if (cont == ContainmentType.Contains)
                {
                    if (req.RequestFlags.HasFlags(MyVoxelRequestFlags.ContentChecked))
                    {
                        flags |= MyVoxelRequestFlags.FullContent | MyVoxelRequestFlags.ContentCheckedDeep | MyVoxelRequestFlags.ContentChecked;
                    }
                    else
                    {
                        req.Target.BlockFillContent(req.Offset, req.Offset + max - min, MyVoxelConstants.VOXEL_CONTENT_FULL);
                    }
                }
                req.Flags = flags;
                PruningStats.Hit();
            }
            finally
            {
                ProfilerShort.End();
            }
        }
Example #33
0
        public void ReadMaterialRange(ref MyVoxelDataRequest req)
        {
            byte biome;

            ProfilerShort.Begin("MaterialComputation");

            req.Flags = req.RequestFlags & (MyVoxelRequestFlags.SurfaceMaterial | MyVoxelRequestFlags.ConsiderContent);

            Vector3I minInLod = req.minInLod;
            Vector3I maxInLod = req.maxInLod;
            var      target   = req.Target;

            float lodVoxelSize = 1 << req.Lod;

            MyVoxelRequestFlags usedFlags = 0;

            bool computeOcclusion = req.RequestedData.Requests(MyStorageDataTypeEnum.Occlusion);

            // We don't bother determining where the surface is if we don't have the normal.
            bool assignToSurface = req.RequestFlags.HasFlags(MyVoxelRequestFlags.SurfaceMaterial);

            bool useContent = req.RequestFlags.HasFlags(MyVoxelRequestFlags.ConsiderContent);

            // Prepare coefficient cache
            m_planetShape.PrepareCache();

            // Here we will compute which rules match the requested range and apply those.
            if (m_biomes != null)
            {
                if (req.SizeLinear > 125)
                {
                    BoundingBox rbox = new BoundingBox((Vector3)minInLod * lodVoxelSize, (Vector3)maxInLod * lodVoxelSize);

                    PrepareRulesForBoxInternal(ref rbox);
                }
                else if (!m_rangeClean || m_providerForRules != this)
                {
                    CleanRules();
                }
            }

            Vector3I combinedOffset = -minInLod + req.Offset;
            Vector3I v = new Vector3I();

            for (v.Z = minInLod.Z; v.Z <= maxInLod.Z; ++v.Z)
            {
                for (v.Y = minInLod.Y; v.Y <= maxInLod.Y; ++v.Y)
                {
                    for (v.X = minInLod.X; v.X <= maxInLod.X; ++v.X)
                    {
                        Vector3I coords = v;

                        var write       = v + combinedOffset;
                        var writeLinear = target.ComputeLinear(ref write);

                        if ((assignToSurface && target.Material(writeLinear) != 0) ||
                            (useContent && target.Content(writeLinear) == 0))
                        {
                            if (computeOcclusion)
                            {
                                // Prevent empty voxels from affecting occlusion.
                                target.Content(writeLinear, 0);
                            }
                            target.Material(writeLinear, MyVoxelConstants.NULL_MATERIAL);
                            continue;
                        }

                        MyVoxelMaterialDefinition mat = null;
                        byte occlusion = (byte)(computeOcclusion ? 255 : 0); // flag that we want occlusion.

                        Vector3 localPos = coords * lodVoxelSize;
                        mat = GetMaterialForPosition(ref localPos, lodVoxelSize, out biome, ref occlusion);

                        if (mat == null)
                        {
                            mat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(0);
                        }

                        target.Material(writeLinear, mat.Index);
                        if (computeOcclusion)
                        {
                            target[MyStorageDataTypeEnum.Occlusion][writeLinear] = occlusion;
                        }
                    }
                }
            }

            ProfilerShort.End();
        }
Example #34
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();
        }
        public void ReadRange(MyStorageData target, MyStorageDataTypeFlags dataToRead, int lodIndex, ref Vector3I lodVoxelRangeMin, ref Vector3I lodVoxelRangeMax, ref MyVoxelRequestFlags requestFlags)
        {
            ProfilerShort.Begin(GetType().Name + ".ReadRange");
            try
            {
                const int SUBRANGE_SIZE_SHIFT = 3;
                const int SUBRANGE_SIZE = 1 << SUBRANGE_SIZE_SHIFT;
                var threshold = new Vector3I(SUBRANGE_SIZE);
                var rangeSize = lodVoxelRangeMax - lodVoxelRangeMin + 1;
                if ((dataToRead & MyStorageDataTypeFlags.Content) != 0)
                {
                    target.ClearContent(0);
                }

                if ((rangeSize.X <= threshold.X &&
                    rangeSize.Y <= threshold.Y &&
                    rangeSize.Z <= threshold.Z) || !MyFakes.ENABLE_SPLIT_VOXEL_READ_QUERIES)
                {
                    using (m_lock.AcquireSharedUsing())
                    {
                        ReadRangeInternal(target, ref Vector3I.Zero, dataToRead, lodIndex, ref lodVoxelRangeMin, ref lodVoxelRangeMax, ref requestFlags);
                    }
                }
                else
                {
                    // These optimizations don't work when splitting the range.
                    requestFlags &= ~(MyVoxelRequestFlags.OneMaterial | MyVoxelRequestFlags.ContentChecked);
                    MyVoxelRequestFlags flags = requestFlags;

                    // splitting to smaller ranges to make sure the lock is not held for too long, preventing write on update thread
                    // subranges could be aligned to multiple of their size for possibly better performance
                    var steps = (rangeSize - 1) >> SUBRANGE_SIZE_SHIFT;
                    for (var it = new Vector3I.RangeIterator(ref Vector3I.Zero, ref steps); it.IsValid(); it.MoveNext())
                    {
                        flags = requestFlags;
                        var offset = it.Current << SUBRANGE_SIZE_SHIFT;
                        var min = lodVoxelRangeMin + offset;
                        var max = min + SUBRANGE_SIZE - 1;
                        Vector3I.Min(ref max, ref lodVoxelRangeMax, out max);
                        Debug.Assert(min.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax));
                        Debug.Assert(max.IsInsideInclusive(ref lodVoxelRangeMin, ref lodVoxelRangeMax));
                        using (m_lock.AcquireSharedUsing())
                        {
                            ReadRangeInternal(target, ref offset, dataToRead, lodIndex, ref min, ref max, ref flags);
                        }
                    }

                    // If the storage is consistent this should be fine.
                    requestFlags = flags;
                }
            }
            finally
            {
                ProfilerShort.End();
            }
        }