Пример #1
0
        //[Conditional("DEBUG")]
        private void FixCacheMaterial(Vector3I voxelStart, Vector3I voxelEnd)
        {
            var mcount = Sandbox.Definitions.MyDefinitionManager.Static.VoxelMaterialCount;

            voxelEnd   = Vector3I.Min(voxelEnd - voxelStart, m_cache.Size3D);
            voxelStart = Vector3I.Zero;
            var it  = new Vector3I_RangeIterator(ref voxelStart, ref voxelEnd);
            var pos = it.Current;

            for (; it.IsValid(); it.GetNext(out pos))
            {
                var lin = m_cache.ComputeLinear(ref pos);
                var mat = m_cache.Material(lin);

                if (mat >= mcount && mat != MyVoxelConstants.NULL_MATERIAL)
                {
                    //Debug.Fail(String.Format("VoxelData contains invalid materials (id: {0}).", m_cache.Material(lin)));
                    m_cache.Material(lin, MyVoxelConstants.NULL_MATERIAL);
                }
            }
        }
Пример #2
0
        public static void CutOutShapeWithProperties(
            MyVoxelBase voxelMap,
            MyShape shape,
            out float voxelsCountInPercent,
            out MyVoxelMaterialDefinition voxelMaterial,
            Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null,
            bool updateSync          = false,
            bool onlyCheck           = false,
            bool applyDamageMaterial = false,
            bool onlyApplyMaterial   = false)
        {
            if (MySession.Static.EnableVoxelDestruction == false)
            {
                voxelsCountInPercent = 0;
                voxelMaterial        = null;
                return;
            }

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

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

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

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

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

            Vector3I minCorner, maxCorner;

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

            bool readMaterial = exactCutOutMaterials != null || applyDamageMaterial;

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

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

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

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

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

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

            Vector3I center;

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

            MyVoxelMaterialDefinition voxelMat = null;

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

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

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

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

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

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

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

                        originalSum += original;
                        removedSum  += removed;

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

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

                        if (applyDamageMaterial && voxelMat.HasDamageMaterial && !onlyCheck)
                        {
                            m_cache.Material(lin, voxelMat.DamagedMaterialId);
                        }
                    }
                }
            }

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

            ProfilerShort.BeginNextBlock("Write");


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

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


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

            shape.Transformation = oldTranmsform;

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

            ProfilerShort.End();
        }
        private Vector3I ComputeTemporaryVoxelData(MyStorageData cache, ref Vector3I coord0, int cubeIndex, int lod)
        {
            int coord0LinIdx = coord0.X * m_sX + coord0.Y * m_sY + coord0.Z * m_sZ;

            MyTemporaryVoxel tempVoxel0 = m_temporaryVoxels[coord0LinIdx];
            MyTemporaryVoxel tempVoxel1 = m_temporaryVoxels[coord0LinIdx + m_sX];
            MyTemporaryVoxel tempVoxel2 = m_temporaryVoxels[coord0LinIdx + m_sX + m_sZ];
            MyTemporaryVoxel tempVoxel3 = m_temporaryVoxels[coord0LinIdx + m_sZ];
            MyTemporaryVoxel tempVoxel4 = m_temporaryVoxels[coord0LinIdx + m_sY];
            MyTemporaryVoxel tempVoxel5 = m_temporaryVoxels[coord0LinIdx + m_sX + m_sY];
            MyTemporaryVoxel tempVoxel6 = m_temporaryVoxels[coord0LinIdx + m_sX + m_sY + m_sZ];
            MyTemporaryVoxel tempVoxel7 = m_temporaryVoxels[coord0LinIdx + m_sY + m_sZ];



            Vector3I coord1 = new Vector3I(coord0.X + 1, coord0.Y + 0, coord0.Z + 0);
            Vector3I coord2 = new Vector3I(coord0.X + 1, coord0.Y + 0, coord0.Z + 1);
            Vector3I coord3 = new Vector3I(coord0.X + 0, coord0.Y + 0, coord0.Z + 1);
            Vector3I coord4 = new Vector3I(coord0.X + 0, coord0.Y + 1, coord0.Z + 0);
            Vector3I coord5 = new Vector3I(coord0.X + 1, coord0.Y + 1, coord0.Z + 0);
            Vector3I coord6 = new Vector3I(coord0.X + 1, coord0.Y + 1, coord0.Z + 1);
            Vector3I coord7 = new Vector3I(coord0.X + 0, coord0.Y + 1, coord0.Z + 1);

            Vector3I tempVoxelCoord0 = coord0;
            Vector3I tempVoxelCoord1 = coord1;
            Vector3I tempVoxelCoord2 = coord2;
            Vector3I tempVoxelCoord3 = coord3;
            Vector3I tempVoxelCoord4 = coord4;
            Vector3I tempVoxelCoord5 = coord5;
            Vector3I tempVoxelCoord6 = coord6;
            Vector3I tempVoxelCoord7 = coord7;


            tempVoxel0.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord0);
            tempVoxel1.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord1);
            tempVoxel2.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord2);
            tempVoxel3.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord3);
            tempVoxel4.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord4);
            tempVoxel5.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord5);
            tempVoxel6.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord6);
            tempVoxel7.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord7);

            //tempVoxel0.Position.X = m_originPosition.X + (coord0.X) * m_voxelSizeInMeters;
            //tempVoxel0.Position.Y = m_originPosition.Y + (coord0.Y) * m_voxelSizeInMeters;
            //tempVoxel0.Position.Z = m_originPosition.Z + (coord0.Z) * m_voxelSizeInMeters;

            tempVoxel0.Position.X = (m_voxelStart.X + coord0.X) * m_voxelSizeInMeters;
            tempVoxel0.Position.Y = (m_voxelStart.Y + coord0.Y) * m_voxelSizeInMeters;
            tempVoxel0.Position.Z = (m_voxelStart.Z + coord0.Z) * m_voxelSizeInMeters;


            tempVoxel1.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters;
            tempVoxel1.Position.Y = tempVoxel0.Position.Y;
            tempVoxel1.Position.Z = tempVoxel0.Position.Z;

            tempVoxel2.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters;
            tempVoxel2.Position.Y = tempVoxel0.Position.Y;
            tempVoxel2.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters;

            tempVoxel3.Position.X = tempVoxel0.Position.X;
            tempVoxel3.Position.Y = tempVoxel0.Position.Y;
            tempVoxel3.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters;

            tempVoxel4.Position.X = tempVoxel0.Position.X;
            tempVoxel4.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters;
            tempVoxel4.Position.Z = tempVoxel0.Position.Z;

            tempVoxel5.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters;
            tempVoxel5.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters;
            tempVoxel5.Position.Z = tempVoxel0.Position.Z;

            tempVoxel6.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters;
            tempVoxel6.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters;
            tempVoxel6.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters;

            tempVoxel7.Position.X = tempVoxel0.Position.X;
            tempVoxel7.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters;
            tempVoxel7.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters;

            //  Normals at grid corners (calculated from gradient)
            GetVoxelNormal(tempVoxel0, ref coord0, ref tempVoxelCoord0, tempVoxel0);
            GetVoxelNormal(tempVoxel1, ref coord1, ref tempVoxelCoord1, tempVoxel0);
            GetVoxelNormal(tempVoxel2, ref coord2, ref tempVoxelCoord2, tempVoxel0);
            GetVoxelNormal(tempVoxel3, ref coord3, ref tempVoxelCoord3, tempVoxel0);
            GetVoxelNormal(tempVoxel4, ref coord4, ref tempVoxelCoord4, tempVoxel0);
            GetVoxelNormal(tempVoxel5, ref coord5, ref tempVoxelCoord5, tempVoxel0);
            GetVoxelNormal(tempVoxel6, ref coord6, ref tempVoxelCoord6, tempVoxel0);
            GetVoxelNormal(tempVoxel7, ref coord7, ref tempVoxelCoord7, tempVoxel0);

            //  Ambient occlusion colors at grid corners
            //  IMPORTANT: At this point normals must be calculated because GetVoxelAmbientAndSun() will be retrieving them from temp table and not checking if there is actual value
            GetVoxelAmbient(tempVoxel0, ref coord0, ref tempVoxelCoord0);
            GetVoxelAmbient(tempVoxel1, ref coord1, ref tempVoxelCoord1);
            GetVoxelAmbient(tempVoxel2, ref coord2, ref tempVoxelCoord2);
            GetVoxelAmbient(tempVoxel3, ref coord3, ref tempVoxelCoord3);
            GetVoxelAmbient(tempVoxel4, ref coord4, ref tempVoxelCoord4);
            GetVoxelAmbient(tempVoxel5, ref coord5, ref tempVoxelCoord5);
            GetVoxelAmbient(tempVoxel6, ref coord6, ref tempVoxelCoord6);
            GetVoxelAmbient(tempVoxel7, ref coord7, ref tempVoxelCoord7);

            //  Find the vertices where the surface intersects the cube
            int edgeVal = MyMarchingCubesConstants.EdgeTable[cubeIndex];

            if ((edgeVal & 1) == 1)
            {
                GetVertexInterpolation(cache, tempVoxel0, tempVoxel1, 0);
            }
            if ((edgeVal & 2) == 2)
            {
                GetVertexInterpolation(cache, tempVoxel1, tempVoxel2, 1);
            }
            if ((edgeVal & 4) == 4)
            {
                GetVertexInterpolation(cache, tempVoxel2, tempVoxel3, 2);
            }
            if ((edgeVal & 8) == 8)
            {
                GetVertexInterpolation(cache, tempVoxel3, tempVoxel0, 3);
            }
            if ((edgeVal & 16) == 16)
            {
                GetVertexInterpolation(cache, tempVoxel4, tempVoxel5, 4);
            }
            if ((edgeVal & 32) == 32)
            {
                GetVertexInterpolation(cache, tempVoxel5, tempVoxel6, 5);
            }
            if ((edgeVal & 64) == 64)
            {
                GetVertexInterpolation(cache, tempVoxel6, tempVoxel7, 6);
            }
            if ((edgeVal & 128) == 128)
            {
                GetVertexInterpolation(cache, tempVoxel7, tempVoxel4, 7);
            }
            if ((edgeVal & 256) == 256)
            {
                GetVertexInterpolation(cache, tempVoxel0, tempVoxel4, 8);
            }
            if ((edgeVal & 512) == 512)
            {
                GetVertexInterpolation(cache, tempVoxel1, tempVoxel5, 9);
            }
            if ((edgeVal & 1024) == 1024)
            {
                GetVertexInterpolation(cache, tempVoxel2, tempVoxel6, 10);
            }
            if ((edgeVal & 2048) == 2048)
            {
                GetVertexInterpolation(cache, tempVoxel3, tempVoxel7, 11);
            }

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

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

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

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

            Stopwatch stopwatch = Stopwatch.StartNew();

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

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

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

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

                MyAPIGateway.Parallel.Sleep(sleepTimer);
            }

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

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

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

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

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

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

                                    if (voxelDefinition != null && voxelDefinition.MinedOre != null)
                                    {
                                        foreach (string mat in OreListSelected)
                                        {
                                            if (voxelDefinition.MinedOre.ToLower() == mat.ToLower())
                                            {
                                                Materials.AddMaterial(b, vector3I + p);
                                                break;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        Materials.AddMaterial(b, vector3I + p);
                                    }
                                }
                                else
                                {
                                    Materials.AddMaterial(b, vector3I + p);
                                }
                            }
                            p.X++;
                        }
                        p.Y++;
                    }
                    p.Z++;
                }
            }
        }
        private Vector3I ComputeTemporaryVoxelData(MyStorageData cache, ref Vector3I coord0, int cubeIndex, int lod)
        {
            int coord0LinIdx = coord0.X * m_sX + coord0.Y * m_sY + coord0.Z * m_sZ;

            MyTemporaryVoxel tempVoxel0 = m_temporaryVoxels[coord0LinIdx];
            MyTemporaryVoxel tempVoxel1 = m_temporaryVoxels[coord0LinIdx + m_sX];
            MyTemporaryVoxel tempVoxel2 = m_temporaryVoxels[coord0LinIdx + m_sX + m_sZ];
            MyTemporaryVoxel tempVoxel3 = m_temporaryVoxels[coord0LinIdx + m_sZ];
            MyTemporaryVoxel tempVoxel4 = m_temporaryVoxels[coord0LinIdx + m_sY];
            MyTemporaryVoxel tempVoxel5 = m_temporaryVoxels[coord0LinIdx + m_sX + m_sY];
            MyTemporaryVoxel tempVoxel6 = m_temporaryVoxels[coord0LinIdx + m_sX + m_sY + m_sZ];
            MyTemporaryVoxel tempVoxel7 = m_temporaryVoxels[coord0LinIdx + m_sY + m_sZ];



            Vector3I coord1 = new Vector3I(coord0.X + 1, coord0.Y + 0, coord0.Z + 0);
            Vector3I coord2 = new Vector3I(coord0.X + 1, coord0.Y + 0, coord0.Z + 1);
            Vector3I coord3 = new Vector3I(coord0.X + 0, coord0.Y + 0, coord0.Z + 1);
            Vector3I coord4 = new Vector3I(coord0.X + 0, coord0.Y + 1, coord0.Z + 0);
            Vector3I coord5 = new Vector3I(coord0.X + 1, coord0.Y + 1, coord0.Z + 0);
            Vector3I coord6 = new Vector3I(coord0.X + 1, coord0.Y + 1, coord0.Z + 1);
            Vector3I coord7 = new Vector3I(coord0.X + 0, coord0.Y + 1, coord0.Z + 1);

            Vector3I tempVoxelCoord0 = coord0;
            Vector3I tempVoxelCoord1 = coord1;
            Vector3I tempVoxelCoord2 = coord2;
            Vector3I tempVoxelCoord3 = coord3;
            Vector3I tempVoxelCoord4 = coord4;
            Vector3I tempVoxelCoord5 = coord5;
            Vector3I tempVoxelCoord6 = coord6;
            Vector3I tempVoxelCoord7 = coord7;


            tempVoxel0.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord0);
            tempVoxel1.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord1);
            tempVoxel2.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord2);
            tempVoxel3.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord3);
            tempVoxel4.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord4);
            tempVoxel5.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord5);
            tempVoxel6.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord6);
            tempVoxel7.IdxInCache = cache.ComputeLinear(ref tempVoxelCoord7);

            //tempVoxel0.Position.X = m_originPosition.X + (coord0.X) * m_voxelSizeInMeters;
            //tempVoxel0.Position.Y = m_originPosition.Y + (coord0.Y) * m_voxelSizeInMeters;
            //tempVoxel0.Position.Z = m_originPosition.Z + (coord0.Z) * m_voxelSizeInMeters;

            tempVoxel0.Position.X = (m_voxelStart.X + coord0.X) * m_voxelSizeInMeters;
            tempVoxel0.Position.Y = (m_voxelStart.Y + coord0.Y) * m_voxelSizeInMeters;
            tempVoxel0.Position.Z = (m_voxelStart.Z + coord0.Z) * m_voxelSizeInMeters;


            tempVoxel1.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters;
            tempVoxel1.Position.Y = tempVoxel0.Position.Y;
            tempVoxel1.Position.Z = tempVoxel0.Position.Z;

            tempVoxel2.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters;
            tempVoxel2.Position.Y = tempVoxel0.Position.Y;
            tempVoxel2.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters;

            tempVoxel3.Position.X = tempVoxel0.Position.X;
            tempVoxel3.Position.Y = tempVoxel0.Position.Y;
            tempVoxel3.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters;

            tempVoxel4.Position.X = tempVoxel0.Position.X;
            tempVoxel4.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters;
            tempVoxel4.Position.Z = tempVoxel0.Position.Z;

            tempVoxel5.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters;
            tempVoxel5.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters;
            tempVoxel5.Position.Z = tempVoxel0.Position.Z;

            tempVoxel6.Position.X = tempVoxel0.Position.X + m_voxelSizeInMeters;
            tempVoxel6.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters;
            tempVoxel6.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters;

            tempVoxel7.Position.X = tempVoxel0.Position.X;
            tempVoxel7.Position.Y = tempVoxel0.Position.Y + m_voxelSizeInMeters;
            tempVoxel7.Position.Z = tempVoxel0.Position.Z + m_voxelSizeInMeters;

            //  Normals at grid corners (calculated from gradient)
            GetVoxelNormal(tempVoxel0, ref coord0, ref tempVoxelCoord0, tempVoxel0);
            GetVoxelNormal(tempVoxel1, ref coord1, ref tempVoxelCoord1, tempVoxel0);
            GetVoxelNormal(tempVoxel2, ref coord2, ref tempVoxelCoord2, tempVoxel0);
            GetVoxelNormal(tempVoxel3, ref coord3, ref tempVoxelCoord3, tempVoxel0);
            GetVoxelNormal(tempVoxel4, ref coord4, ref tempVoxelCoord4, tempVoxel0);
            GetVoxelNormal(tempVoxel5, ref coord5, ref tempVoxelCoord5, tempVoxel0);
            GetVoxelNormal(tempVoxel6, ref coord6, ref tempVoxelCoord6, tempVoxel0);
            GetVoxelNormal(tempVoxel7, ref coord7, ref tempVoxelCoord7, tempVoxel0);

            //  Ambient occlusion colors at grid corners
            //  IMPORTANT: At this point normals must be calculated because GetVoxelAmbientAndSun() will be retrieving them from temp table and not checking if there is actual value
            GetVoxelAmbient(tempVoxel0, ref coord0, ref tempVoxelCoord0);
            GetVoxelAmbient(tempVoxel1, ref coord1, ref tempVoxelCoord1);
            GetVoxelAmbient(tempVoxel2, ref coord2, ref tempVoxelCoord2);
            GetVoxelAmbient(tempVoxel3, ref coord3, ref tempVoxelCoord3);
            GetVoxelAmbient(tempVoxel4, ref coord4, ref tempVoxelCoord4);
            GetVoxelAmbient(tempVoxel5, ref coord5, ref tempVoxelCoord5);
            GetVoxelAmbient(tempVoxel6, ref coord6, ref tempVoxelCoord6);
            GetVoxelAmbient(tempVoxel7, ref coord7, ref tempVoxelCoord7);

            //  Find the vertices where the surface intersects the cube
            int edgeVal = MyMarchingCubesConstants.EdgeTable[cubeIndex];
            if ((edgeVal & 1) == 1) { GetVertexInterpolation(cache, tempVoxel0, tempVoxel1, 0); }
            if ((edgeVal & 2) == 2) { GetVertexInterpolation(cache, tempVoxel1, tempVoxel2, 1); }
            if ((edgeVal & 4) == 4) { GetVertexInterpolation(cache, tempVoxel2, tempVoxel3, 2); }
            if ((edgeVal & 8) == 8) { GetVertexInterpolation(cache, tempVoxel3, tempVoxel0, 3); }
            if ((edgeVal & 16) == 16) { GetVertexInterpolation(cache, tempVoxel4, tempVoxel5, 4); }
            if ((edgeVal & 32) == 32) { GetVertexInterpolation(cache, tempVoxel5, tempVoxel6, 5); }
            if ((edgeVal & 64) == 64) { GetVertexInterpolation(cache, tempVoxel6, tempVoxel7, 6); }
            if ((edgeVal & 128) == 128) { GetVertexInterpolation(cache, tempVoxel7, tempVoxel4, 7); }
            if ((edgeVal & 256) == 256) { GetVertexInterpolation(cache, tempVoxel0, tempVoxel4, 8); }
            if ((edgeVal & 512) == 512) { GetVertexInterpolation(cache, tempVoxel1, tempVoxel5, 9); }
            if ((edgeVal & 1024) == 1024) { GetVertexInterpolation(cache, tempVoxel2, tempVoxel6, 10); }
            if ((edgeVal & 2048) == 2048) { GetVertexInterpolation(cache, tempVoxel3, tempVoxel7, 11); }

            return tempVoxelCoord0;
        }
Пример #6
0
        private unsafe void CalculateDistanceFieldInternal(Vector3 localPos, int faceHint, Vector3I min, Vector3I max, Vector3I writeOffsetLoc, MyStorageData target, float lodVoxelSize)
        {
            Vector3I vectori;

            this.PrepareCache();
            Vector3 vector = localPos;

            if (faceHint == -1)
            {
                vectori.Z = min.Z;
                while (vectori.Z <= max.Z)
                {
                    vectori.Y = min.Y;
                    while (true)
                    {
                        if (vectori.Y > max.Y)
                        {
                            float *singlePtr3 = (float *)ref localPos.Z;
                            singlePtr3[0] += lodVoxelSize;
                            localPos.Y     = vector.Y;
                            int *numPtr3 = (int *)ref vectori.Z;
                            numPtr3[0]++;
                            break;
                        }
                        vectori.X = min.X;
                        Vector3I p         = (Vector3I)(vectori + writeOffsetLoc);
                        int      linearIdx = target.ComputeLinear(ref p);
                        while (true)
                        {
                            if (vectori.X > max.X)
                            {
                                float *singlePtr2 = (float *)ref localPos.Y;
                                singlePtr2[0] += lodVoxelSize;
                                localPos.X     = vector.X;
                                int *numPtr2 = (int *)ref vectori.Y;
                                numPtr2[0]++;
                                break;
                            }
                            byte content = (byte)(((MathHelper.Clamp(-(this.SignedDistanceLocal(localPos, lodVoxelSize) / lodVoxelSize), -1f, 1f) * 0.5f) + 0.5f) * 255f);
                            target.Content(linearIdx, content);
                            linearIdx += target.StepLinear;
                            float *singlePtr1 = (float *)ref localPos.X;
                            singlePtr1[0] += lodVoxelSize;
                            int *numPtr1 = (int *)ref vectori.X;
                            numPtr1[0]++;
                        }
                    }
                }
            }
            else
            {
                vectori.Z = min.Z;
                while (vectori.Z <= max.Z)
                {
                    vectori.Y = min.Y;
                    while (true)
                    {
                        if (vectori.Y > max.Y)
                        {
                            float *singlePtr6 = (float *)ref localPos.Z;
                            singlePtr6[0] += lodVoxelSize;
                            localPos.Y     = vector.Y;
                            int *numPtr6 = (int *)ref vectori.Z;
                            numPtr6[0]++;
                            break;
                        }
                        vectori.X = min.X;
                        Vector3I p         = (Vector3I)(vectori + writeOffsetLoc);
                        int      linearIdx = target.ComputeLinear(ref p);
                        while (true)
                        {
                            if (vectori.X > max.X)
                            {
                                float *singlePtr5 = (float *)ref localPos.Y;
                                singlePtr5[0] += lodVoxelSize;
                                localPos.X     = vector.X;
                                int *numPtr5 = (int *)ref vectori.Y;
                                numPtr5[0]++;
                                break;
                            }
                            byte content = (byte)(((MathHelper.Clamp(-(this.SignedDistanceLocal(localPos, lodVoxelSize, faceHint) / lodVoxelSize), -1f, 1f) * 0.5f) + 0.5f) * 255f);
                            target.Content(linearIdx, content);
                            linearIdx += target.StepLinear;
                            float *singlePtr4 = (float *)ref localPos.X;
                            singlePtr4[0] += lodVoxelSize;
                            int *numPtr4 = (int *)ref vectori.X;
                            numPtr4[0]++;
                        }
                    }
                }
            }
        }
        internal void ReadContentRange(MyStorageData target, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod)
        {
            float          lodVoxelSizeHalf;
            BoundingBox    queryBox;
            BoundingSphere querySphere;

            SetupReading(lodIndex, ref minInLod, ref maxInLod, out lodVoxelSizeHalf, out queryBox, out querySphere);
            float lodVoxelSize = 2f * lodVoxelSizeHalf;

            ProfilerShort.Begin("Testing removed shapes");
            var overlappedRemovedShapes = OverlappedRemovedShapes;

            overlappedRemovedShapes.Clear();
            ContainmentType testRemove = ContainmentType.Disjoint;

            for (int i = 0; i < m_data.RemovedShapes.Length; ++i)
            {
                var test = m_data.RemovedShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize);
                if (test == ContainmentType.Contains)
                {
                    testRemove = ContainmentType.Contains;
                    break; // completely empty so we can leave
                }
                else if (test == ContainmentType.Intersects)
                {
                    testRemove = ContainmentType.Intersects;
                    overlappedRemovedShapes.Add(m_data.RemovedShapes[i]);
                }
            }
            ProfilerShort.End();
            if (testRemove == ContainmentType.Contains)
            {
                ProfilerShort.Begin("target.BlockFillContent");
                target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY);
                ProfilerShort.End();
                return;
            }

            ProfilerShort.Begin("Testing filled shapes");
            var overlappedFilledShapes = OverlappedFilledShapes;

            overlappedFilledShapes.Clear();
            ContainmentType testFill = ContainmentType.Disjoint;

            for (int i = 0; i < m_data.FilledShapes.Length; ++i)
            {
                var test = m_data.FilledShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize);
                if (test == ContainmentType.Contains)
                {
                    overlappedFilledShapes.Clear();
                    testFill = ContainmentType.Contains;
                    break;
                }
                else if (test == ContainmentType.Intersects)
                {
                    overlappedFilledShapes.Add(m_data.FilledShapes[i]);
                    testFill = ContainmentType.Intersects;
                }
            }
            ProfilerShort.End();

            if (testFill == ContainmentType.Disjoint)
            {
                ProfilerShort.Begin("target.BlockFillContent");
                target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY);
                ProfilerShort.End();
                return;
            }
            else if (testRemove == ContainmentType.Disjoint && testFill == ContainmentType.Contains)
            {
                ProfilerShort.Begin("target.BlockFillContent");
                target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_FULL);
                ProfilerShort.End();
                return;
            }

            ProfilerShort.Begin("Distance field computation");
            Vector3I v              = minInLod;
            Vector3  localPos       = v * lodVoxelSize;
            Vector3  localPosStart  = v * lodVoxelSize;
            var      writeOffsetLoc = writeOffset - minInLod;

            for (v.Z = minInLod.Z; v.Z <= maxInLod.Z; ++v.Z)
            {
                for (v.Y = minInLod.Y; v.Y <= maxInLod.Y; ++v.Y)
                {
                    v.X = minInLod.X;
                    var write2 = v + writeOffsetLoc;
                    var write  = target.ComputeLinear(ref write2);
                    for (; v.X <= maxInLod.X; ++v.X)
                    {
                        //Vector3 localPos = v * lodVoxelSize;

                        //ProfilerShort.Begin("Dist filled");
                        float distFill;
                        if (testFill == ContainmentType.Contains)
                        {
                            distFill = -1f;
                        }
                        else
                        {
                            //ProfilerShort.Begin("shape distances");
                            distFill = 1f;
                            foreach (var shape in overlappedFilledShapes)
                            {
                                distFill = Math.Min(distFill, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule));
                                if (distFill <= -1)
                                {
                                    break;
                                }
                            }
                            //ProfilerShort.End();
                        }

                        //ProfilerShort.BeginNextBlock("Dist removed");
                        float distRemoved = 1f;
                        if (testRemove != ContainmentType.Disjoint)
                        {
                            foreach (var shape in overlappedRemovedShapes)
                            {
                                distRemoved = Math.Min(distRemoved, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule));
                                if (distRemoved <= -1)
                                {
                                    break;
                                }
                            }
                        }
                        //ProfilerShort.BeginNextBlock("content");
                        float signedDist = MathHelper.Max(distFill, -distRemoved);

                        var  fillRatio = MathHelper.Clamp(-signedDist, -1f, 1f) * 0.5f + 0.5f;
                        byte content   = (byte)(fillRatio * MyVoxelConstants.VOXEL_CONTENT_FULL);
                        target.Content(write, content);
                        Debug.Assert(Math.Abs((((float)content) / MyVoxelConstants.VOXEL_CONTENT_FULL) - fillRatio) <= 0.5f);
                        //ProfilerShort.End();
                        write      += target.StepLinear;
                        localPos.X += lodVoxelSize;
                    }
                    localPos.Y += lodVoxelSize;
                    localPos.X  = localPosStart.X;
                }
                localPos.Z += lodVoxelSize;
                localPos.Y  = localPosStart.Y;
            }
            ProfilerShort.End();
        }
Пример #8
0
        private void ReadVoxel(IMyVoxelBase voxel, Vector3D position, Dictionary <Vector3D, NaniteMiningItem> targets, HashSet <string> allowedOreList = null)
        {
            var m_cache = new MyStorageData();
            NaniteShapeSphere shapeSphere = new NaniteShapeSphere();

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

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

            Vector3I minCorner, maxCorner, numCells;

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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

            //Logging.Instance.WriteLine(string.Format("Voxels Read: {0} - {1}", voxel.GetType().Name, count));
        }
Пример #9
0
            private void ExecuteQuery()
            {
                try
                {
                    var      shape = _component._cachedRegion;
                    var      worldMin = shape.Center - shape.Radius;
                    var      worldMax = shape.Center + shape.Radius;
                    Vector3I voxMin, voxMax;
                    MyVoxelCoordSystems.WorldPositionToVoxelCoord(_vox.PositionLeftBottomCorner, ref worldMin, out voxMin);
                    MyVoxelCoordSystems.WorldPositionToVoxelCoord(_vox.PositionLeftBottomCorner, ref worldMax, out voxMax);

                    {
                        var tmp = Vector3I.Max(voxMin, voxMax);
                        voxMin = Vector3I.Min(voxMin, voxMax);
                        voxMax = tmp;
                    }

                    {
                        voxMin = voxMin >> _component.Definition.LevelOfDetail;
                        voxMax = (voxMax >> _component.Definition.LevelOfDetail) + 1;
                    }

                    _storage.Resize(voxMin, voxMax);
                    // ReSharper disable once RedundantCast
                    ((IMyStorage)_vox.Storage).ReadRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, _component.Definition.LevelOfDetail, in voxMin,
                                                         in voxMax);

                    for (var i = 0; i < _countsWorking.Length; i++)
                    {
                        _countsWorking[i] = 0;
                    }
                    for (var itr = new Vector3I_RangeIterator(ref voxMin, ref voxMax); itr.IsValid(); itr.MoveNext())
                    {
                        var      local     = itr.Current;
                        var      localRoot = local << _component.Definition.LevelOfDetail;
                        Vector3D box;
                        MyVoxelCoordSystems.VoxelCoordToWorldPosition(_vox.PositionLeftBottomCorner, ref localRoot, out box);
                        if (!shape.Intersects(new BoundingBoxD(box, box + (1 << _component.Definition.LevelOfDetail))))
                        {
                            continue;
                        }
                        var stor    = local - voxMin;
                        var idx     = _storage.ComputeLinear(ref stor);
                        var content = _storage.Content(idx);
                        if (content == 0)
                        {
                            continue;
                        }
                        if (_component.Definition.Mode == VoxelPowerCountMode.Surface)
                        {
                            if (content == byte.MaxValue)
                            {
                                continue;
                            }
                            content = 1;
                        }

                        _countsWorking[_storage.Material(idx)] += content;
                    }

                    {
                        var tmp = _countsWorking;
                        _countsWorking = Counts;
                        Counts         = tmp;
                    }
                }
                finally
                {
                    _currentlyExecuting = false;
                    _component.QueryFinishedAsync();
                }
            }
Пример #10
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);
            }
        }
Пример #11
0
        public unsafe void ReadMaterialRange(ref MyVoxelDataRequest req, bool detectOnly = false)
        {
            Vector3I vectori4;

            req.Flags = req.RequestFlags & MyVoxelRequestFlags.RequestFlags;
            Vector3I minInLod            = req.MinInLod;
            Vector3I maxInLod            = req.MaxInLod;
            float    lodSize             = 1 << (req.Lod & 0x1f);
            bool     flag                = req.RequestFlags.HasFlags(MyVoxelRequestFlags.SurfaceMaterial);
            bool     flag2               = req.RequestFlags.HasFlags(MyVoxelRequestFlags.ConsiderContent);
            bool     preciseOrePositions = req.RequestFlags.HasFlags(MyVoxelRequestFlags.PreciseOrePositions);

            this.m_planetShape.PrepareCache();
            if (this.m_biomes != null)
            {
                if (req.SizeLinear > 0x7d)
                {
                    BoundingBox request = new BoundingBox((Vector3)(minInLod * lodSize), (Vector3)(maxInLod * lodSize));
                    this.PrepareRulesForBoxInternal(ref request);
                }
                else if (!m_rangeClean || !ReferenceEquals(CachedProvider, this))
                {
                    this.CleanRules();
                }
            }
            Vector3  vector   = (minInLod + 0.5f) * lodSize;
            Vector3  pos      = vector;
            Vector3I vectori3 = (Vector3I)(-minInLod + req.Offset);

            if (detectOnly)
            {
                vectori4.Z = minInLod.Z;
                while (vectori4.Z <= maxInLod.Z)
                {
                    vectori4.Y = minInLod.Y;
                    while (true)
                    {
                        if (vectori4.Y > maxInLod.Y)
                        {
                            float *singlePtr3 = (float *)ref pos.Z;
                            singlePtr3[0] += lodSize;
                            pos.Y          = vector.Y;
                            int *numPtr3 = (int *)ref vectori4.Z;
                            numPtr3[0]++;
                            break;
                        }
                        vectori4.X = minInLod.X;
                        while (true)
                        {
                            byte num2;
                            if (vectori4.X > maxInLod.X)
                            {
                                float *singlePtr2 = (float *)ref pos.Y;
                                singlePtr2[0] += lodSize;
                                pos.X          = vector.X;
                                int *numPtr2 = (int *)ref vectori4.Y;
                                numPtr2[0]++;
                                break;
                            }
                            MyVoxelMaterialDefinition definition = this.GetMaterialForPosition(ref pos, lodSize, out num2, preciseOrePositions);
                            if ((definition != null) && (definition.Index != 0xff))
                            {
                                return;
                            }
                            float *singlePtr1 = (float *)ref pos.X;
                            singlePtr1[0] += lodSize;
                            int *numPtr1 = (int *)ref vectori4.X;
                            numPtr1[0]++;
                        }
                    }
                }
                MyVoxelRequestFlags *flagsPtr1 = (MyVoxelRequestFlags *)ref req.Flags;
                *((int *)flagsPtr1) |= 8;
            }
            else
            {
                bool          flag4  = true;
                MyStorageData target = req.Target;
                vectori4.Z = minInLod.Z;
                while (true)
                {
                    while (true)
                    {
                        if (vectori4.Z <= maxInLod.Z)
                        {
                            vectori4.Y = minInLod.Y;
                            break;
                        }
                        if (flag4)
                        {
                            MyVoxelRequestFlags *flagsPtr2 = (MyVoxelRequestFlags *)ref req.Flags;
                            *((int *)flagsPtr2) |= 8;
                        }
                        return;
                    }
                    while (true)
                    {
                        if (vectori4.Y > maxInLod.Y)
                        {
                            float *singlePtr6 = (float *)ref pos.Z;
                            singlePtr6[0] += lodSize;
                            pos.Y          = vector.Y;
                            int *numPtr6 = (int *)ref vectori4.Z;
                            numPtr6[0]++;
                            break;
                        }
                        vectori4.X = minInLod.X;
                        Vector3I p         = (Vector3I)(vectori4 + vectori3);
                        int      linearIdx = target.ComputeLinear(ref p);
                        while (true)
                        {
                            if (vectori4.X <= maxInLod.X)
                            {
                                byte num4;
                                if ((!flag || (target.Material(linearIdx) == 0)) && (!flag2 || (target.Content(linearIdx) != 0)))
                                {
                                    byte num5;
                                    MyVoxelMaterialDefinition definition2 = this.GetMaterialForPosition(ref pos, lodSize, out num5, preciseOrePositions);
                                    num4 = (definition2 != null) ? definition2.Index : ((byte)0xff);
                                }
                                else
                                {
                                    num4 = 0xff;
                                }
                                target.Material(linearIdx, num4);
                                flag4     &= num4 == 0xff;
                                linearIdx += target.StepLinear;
                                float *singlePtr4 = (float *)ref pos.X;
                                singlePtr4[0] += lodSize;
                                int *numPtr4 = (int *)ref vectori4.X;
                                numPtr4[0]++;
                                continue;
                            }
                            else
                            {
                                float *singlePtr5 = (float *)ref pos.Y;
                                singlePtr5[0] += lodSize;
                                pos.X          = vector.X;
                                int *numPtr5 = (int *)ref vectori4.Y;
                                numPtr5[0]++;
                            }
                            break;
                        }
                    }
                }
            }
        }
        internal void ReadContentRange(MyStorageData target, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod)
        {
            float lodVoxelSizeHalf;
            BoundingBox queryBox;
            BoundingSphere querySphere;
            SetupReading(lodIndex, ref minInLod, ref maxInLod, out lodVoxelSizeHalf, out queryBox, out querySphere);
            float lodVoxelSize = 2f * lodVoxelSizeHalf;

            ProfilerShort.Begin("Testing removed shapes");
            var overlappedRemovedShapes = OverlappedRemovedShapes;
            overlappedRemovedShapes.Clear();
            ContainmentType testRemove = ContainmentType.Disjoint;
            for (int i = 0; i < m_data.RemovedShapes.Length; ++i)
            {
                var test = m_data.RemovedShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize);
                if (test == ContainmentType.Contains)
                {
                    testRemove = ContainmentType.Contains;
                    break; // completely empty so we can leave
                }
                else if (test == ContainmentType.Intersects)
                {
                    testRemove = ContainmentType.Intersects;
                    overlappedRemovedShapes.Add(m_data.RemovedShapes[i]);
                }
            }
            ProfilerShort.End();
            if (testRemove == ContainmentType.Contains)
            {
                ProfilerShort.Begin("target.BlockFillContent");
                target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY);
                ProfilerShort.End();
                return;
            }

            ProfilerShort.Begin("Testing filled shapes");
            var overlappedFilledShapes = OverlappedFilledShapes;
            overlappedFilledShapes.Clear();
            ContainmentType testFill = ContainmentType.Disjoint;
            for (int i = 0; i < m_data.FilledShapes.Length; ++i)
            {
                var test = m_data.FilledShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize);
                if (test == ContainmentType.Contains)
                {
                    overlappedFilledShapes.Clear();
                    testFill = ContainmentType.Contains;
                    break;
                }
                else if (test == ContainmentType.Intersects)
                {
                    overlappedFilledShapes.Add(m_data.FilledShapes[i]);
                    testFill = ContainmentType.Intersects;
                }
            }
            ProfilerShort.End();

            if (testFill == ContainmentType.Disjoint)
            {
                ProfilerShort.Begin("target.BlockFillContent");
                target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY);
                ProfilerShort.End();
                return;
            }
            else if (testRemove == ContainmentType.Disjoint && testFill == ContainmentType.Contains)
            {
                ProfilerShort.Begin("target.BlockFillContent");
                target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_FULL);
                ProfilerShort.End();
                return;
            }

            ProfilerShort.Begin("Distance field computation");
            Vector3I v = minInLod;
            Vector3 localPos = v * lodVoxelSize;
            Vector3 localPosStart = v * lodVoxelSize;
            var writeOffsetLoc = writeOffset - minInLod;
            for (v.Z = minInLod.Z; v.Z <= maxInLod.Z; ++v.Z)
            {
                for (v.Y = minInLod.Y; v.Y <= maxInLod.Y; ++v.Y)
                {
                    v.X = minInLod.X;
                    var write2 = v + writeOffsetLoc;
                    var write = target.ComputeLinear(ref write2);
                    for (; v.X <= maxInLod.X; ++v.X)
                    {
                        //Vector3 localPos = v * lodVoxelSize;

                        //ProfilerShort.Begin("Dist filled");
                        float distFill;
                        if (testFill == ContainmentType.Contains)
                        {
                            distFill = -1f;
                        }
                        else
                        {
                            //ProfilerShort.Begin("shape distances");
                            distFill = 1f;
                            foreach (var shape in overlappedFilledShapes)
                            {
                                distFill = Math.Min(distFill, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule));
                                if (distFill <= -1)
                                    break;

                            }
                            //ProfilerShort.End();
                        }

                        //ProfilerShort.BeginNextBlock("Dist removed");
                        float distRemoved = 1f;
                        if (testRemove != ContainmentType.Disjoint)
                        {
                            foreach (var shape in overlappedRemovedShapes)
                            {
                                distRemoved = Math.Min(distRemoved, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule));
                                if (distRemoved <= -1)
                                    break;
                            }
                        }
                        //ProfilerShort.BeginNextBlock("content");
                        float signedDist = MathHelper.Max(distFill, -distRemoved);

                        var fillRatio = MathHelper.Clamp(-signedDist, -1f, 1f) * 0.5f + 0.5f;
                        byte content = (byte)(fillRatio * MyVoxelConstants.VOXEL_CONTENT_FULL);
                        target.Content(write, content);
                        Debug.Assert(Math.Abs((((float)content) / MyVoxelConstants.VOXEL_CONTENT_FULL) - fillRatio) <= 0.5f);
                        //ProfilerShort.End();
                        write += target.StepLinear;
                        localPos.X += lodVoxelSize;
                    }
                    localPos.Y += lodVoxelSize;
                    localPos.X = localPosStart.X;
                }
                localPos.Z += lodVoxelSize;
                localPos.Y = localPosStart.Y;
            }
            ProfilerShort.End();
        }
        private void ProcessCell(MyStorageData cache, IMyStorage storage, Vector3I cell)
        {
            var min = cell << MyOreDetectorComponent.CELL_SIZE_IN_VOXELS_BITS;
            var max = min + (MyOreDetectorComponent.CELL_SIZE_IN_LOD_VOXELS - 1);

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

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

            var      materialData = MaterialData;
            Vector3I c;

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

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

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

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

            MyEntityOreDeposit result = null;

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

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

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

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

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

            return;
        }
Пример #14
0
            /// <summary>
            /// Start the reads if it is not already running.
            /// </summary>
            /// <param name="onFinished">Invoked when reads finish, not invoked if already running.</param>
            /// <returns>True if started, false if already running.</returns>
            public void Read()
            {
                Profiler.StartProfileBlock();
                m_throwOutVoxelData = Globals.ElapsedTime + Static.LifeSpan_VoxelData;

                NeedsUpdate = false;
                Vector3D m_oreDetectorPosition = m_oreDetector.GetPosition();
                Vector3D worldMin = m_oreDetectorPosition - m_maxRange;
                Vector3D worldMax = m_oreDetectorPosition + m_maxRange;

                float rangeSquared = m_maxRange * m_maxRange;

                Vector3I odPosVoxelStorage, m_localMin, m_localMax;

                MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxel.PositionLeftBottomCorner, ref m_oreDetectorPosition, out odPosVoxelStorage);
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxel.PositionLeftBottomCorner, ref worldMin, out m_localMin);
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxel.PositionLeftBottomCorner, ref worldMax, out m_localMax);

                MyVoxelBase vox = m_voxel as MyVoxelBase;

                if (m_voxel == null || m_voxel.Storage == null)
                {
                    Profiler.EndProfileBlock();
                    return;
                }

                m_localMin          = Vector3I.Clamp(m_localMin, vox.StorageMin, vox.StorageMax);
                m_localMax          = Vector3I.Clamp(m_localMax, vox.StorageMin, vox.StorageMax);
                m_localMin        >>= QUERY_LOD;
                m_localMax        >>= QUERY_LOD;
                odPosVoxelStorage >>= QUERY_LOD;
                Log.DebugLog("minLocal: " + m_localMin + ", maxLocal: " + m_localMax + ", odPosVoxelStorage: " + odPosVoxelStorage);

                Vector3I size = m_localMax - m_localMin;

                Log.DebugLog("number of coords in box: " + (size.X + 1) * (size.Y + 1) * (size.Z + 1));
                //ulong processed = 0;
                foreach (List <Vector3I> locations in m_materialLocations2.Values)
                {
                    locations.Clear();
                }

                Vector3I vector = new Vector3I();

                for (vector.X = m_localMin.X; vector.X < m_localMax.X; vector.X += QUERY_STEP)
                {
                    for (vector.Y = m_localMin.Y; vector.Y < m_localMax.Y; vector.Y += QUERY_STEP)
                    {
                        for (vector.Z = m_localMin.Z; vector.Z < m_localMax.Z; vector.Z += QUERY_STEP)
                        {
                            if (vector.DistanceSquared(odPosVoxelStorage) <= rangeSquared)
                            {
                                m_voxel.Storage.ReadRange(m_storage, MyStorageDataTypeFlags.ContentAndMaterial, QUERY_LOD, vector, vector + QUERY_MAX);

                                Vector3I index  = Vector3I.Zero;
                                Vector3I size3D = m_storage.Size3D;
                                for (index.X = 0; index.X < size3D.X; index.X++)
                                {
                                    for (index.Y = 0; index.Y < size3D.Y; index.Y++)
                                    {
                                        for (index.Z = 0; index.Z < size3D.Z; index.Z++)
                                        {
                                            int linear = m_storage.ComputeLinear(ref index);
                                            if (m_storage.Content(linear) > MyVoxelConstants.VOXEL_ISO_LEVEL)
                                            {
                                                byte mat = m_storage.Material(linear);
                                                if (Static.RareMaterials[mat])
                                                {
                                                    //Log.DebugLog("mat: " + mat + ", content: " + m_storage.Content(linear) + ", vector: " + vector + ", position: " + vector + index
                                                    //	+ ", name: " + MyDefinitionManager.Static.GetVoxelMaterialDefinition(mat).MinedOre, "Read()");
                                                    //m_materialLocations[vector + index] = mat;

                                                    List <Vector3I> locations;
                                                    if (!m_materialLocations2.TryGetValue(mat, out locations))
                                                    {
                                                        locations = new List <Vector3I>(1000);
                                                        m_materialLocations2.Add(mat, locations);
                                                    }
                                                    locations.Add(vector + index);

                                                    //processed++;
                                                    goto Finished_Deposit;
                                                }
                                            }
                                        }
                                    }
                                }

                                Finished_Deposit :;
                                //processed++;
                            }
                        }
                    }
                }

                //Log.DebugLog("read " + processed + ", chunks" + ", number of mats: " + m_materialLocations.Count, Logger.severity.DEBUG);
                Profiler.EndProfileBlock();
            }