private int GetDivideIndex(ref Vector3I renderCellCoord)
            {
                // TODO: Optimize
                int divideIndex = 0;

                if (m_lodDivisions > 1)
                {
                    BoundingBoxD lodAabb = m_boundingBoxes.GetAabb(m_boundingBoxes.GetRoot());
                    Vector3I     test    = Vector3I.Round(lodAabb.Size / (double)MyVoxelCoordSystems.RenderCellSizeInMeters(m_lod));
                    //Vector3I lodSizeMinusOne = m_parentClipmap.LodSizeMinusOne(m_lod);
                    //Vector3I lodSize = lodSizeMinusOne + Vector3I.One;
                    Vector3I lodSize         = test;
                    Vector3I lodSizeMinusOne = test - 1;
                    Vector3I lodDivision     = Vector3I.One * (m_lodDivisions - 1);

                    var cellIterator = new Vector3I_RangeIterator(ref Vector3I.Zero, ref lodDivision);
                    for (; cellIterator.IsValid(); cellIterator.MoveNext())
                    {
                        Vector3I currentDivision = cellIterator.Current;
                        Vector3I min             = currentDivision * lodSize / m_lodDivisions;
                        Vector3I max             = (currentDivision + Vector3I.One) * lodSize / m_lodDivisions;
                        if (renderCellCoord.IsInsideInclusive(ref min, ref max))
                        {
                            break;
                        }
                    }
                    Debug.Assert(cellIterator.IsValid(), "Valid division index not found!");
                    Vector3I foundCell = cellIterator.Current;
                    divideIndex = GetDivideIndexFromMergeCell(ref foundCell);
                }
                return(divideIndex);
            }
Пример #2
0
        private void storage_RangeChangedPlanet(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags dataChanged)
        {
            ProfilerShort.Begin("MyVoxelMap::storage_RangeChanged");
            Vector3I minSector = minChanged / PHYSICS_SECTOR_SIZE_METERS;
            Vector3I maxSector = maxChanged / PHYSICS_SECTOR_SIZE_METERS;

            MyVoxelPhysics voxelMap;

            if (m_physicsShapes != null)
            {
                for (var it = new Vector3I_RangeIterator(ref minSector, ref maxSector);
                     it.IsValid(); it.MoveNext())
                {
                    if (m_physicsShapes.TryGetValue(it.Current, out voxelMap))
                    {
                        if (voxelMap != null)
                        {
                            voxelMap.OnStorageChanged(minChanged, maxChanged, dataChanged);
                        }
                    }
                }
            }

            if (Render is MyRenderComponentVoxelMap)
            {
                (Render as MyRenderComponentVoxelMap).InvalidateRange(minChanged, maxChanged);
            }

            OnRangeChanged(minChanged, maxChanged, dataChanged);
            ProfilerShort.End();
        }
Пример #3
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();
                 }
             }
         }
     }
 }
Пример #4
0
        public static MyDefinitionId?VoxelMaterialAt(this MyVoxelBase voxel, Vector3D min, Vector3D grow,
                                                     ref MyStorageData cache)
        {
            if (cache == null)
            {
                cache = new MyStorageData();
            }
            var      shape = new BoundingBoxD(Vector3D.Min(min, min + grow), Vector3D.Max(min, min + grow));
            Vector3I voxMin;
            Vector3I voxMax;
            Vector3I voxCells;

            GetVoxelShapeDimensions(voxel, shape, out voxMin, out voxMax, out voxCells);
            Vector3I_RangeIterator cellsItr = new Vector3I_RangeIterator(ref Vector3I.Zero, ref voxCells);

            while (cellsItr.IsValid())
            {
                Vector3I cellMinCorner;
                Vector3I cellMaxCorner;
                GetCellCorners(ref voxMin, ref voxMax, ref cellsItr, out cellMinCorner, out cellMaxCorner);
                Vector3I rangeMin = cellMinCorner - 1;
                Vector3I rangeMax = cellMaxCorner + 1;
                voxel.Storage.ClampVoxelCoord(ref rangeMin);
                voxel.Storage.ClampVoxelCoord(ref rangeMax);
                cache.Resize(rangeMin, rangeMax);
                voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, rangeMin, rangeMax);

                var mortonCode    = -1;
                var maxMortonCode = cache.Size3D.Size;
                while (++mortonCode < maxMortonCode)
                {
                    Vector3I pos;
                    MyMortonCode3D.Decode(mortonCode, out pos);
                    var content = cache.Content(ref pos);
                    if (content <= MyVoxelConstants.VOXEL_CONTENT_EMPTY)
                    {
                        continue;
                    }
                    var material = cache.Material(ref pos);
                    var def      = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material);
                    if (def != null)
                    {
                        return(def.Id);
                    }
                }
                cellsItr.MoveNext();
            }

            return(null);
        }
Пример #5
0
        public void PrefetchShapeOnRay(ref LineD ray)
        {
            Vector3I minCorner, maxCorner;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref ray.From, out minCorner);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref ray.To, out maxCorner);

            minCorner /= PHYSICS_SECTOR_SIZE_METERS;
            maxCorner /= PHYSICS_SECTOR_SIZE_METERS;

            for (var it = new Vector3I_RangeIterator(ref minCorner, ref maxCorner);
                 it.IsValid(); it.MoveNext())
            {
                if (m_physicsShapes.ContainsKey(it.Current))
                {
                    m_physicsShapes[it.Current].PrefetchShapeOnRay(ref ray);
                }
            }
        }
Пример #6
0
        private void GeneratePhysicalShapeForBox(ref Vector3I increment, ref BoundingBoxD shapeBox)
        {
            if (!shapeBox.Intersects(PositionComp.WorldAABB))
            {
                return;
            }

            Vector3I minCorner, maxCorner;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Min, out minCorner);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Max, out maxCorner);

            minCorner /= PHYSICS_SECTOR_SIZE_METERS;
            maxCorner /= PHYSICS_SECTOR_SIZE_METERS;

            for (var it = new Vector3I_RangeIterator(ref minCorner, ref maxCorner);
                 it.IsValid(); it.MoveNext())
            {
                ProfilerShort.Begin("Myplanet::create physics shape");
                CreateVoxelPhysics(ref increment, ref it);
                ProfilerShort.End();
            }
        }
            private bool FindFirstAcceptableEntry()
            {
                while (true)
                {
                    while (m_storageIndex != -1)
                    {
                        Entry current = m_parent.m_storage[m_storageIndex];
                        if ((current.Point - m_point).LengthSquared() < m_distSq)
                        {
                            return(true);
                        }
                        m_previousIndex = m_storageIndex;
                        m_storageIndex  = current.NextEntry;
                    }

                    m_rangeIterator.MoveNext();

                    if (!FindNextNonemptyBin())
                    {
                        return(false);
                    }
                }
            }
Пример #8
0
        public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;

            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

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

                m_cache.Resize(cellMinCorner, cellMaxCorner);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, ref cellMinCorner, ref cellMaxCorner);

                for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
                {
                    var relPos = it.Current - cellMinCorner;

                    Vector3D vpos;
                    MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos);
                    float volume = shape.GetVolume(ref vpos);
                    if (volume > 0.5f)
                    {
                        m_cache.Material(ref relPos, materialIdx); // set material
                    }
                }

                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, ref cellMinCorner, ref cellMaxCorner);
            }
        }
        public override IEnumerable <ProceduralObject> Generate(BoundingSphereD include, BoundingSphereD?exclude)
        {
            var root        = Vector3D.Transform(include.Center, m_invTransform);
            var excludeRoot = exclude.HasValue
                ? Vector3D.Transform(exclude.Value.Center, m_invTransform)
                : default(Vector3D);

            var minLocal = root - include.Radius;
            var maxLocal = root + include.Radius;

            minLocal = Vector3D.Max(minLocal, Shape.RelevantArea.Min);
            maxLocal = Vector3D.Min(maxLocal, Shape.RelevantArea.Max);
            for (var i = 0; i < m_layers.Length; i++)
            {
                var layer = m_layers[i];
                var includePaddedSquared = include.Radius + layer.AsteroidSpacing * 2;
                includePaddedSquared *= includePaddedSquared;
                var excludePaddedSquared = exclude.HasValue ? exclude.Value.Radius - layer.AsteroidSpacing * 2 : 0;
                excludePaddedSquared *= excludePaddedSquared;

                var minPos = Vector3I.Floor(minLocal / layer.AsteroidSpacing);
                var maxPos = Vector3I.Ceiling(maxLocal / layer.AsteroidSpacing);
                for (var itr = new Vector3I_RangeIterator(ref minPos, ref maxPos); itr.IsValid(); itr.MoveNext())
                {
                    var seed     = new Vector4I(itr.Current.X, itr.Current.Y, itr.Current.Z, i);
                    var localPos = ((Vector3D)itr.Current + 0.5) * layer.AsteroidSpacing;

                    // Very quick, include/exclude.
                    if (Vector3D.DistanceSquared(root, localPos) > includePaddedSquared)
                    {
                        continue;
                    }
                    if (exclude.HasValue && Vector3D.DistanceSquared(excludeRoot, localPos) < excludePaddedSquared)
                    {
                        continue;
                    }
                    var localWeight = Shape.Weight(localPos) + layer.UsableRegion - 1;
                    if (1 - layer.AsteroidDensity > localWeight)
                    {
                        continue;
                    }

                    var densityNoise = Math.Abs(m_noise.GetValue(localPos + Math.PI)) * localWeight;
                    if (1 - layer.AsteroidDensity > densityNoise)
                    {
                        continue;
                    }

                    localPos.X += 0.45 * m_noise.GetValue(localPos) * layer.AsteroidSpacing;
                    localPos.Y += 0.45 * m_noise.GetValue(localPos) * layer.AsteroidSpacing;
                    localPos.Z += 0.45 * m_noise.GetValue(localPos) * layer.AsteroidSpacing;

                    localPos.X += 0.35 * Shape.WarpSize.X * m_noiseWarp.GetValue(localPos);
                    localPos.Y += 0.35 * Shape.WarpSize.Y * m_noiseWarp.GetValue(localPos);
                    localPos.Z += 0.05 * Shape.WarpSize.Z * m_noiseWarp.GetValue(localPos);

                    var worldPos = Vector3D.Transform(localPos, m_transform);
                    ProceduralAsteroid procAst;
                    if (!m_asteroids.TryGetValue(seed, out procAst))
                    {
                        var size = m_noise.GetValue(worldPos) * (layer.AsteroidMaxSize - layer.AsteroidMinSize) +
                                   layer.AsteroidMinSize;
                        m_asteroids[seed] = procAst = new ProceduralAsteroid(this, seed, worldPos, size, m_layers[i]);
                    }

                    procAst.SpawnIfNeeded((procAst.m_boundingBox.Center - include.Center).LengthSquared());
                    yield return(procAst);
                }
            }
        }
Пример #10
0
        private void ComputeBlockMap(MyObjectBuilder_CubeGrid primaryGrid, IEnumerable <MyObjectBuilder_CubeGrid> allGrids, BlockSetInfo info)
        {
            m_blocks.Clear();
            info.BlockCountByType.Clear();
            info.ComponentCost.Clear();
            info.PowerConsumptionByGroup.Clear();

            BoundingBox = new BoundingBox((Vector3I)primaryGrid.CubeBlocks[0].Min, (Vector3I)primaryGrid.CubeBlocks[0].Min);

            foreach (var grid in allGrids)
            {
                foreach (var block in grid.CubeBlocks)
                {
                    var blockID = block.GetId();
                    var def     = MyDefinitionManager.Static.GetCubeBlockDefinition(blockID);
                    if (grid == primaryGrid)
                    {
                        Vector3I blockMin = block.Min;
                        Vector3I blockMax;
                        BlockTransformations.ComputeBlockMax(block, ref def, out blockMax);
                        BoundingBox = BoundingBox.Include(blockMin);
                        BoundingBox = BoundingBox.Include(blockMax);
                        for (var rangeItr = new Vector3I_RangeIterator(ref blockMin, ref blockMax); rangeItr.IsValid(); rangeItr.MoveNext())
                        {
                            m_blocks[rangeItr.Current] = block;
                        }
                    }
                    if (def == null)
                    {
                        if (m_erroredDefinitionIds.Add(blockID))
                        {
                            Logger.Error("Failed to find definition for block {0}", blockID);
                        }
                        continue;
                    }

                    info.BlockCountByType.AddValue(def.Id, 1);

                    foreach (var c in def.Components)
                    {
                        info.ComponentCost.AddValue(c.Definition, c.Count);
                    }

                    var powerUsage = PowerUtilities.MaxPowerConsumption(def);
                    // if it is off, ignore it.
                    if (Math.Abs(powerUsage.Consumption) > 1e-8 && ((block as MyObjectBuilder_FunctionalBlock)?.Enabled ?? true))
                    {
                        info.PowerConsumptionByGroup.AddValue(powerUsage.ResourceGroup, powerUsage.Consumption);
                    }
                }
            }
        }
Пример #11
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();
                }
            }
        private float GetDensity(ref Vector3D voxelCoord, int iterations)
        {
            // ReSharper disable once ImpureMethodCallOnReadonlyValueField
            if (Box.Contains(voxelCoord) == ContainmentType.Disjoint)
            {
                return(0f);
            }
            var inflatedBox = new BoundingBoxD(voxelCoord - 0.5f, voxelCoord + 0.5f);
            var queryBox    = new BoundingBoxD(inflatedBox.Min - 0.1f, inflatedBox.Max + 0.1f + QueryDir * 1000);

            {
                var hits = 0;
                foreach (var k in _tris)
                {
                    if (!inflatedBox.IntersectsTriangle(k.Origin, k.Origin + k.Edge1, k.Origin + k.Edge2))
                    {
                        continue;
                    }
                    hits++;
                    break;
                }

                if (hits == 0)
                {
                    return(IsInside(voxelCoord) ? 1 : 0);
                }
            }

            List <int> tmp;

            if (!_stackBorrow.TryPop(out tmp))
            {
                tmp = new List <int>();
            }
            else
            {
                tmp.Clear();
            }
            QueryTriangles(queryBox, tmp);

            var max = new Vector3I(iterations, iterations, iterations);
            var hit = 0;

            for (var itr = new Vector3I_RangeIterator(ref Vector3I.Zero, ref max); itr.IsValid(); itr.MoveNext())
            {
                var sample = inflatedBox.Min + inflatedBox.Extents * itr.Current / iterations;
                if (IsInsideHelper(sample, tmp))
                {
                    hit++;
                }
            }

            _stackBorrow.Push(tmp);
            return(hit / (float)((iterations + 1) * (iterations + 1) * (iterations + 1)));
        }
Пример #13
0
        private unsafe void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary <Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List <BoundingBoxD> bbList)
        {
            Vector3I vectori3;
            Vector3I vectori4;
            bool     flag = cache != null;

            if (flag)
            {
                this.CheckCacheValidity();
            }
            Vector3D *vectordPtr1 = (Vector3D *)ref obb.HalfExtent;

            vectordPtr1[0] += new Vector3D((double)border, 0.0, (double)border);
            BoundingBoxD  aABB   = obb.GetAABB();
            int           num    = (int)Math.Round((double)(aABB.HalfExtents.Max() * 2.0));
            BoundingBoxD *xdPtr1 = (BoundingBoxD *)ref aABB;

            xdPtr1 = (BoundingBoxD *)new BoundingBoxD(aABB.Min, aABB.Min + num);
            ((BoundingBoxD *)ref aABB).Translate(obb.Center - aABB.Center);
            bbList.Add(new BoundingBoxD(aABB.Min, aABB.Max));
            aABB = aABB.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled);
            aABB.Translate(voxelBase.SizeInMetresHalf);
            Vector3I voxelCoord = Vector3I.Round(aABB.Min);
            Vector3I vectori2   = (Vector3I)(voxelCoord + num);

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref voxelCoord, out vectori3);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref vectori2, out vectori4);
            MyOrientedBoundingBoxD xd2 = obb;

            xd2.Transform(voxelBase.PositionComp.WorldMatrixInvScaled);
            Vector3D *vectordPtr2 = (Vector3D *)ref xd2.Center;

            vectordPtr2[0] += voxelBase.SizeInMetresHalf;
            Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori3, ref vectori4);
            MyCellCoord            coord    = new MyCellCoord {
                Lod = 0
            };
            int     num2        = 0;
            Vector3 offset      = (Vector3)(originPosition - voxelBase.PositionLeftBottomCorner);
            Vector3 up          = -Vector3.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition));
            Matrix  rotation    = Matrix.CreateFromQuaternion(Quaternion.Inverse(Quaternion.CreateFromForwardUp(Vector3.CalculatePerpendicularVector(up), up)));
            Matrix  orientation = (Matrix)voxelBase.PositionComp.WorldMatrix.GetOrientation();

            while (iterator.IsValid())
            {
                BoundingBox box;
                MyIsoMesh   mesh;
                if (flag && cache.TryGetValue(iterator.Current, out mesh))
                {
                    if (mesh != null)
                    {
                        this.AddMeshTriangles(mesh, offset, rotation, orientation);
                    }
                    iterator.MoveNext();
                    continue;
                }
                coord.CoordInLod = iterator.Current;
                MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out box);
                if (!xd2.Intersects(ref box))
                {
                    num2++;
                    iterator.MoveNext();
                }
                else
                {
                    BoundingBoxD item = new BoundingBoxD(box.Min, box.Max).Translate(-voxelBase.SizeInMetresHalf);
                    bbList.Add(item);
                    Vector3I  lodVoxelMin = (coord.CoordInLod * 8) - 1;
                    MyIsoMesh mesh2       = MyPrecalcComponent.IsoMesher.Precalc(storage, 0, lodVoxelMin, (Vector3I)(((lodVoxelMin + 8) + 1) + 1), MyStorageDataTypeFlags.Content, 0);
                    if (flag)
                    {
                        cache[iterator.Current] = mesh2;
                    }
                    if (mesh2 != null)
                    {
                        this.AddMeshTriangles(mesh2, offset, rotation, orientation);
                    }
                    iterator.MoveNext();
                }
            }
        }
Пример #14
0
        public static bool DoGrading(
            IReadOnlyList <IRailGradeComponent> components, Vector3D target, float radius, uint availableForDeposit,
            uint availableForExcavate,
            uint[] excavatedByMaterial, byte materialToDeposit, out uint totalDeposited, out uint totalExcavated,
            bool testDynamic, out bool triedToChange, out bool intersectedDynamic)
        {
            try
            {
                var voxelRadius = (int)Math.Ceiling(radius);
                {
                    _dynamicEntities.Clear();
                    _workingVoxels.Clear();
                    var sphere = new BoundingSphereD(target, voxelRadius + 2);
                    var tmp    = MyEntities.GetEntitiesInSphere(ref sphere);
                    using (tmp.GetClearToken())
                        foreach (var e in tmp)
                        {
                            if (e is MyVoxelBase vox)
                            {
                                _workingVoxels.Add(vox);
                            }
                            if (e.Physics != null && !e.Physics.IsStatic)
                            {
                                _dynamicEntities.Add(e);
                            }
                        }
                }


                totalDeposited     = 0;
                totalExcavated     = 0;
                triedToChange      = false;
                intersectedDynamic = false;

                var fill     = new IGradeShape[components.Count];
                var excavate = new IGradeShape[components.Count];
                for (var i = 0; i < components.Count; i++)
                {
                    components[i].Unblit(out fill[i], out excavate[i]);
                }

                var voxel = MyGamePruningStructureSandbox.GetClosestPlanet(target)?.RootVoxel;
                if (voxel == null)
                {
                    return(false);
                }
                Vector3I center;
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref target, out center);
                var voxMin = center - voxelRadius - 1;
                var voxMax = center + voxelRadius + 1;
                _storage.Resize(voxMin, voxMax);
                voxel.Storage.ReadRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, 0, voxMin, voxMax);

                var changed = false;

                #region Mutate

                for (var i = 0;
                     i <= voxelRadius && (!triedToChange || availableForExcavate > 0 || availableForDeposit > 0);
                     i++)
                {
                    for (var e = new ShellEnumerator(center - i, center + i);
                         e.MoveNext() && (!triedToChange || availableForExcavate > 0 || availableForDeposit > 0);)
                    {
                        var      vCoord    = e.Current;
                        var      dataCoord = e.Current - voxMin;
                        Vector3D worldCoord;
                        MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref vCoord,
                                                                      out worldCoord);
                        var cval = _storage.Get(MyStorageDataTypeEnum.Content, ref dataCoord);

                        byte?excavationDensity = null;
                        if (cval > 0 && (!triedToChange || availableForExcavate > 0))
                        {
                            float density = 0;
                            foreach (var c in excavate.Where(x => x != null))
                            {
                                density = Math.Max(density, c.GetDensity(ref worldCoord));
                            }
                            if (density > 0)
                            {
                                excavationDensity = (byte)((1 - density) * byte.MaxValue);
                            }
                        }

                        byte?fillDensity = null;
                        if (cval < byte.MaxValue && (!triedToChange || availableForDeposit > 0))
                        {
                            float density = 0;
                            foreach (var c in fill.Where(x => x != null))
                            {
                                density = Math.Max(density, c.GetDensity(ref worldCoord));
                            }
                            if (density > 0)
                            {
                                fillDensity = (byte)(density * byte.MaxValue);
                            }
                        }

                        if ((!fillDensity.HasValue || cval >= fillDensity.Value) &&
                            (!excavationDensity.HasValue || cval <= excavationDensity.Value))
                        {
                            continue;
                        }

                        if (excavationDensity.HasValue && excavationDensity.Value < cval)
                        {
                            triedToChange = true;
                            var toExtract = (uint)Math.Min(availableForExcavate, cval - excavationDensity.Value);
                            if (toExtract > 0)
                            {
                                var mid = _storage.Get(MyStorageDataTypeEnum.Material, ref dataCoord);
                                if (excavatedByMaterial != null && mid < excavatedByMaterial.Length)
                                {
                                    excavatedByMaterial[mid] += toExtract;
                                }
                                DisableFarming(worldCoord);
                                _storage.Set(MyStorageDataTypeEnum.Content, ref dataCoord, (byte)(cval - toExtract));
                                totalExcavated       += toExtract;
                                availableForExcavate -= toExtract;
                                changed = true;
                            }

                            continue;
                        }

                        if (!fillDensity.HasValue || fillDensity.Value <= cval)
                        {
                            continue;
                        }
                        triedToChange = true;
                        var toFill = Math.Min(availableForDeposit, fillDensity.Value - cval);
                        if (toFill <= 0)
                        {
                            continue;
                        }

                        // would this deposit in midair?
                        {
                            var test = worldCoord;
                            test += 2 * Vector3D.Normalize(
                                MyGravityProviderSystem.CalculateNaturalGravityInPoint(worldCoord));
                            Vector3I vtest;
                            MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref test,
                                                                          out vtest);
                            vtest = Vector3I.Clamp(vtest, voxMin, voxMax) - voxMin;
                            if (vtest != vCoord && _storage.Get(MyStorageDataTypeEnum.Content, ref vtest) == 0)
                            {
                                continue;
                            }
                        }

                        // would it touch something dynamic?
                        if (testDynamic)
                        {
                            var box = new BoundingBoxD(worldCoord - 0.25, worldCoord + 0.25);
                            var bad = false;
                            foreach (var k in _dynamicEntities)
                            {
                                if (k.PositionComp.WorldAABB.Contains(box) == ContainmentType.Disjoint)
                                {
                                    continue;
                                }
                                var obb = new OrientedBoundingBoxD(k.PositionComp.LocalAABB, k.WorldMatrix);
                                if (!obb.Intersects(ref box))
                                {
                                    continue;
                                }
                                bad = true;
                                break;
                            }

                            if (bad)
                            {
                                intersectedDynamic = true;
                                continue;
                            }
                        }

                        changed = true;
                        DisableFarming(worldCoord);
                        availableForDeposit = (uint)(availableForDeposit - toFill);
                        totalDeposited     += (uint)toFill;
                        _storage.Set(MyStorageDataTypeEnum.Content, ref dataCoord, (byte)(cval + toFill));
                        if (fillDensity.Value <= cval * 1.25f)
                        {
                            continue;
                        }
                        var t = -Vector3I.One;
                        for (var itrContent = new Vector3I_RangeIterator(ref t, ref Vector3I.One);
                             itrContent.IsValid();
                             itrContent.MoveNext())
                        {
                            var tpos = dataCoord + itrContent.Current;
//                    var state = _storage.Get(MyStorageDataTypeEnum.Content, ref tpos);
//                    if (itrContent.Current == Vector3I.Zero || state == 0)
                            _storage.Set(MyStorageDataTypeEnum.Material, ref tpos, materialToDeposit);
                        }
                    }
                }

                #endregion Mutate

                if (changed)
                {
                    voxel.Storage.WriteRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, voxMin, voxMax);
                }

                return(changed);
            }
            finally
            {
                _dynamicEntities.Clear();
                _workingVoxels.Clear();
            }
        }
Пример #15
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();
                 }
             }
         }
     }
 }
Пример #16
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();
                     }
                 }
             }
         }
     }
 }
Пример #17
0
            private int GetDivideIndex(ref Vector3I renderCellCoord)
            {
                // TODO: Optimize
                int divideIndex = 0;
                if (m_lodDivisions > 1)
                {
                    BoundingBoxD lodAabb = m_boundingBoxes.GetAabb(m_boundingBoxes.GetRoot());
                    Vector3I test = Vector3I.Round(lodAabb.Size / (double)MyVoxelCoordSystems.RenderCellSizeInMeters(m_lod));
                    //Vector3I lodSizeMinusOne = m_parentClipmap.LodSizeMinusOne(m_lod);
                    //Vector3I lodSize = lodSizeMinusOne + Vector3I.One;
                    Vector3I lodSize = test;
                    Vector3I lodSizeMinusOne = test - 1;
                    Vector3I lodDivision = Vector3I.One * (m_lodDivisions - 1);

                    var cellIterator = new Vector3I_RangeIterator(ref Vector3I.Zero, ref lodDivision);
                    for (; cellIterator.IsValid(); cellIterator.MoveNext())
                    {
                        Vector3I currentDivision = cellIterator.Current;
                        Vector3I min = currentDivision * lodSize / m_lodDivisions;
                        Vector3I max = (currentDivision + Vector3I.One) * lodSize / m_lodDivisions;
                        if (renderCellCoord.IsInsideInclusive(ref min, ref max))
                            break;
                    }
                    Debug.Assert(cellIterator.IsValid(), "Valid division index not found!");
                    Vector3I foundCell = cellIterator.Current;
                    divideIndex = GetDivideIndexFromMergeCell(ref foundCell);
                }
                return divideIndex;
            }
Пример #18
0
        public void Apply(IReadOnlyList <IMyCubeGrid> group)
        {
            var totalAABB = BoundingBoxD.CreateInvalid();

            // ReSharper disable once LoopCanBeConvertedToQuery
            foreach (var grid in group)
            {
                totalAABB = totalAABB.Include(grid.WorldAABB);
            }
            var totalSphere = new BoundingSphereD(totalAABB.Center, totalAABB.HalfExtents.Length());

            foreach (var impact in m_impactDirectionRadius)
            {
                var      speed = impact.Velocity.Length();
                var      direction = (Vector3D)impact.Velocity / speed;
                Vector3D start, end;
                {
                    var rayOffset = totalAABB.HalfExtents * 0.8 * (Vector3D)impact.Shift;
                    // mag2(rayOffset + l*direction) == radius*radius
                    // (rayOffset + l*direction)*(rayOffset + l*direction)
                    // mag2(rayOffset) + 2*l*dot(direction, rayOffset) + l*l*mag2(direction)
                    // mag2(rayOffset) - (radius*radius) + 2*l*dot(direction, rayOffset) + l*l == 0
                    var         c   = rayOffset.LengthSquared() - totalSphere.Radius * totalSphere.Radius;
                    var         b   = 2 * Vector3D.Dot(direction, rayOffset);
                    const float a   = 1;
                    var         rad = b * b - 4 * a * c;
                    if (rad <= double.Epsilon)
                    {
                        continue;
                    }
                    var lLow  = (-b - Math.Sqrt(rad)) / (2 * a);
                    var lHigh = (-b + Math.Sqrt(rad)) / (2 * a);
                    start = totalSphere.Center + rayOffset + lLow * direction;
                    end   = totalSphere.Center + rayOffset + lHigh * direction;
                }
                var ray = new RayD(start, direction);

                var bestHitLocation        = default(Vector3D);
                var bestHitDistanceSquared = double.MaxValue;
                foreach (var grid in group)
                {
                    if (!grid.WorldAABB.Intersects(ray).HasValue)
                    {
                        continue;
                    }
                    var block = grid.RayCastBlocks(start, end);
                    if (!block.HasValue)
                    {
                        continue;
                    }
                    var world    = Vector3D.Transform(block.Value * grid.GridSize, grid.WorldMatrix);
                    var distance = Vector3D.DistanceSquared(world, start);
                    if (distance > bestHitDistanceSquared)
                    {
                        continue;
                    }
                    bestHitDistanceSquared = distance;
                    bestHitLocation        = world;
                }
                if (bestHitDistanceSquared > double.MaxValue / 2)
                {
                    continue;
                }
                var impactSphere = new BoundingSphereD(bestHitLocation, impact.Radius);
                var localSphere  = new BoundingSphereD();
                var damageAmount = impact.Mass * speed * speed * (4.0 / 3.0) * Math.PI;
                var damageTotals = new Dictionary <IMySlimBlock, double>();
                foreach (var grid in group)
                {
                    if (grid.WorldAABB.Intersects(impactSphere))
                    {
                        // compute local sphere.
                        localSphere.Center = Vector3D.Transform(impactSphere.Center, grid.WorldMatrixNormalizedInv) / grid.GridSize;
                        localSphere.Radius = impactSphere.Radius / grid.GridSize;
                        var min = Vector3I.Max(Vector3I.Floor(localSphere.Center - localSphere.Radius), grid.Min);
                        var max = Vector3I.Min(Vector3I.Ceiling(localSphere.Center + localSphere.Radius), grid.Max);
                        for (var itr = new Vector3I_RangeIterator(ref min, ref max); itr.IsValid(); itr.MoveNext())
                        {
                            if (localSphere.Contains(itr.Current) == ContainmentType.Disjoint)
                            {
                                continue;
                            }
                            var block = grid.GetCubeBlock(itr.Current);
                            if (block == null)
                            {
                                continue;
                            }
                            var distanceFactor = 1 - ((Vector3D)itr.Current - localSphere.Center).LengthSquared() / (localSphere.Radius * localSphere.Radius);
                            var blockDamage    = damageAmount * distanceFactor * ((block.BlockDefinition as MyCubeBlockDefinition)?.DeformationRatio ?? 1);
                            damageTotals.AddValue(block, blockDamage);
                        }
                    }
                }
                // No idea what shape key should be.
                Logger.Debug("Apply damage to {0} blocks", damageTotals.Count);
                var hitInfo = new MyHitInfo()
                {
                    Normal = direction, Position = impactSphere.Center, Velocity = impact.Velocity, ShapeKey = 0
                };
                foreach (var kv in damageTotals)
                {
                    kv.Key.DoDamage((float)kv.Value, MyDamageType.Explosion, true, hitInfo);
                }
            }
        }
        private void FindForestInitialCandidate()
        {
            BoundingBoxD groundBox = m_ground.PositionComp.WorldAABB;
            Vector3D boxSize = groundBox.Size;
            boxSize *= 0.1f;
            groundBox.Inflate(-boxSize);
            MyBBSetSampler sampler = new MyBBSetSampler(groundBox.Min, groundBox.Max);

            bool posIsValid = true;
            Vector3D worldPos = default(Vector3D);
            int counter = 0;
            do
            {
                // find random position for starting 
                worldPos = sampler.Sample();
                var worldPosProjected = worldPos;
                worldPosProjected.Y = 0.5f;
                posIsValid = true;
                counter++;
                Vector3D areaCheck = new Vector3D(20, 20, 20);
                foreach (var enqueued in m_initialForestLocations)
                {
                    // only interested in XZ plane
                    BoundingBoxD tmp = new BoundingBoxD(enqueued - areaCheck, enqueued + areaCheck);
                    tmp.Min.Y = 0;
                    tmp.Max.Y = 1;

                    if (tmp.Contains(worldPosProjected) == ContainmentType.Contains)
                    {
                        posIsValid = false;
                        break;
                    }
                }
            } while (!posIsValid && counter != 10);

            if (!posIsValid)
            {
                // could not find any position
                return;
            }

            var lineStart = new Vector3D(worldPos.X, groundBox.Max.Y, worldPos.Z);
            var lineEnd = new Vector3D(worldPos.X, groundBox.Min.Y, worldPos.Z);
            LineD line = new LineD(lineStart, lineEnd);
            VRage.Game.Models.MyIntersectionResultLineTriangleEx? result = null;
            var correctGroundDefinition = MyDefinitionManager.Static.GetVoxelMaterialDefinition("Grass");
            var materialId = correctGroundDefinition.Index;

            if (m_ground.GetIntersectionWithLine(ref line, out result, VRage.Game.Components.IntersectionFlags.DIRECT_TRIANGLES))
            {
                Vector3D intersectionPoint = result.Value.IntersectionPointInWorldSpace;
                Vector3I voxelCoord, minRead, maxRead;
                MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_ground.PositionLeftBottomCorner, ref intersectionPoint, out voxelCoord);
                minRead = voxelCoord - Vector3I.One;
                maxRead = voxelCoord + Vector3I.One;
                m_ground.Storage.ReadRange(m_voxelCache, MyStorageDataTypeFlags.Material, 0, ref minRead, ref maxRead);

                var minLocal = Vector3I.Zero;
                var maxLocal = Vector3I.One * 2;
                var it = new Vector3I_RangeIterator(ref minLocal, ref maxLocal);
                while (it.IsValid())
                {
                    var vec = it.Current;
                    var material = m_voxelCache.Material(ref vec);
                    if (material == materialId)
                    {
                        // found a location
                        var desired = voxelCoord - Vector3I.One + vec;
                        Vector3D desiredWorldPosition = default(Vector3D);
                        MyVoxelCoordSystems.VoxelCoordToWorldPosition(m_ground.PositionLeftBottomCorner, ref desired, out desiredWorldPosition);
                        m_initialForestLocations.Enqueue(desiredWorldPosition);
                        break;
                    }

                    it.MoveNext();
                }
            }
        }
        public float GetDensity(ref Vector3D worldCoord)
        {
            List <MeshGradeShape> maskedBorrow;

            using (PoolManager.Get(out maskedBorrow))
            {
                const int iterations        = MeshGradeShape.DefaultDensityIterations;
                var       intersectsSurface = false;
                foreach (var c in _components)
                {
                    if (c.IntersectsSurface(ref worldCoord))
                    {
                        intersectsSurface = true;
                        maskedBorrow.Add(c);
                    }
                    else if (c.IsInside(worldCoord))
                    {
                        return(1f);
                    }
                }

                if (!intersectsSurface)
                {
                    return(0f);
                }

                List <List <int> > borrowed;
                using (PoolManager.Get(out borrowed))
                {
                    foreach (var k in borrowed)
                    {
                        k.Clear();
                    }
                    while (borrowed.Count < maskedBorrow.Count)
                    {
                        borrowed.Add(new List <int>());
                    }

                    var inflatedBox = new BoundingBoxD(worldCoord - 0.5f, worldCoord + 0.5f);
                    var queryBox    = new BoundingBoxD(inflatedBox.Min - 0.1f, inflatedBox.Max + 0.1f + MeshGradeShape.QueryDir * 1000);
                    for (var i = 0; i < maskedBorrow.Count; i++)
                    {
                        maskedBorrow[i].QueryTriangles(queryBox, borrowed[i]);
                    }

                    var max = new Vector3I(iterations, iterations, iterations);
                    var hit = 0;
                    for (var itr = new Vector3I_RangeIterator(ref Vector3I.Zero, ref max); itr.IsValid(); itr.MoveNext())
                    {
                        var sample = inflatedBox.Min + inflatedBox.Extents * itr.Current / iterations;
                        for (var i = 0; i < maskedBorrow.Count; i++)
                        {
                            if (maskedBorrow[i].IsInsideHelper(sample, borrowed[i]))
                            {
                                hit++;
                                break;
                            }
                        }
                    }

                    return(hit / (float)((iterations + 1) * (iterations + 1) * (iterations + 1)));
                }
            }
        }
Пример #21
0
        public static ulong FillInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;
            ulong retValue = 0;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

            //voxel must be at least 1 m from side to be closed (e.g. without holes in it)
            minCorner = Vector3I.Max(Vector3I.One, minCorner);
            maxCorner = Vector3I.Max(minCorner, maxCorner);

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

                Vector3I originalMinCorner = cellMinCorner;
                Vector3I originalMaxCorner = cellMaxCorner;

                voxelMap.Storage.ClampVoxelCoord(ref cellMinCorner, 0);
                voxelMap.Storage.ClampVoxelCoord(ref cellMaxCorner, 0);

                ClampingInfo minCornerClamping = CheckForClamping(originalMinCorner, cellMinCorner);
                ClampingInfo maxCornerClamping = CheckForClamping(originalMaxCorner, cellMaxCorner);

                m_cache.Resize(cellMinCorner, cellMaxCorner);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cellMinCorner, ref cellMaxCorner);

                ulong filledSum = 0;

                for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
                {
                    var relPos = it.Current - cellMinCorner; // get original amount
                    var original = m_cache.Content(ref relPos);

                    if (original == MyVoxelConstants.VOXEL_CONTENT_FULL) // if there is nothing to add
                        continue;

                    //if there was some claping, fill the clamp region with material
                    if ((it.Current.X == cellMinCorner.X && minCornerClamping.X) || (it.Current.X == cellMaxCorner.X && maxCornerClamping.X) ||
                        (it.Current.Y == cellMinCorner.Y && minCornerClamping.Y) || (it.Current.Y == cellMaxCorner.Y && maxCornerClamping.Y) ||
                        (it.Current.Z == cellMinCorner.Z && minCornerClamping.Z) || (it.Current.Z == cellMaxCorner.Z && maxCornerClamping.Z))
                    {
                        m_cache.Material(ref relPos, materialIdx);
                        continue;
                    }

                    Vector3D vpos;
                    MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos);
                    var volume = shape.GetVolume(ref vpos);


                    if (volume <= 0f) // there is nothing to fill
                        continue;

                    m_cache.Material(ref relPos, materialIdx); // set material

                    var toFill = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                    long newVal = MathHelper.Clamp(original + toFill, 0, Math.Max(original, toFill));

                    m_cache.Content(ref relPos, (byte)newVal);
                    filledSum += (ulong)(newVal - original);
                }
                if (filledSum > 0)
                {
                    RemoveSmallVoxelsUsingChachedVoxels();
                    voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref cellMinCorner, ref cellMaxCorner);
                }

                retValue += filledSum;
            }

            if (retValue > 0)
                OnVoxelChanged(OperationType.Fill, voxelMap, shape);

            return retValue;
        }
Пример #22
0
        public static ulong CutOutShape(MyVoxelBase voxelMap, MyShape shape)
        {
            if(MySession.Static.EnableVoxelDestruction == false)
            {
                return 0;
            }

            Vector3I minCorner, maxCorner, numCells;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);
            ulong changedVolumeAmount = 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;
                voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
                voxelMap.Storage.ClampVoxelCoord(ref cacheMax);

                ulong removedSum = 0;
                m_cache.Resize(cacheMin, cacheMax);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax);

                for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
                {
                    var relPos = it.Current - cacheMin; // get original amount
                    var original = m_cache.Content(ref relPos);

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

                    Vector3D vpos;
                    MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos);
                    var volume = shape.GetVolume(ref vpos);

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

                    var toRemove = (int)(MyVoxelConstants.VOXEL_CONTENT_FULL - (volume * MyVoxelConstants.VOXEL_CONTENT_FULL));
                    var newVal = Math.Min(toRemove, original);
                    ulong removed = (ulong)Math.Abs(original - newVal);

                    m_cache.Content(ref relPos, (byte)newVal);
                    removedSum += removed;
                }

                if (removedSum > 0)
                {
                    RemoveSmallVoxelsUsingChachedVoxels(); // must stay because of the around when filling voxels
                    voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax);
                }

                changedVolumeAmount += removedSum;
            }

            if (changedVolumeAmount > 0)
                OnVoxelChanged(OperationType.Cut, voxelMap, shape);

            return changedVolumeAmount;
        }
Пример #23
0
        private void storage_RangeChangedPlanet(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags dataChanged)
        {
            ProfilerShort.Begin("MyVoxelMap::storage_RangeChanged");
            Vector3I minSector = minChanged / PHYSICS_SECTOR_SIZE_METERS;
            Vector3I maxSector = maxChanged / PHYSICS_SECTOR_SIZE_METERS;

            MyVoxelPhysics voxelMap;

            if (m_physicsShapes != null)
            {
                for (var it = new Vector3I_RangeIterator(ref minSector, ref maxSector);
                    it.IsValid(); it.MoveNext())
                {
                    if (m_physicsShapes.TryGetValue(it.Current, out voxelMap))
                    {
                        if (voxelMap != null)
                            voxelMap.OnStorageChanged(minChanged, maxChanged, dataChanged);
                    }
                }
            }

            if (Render is MyRenderComponentVoxelMap)
            {
                (Render as MyRenderComponentVoxelMap).InvalidateRange(minChanged, maxChanged);
            }

            OnRangeChanged(minChanged, maxChanged, dataChanged);
            ProfilerShort.End();
        }
Пример #24
0
        public static float Laze(this MyVoxelBase voxel, BoundingSphereD area, float amount, ref MyStorageData cache)
        {
            if (cache == null)
            {
                cache = new MyStorageData();
            }
            Vector3I voxMin;
            Vector3I voxMax;
            Vector3I voxCells;
            var      shape = new BoundingBoxD(area.Center - area.Radius, area.Center + area.Radius);

            GetVoxelShapeDimensions(voxel, shape, out voxMin, out voxMax, out voxCells);
            ulong totalRemoved = 0uL;
            Vector3I_RangeIterator cellsItr = new Vector3I_RangeIterator(ref Vector3I.Zero, ref voxCells);

            while (cellsItr.IsValid())
            {
                Vector3I cellMinCorner;
                Vector3I cellMaxCorner;
                GetCellCorners(ref voxMin, ref voxMax, ref cellsItr, out cellMinCorner, out cellMaxCorner);
                Vector3I rangeMin = cellMinCorner - 1;
                Vector3I rangeMax = cellMaxCorner + 1;
                voxel.Storage.ClampVoxelCoord(ref rangeMin);
                voxel.Storage.ClampVoxelCoord(ref rangeMax);
                ulong removed = 0uL;
                cache.Resize(rangeMin, rangeMax);
                voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, rangeMin, rangeMax);
                Vector3I_RangeIterator cellVoxItr = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner);
                while (cellVoxItr.IsValid())
                {
                    Vector3I cellVoxIdx = cellVoxItr.Current - rangeMin;
                    byte     b          = cache.Content(ref cellVoxIdx);
                    if (b != 0)
                    {
                        Vector3I current = cellVoxItr.Current;
                        Vector3D worldPos;
                        MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref current,
                                                                      out worldPos);
                        var d = (worldPos - area.Center).Length() / area.Radius;
                        if (d < 1)
                        {
                            int nVal = Math.Max(0, (int)(b - 255f * amount * (1 - d)));
                            cache.Content(ref cellVoxIdx, (byte)nVal);
                            removed += b - (ulong)nVal;
                        }
                    }

                    cellVoxItr.MoveNext();
                }

                if (removed > 0uL)
                {
                    voxel.Storage.WriteRange(cache, MyStorageDataTypeFlags.Content, rangeMin, rangeMax);
                }

                totalRemoved += removed;
                cellsItr.MoveNext();
            }

            return(totalRemoved / 255f);
        }
Пример #25
0
        public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

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

                m_cache.Resize(cellMinCorner, cellMaxCorner);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, ref cellMinCorner, ref cellMaxCorner);

                for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
                {
                    var relPos = it.Current - cellMinCorner;

                    Vector3D vpos;
                    MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos);
                    float volume = shape.GetVolume(ref vpos);
                    if (volume > 0.5f)
                        m_cache.Material(ref relPos, materialIdx); // set material
                }

                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, ref cellMinCorner, ref cellMaxCorner);
            }
        }
Пример #26
0
        private void GeneratePhysicalShapeForBox(ref Vector3I increment, ref BoundingBoxD shapeBox)
        {
            if (!shapeBox.Intersects(PositionComp.WorldAABB))
                return;

            Vector3I minCorner, maxCorner;
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Min, out minCorner);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Max, out maxCorner);

            minCorner /= PHYSICS_SECTOR_SIZE_METERS;
            maxCorner /= PHYSICS_SECTOR_SIZE_METERS;

            for (var it = new Vector3I_RangeIterator(ref minCorner, ref maxCorner);
                it.IsValid(); it.MoveNext())
            {
                ProfilerShort.Begin("Myplanet::create physics shape");
                CreateVoxelPhysics(ref increment, ref it);
                ProfilerShort.End();
            }
        }
Пример #27
0
        private void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary<Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> bbList)
        {
            bool useCache = cache != null;
            if (useCache)
                CheckCacheValidity();

            obb.HalfExtent += new Vector3D(border, 0, border);
            BoundingBoxD bb = obb.GetAABB();            
            int aabbSideSide = (int)Math.Round(bb.HalfExtents.Max() * 2);
            bb = new BoundingBoxD(bb.Min, bb.Min + aabbSideSide);
            bb.Translate(obb.Center - bb.Center);

            // For debug
            bbList.Add(new BoundingBoxD(bb.Min, bb.Max));

            bb = (BoundingBoxD)bb.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled);
            bb.Translate(voxelBase.SizeInMetresHalf);

            Vector3I min = Vector3I.Round(bb.Min);
            Vector3I max = min + aabbSideSide;
            Vector3I geomMin, geomMax;
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref min, out geomMin);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref max, out geomMax);

            var cullBox = obb;
            cullBox.Transform(voxelBase.PositionComp.WorldMatrixInvScaled);
            cullBox.Center += voxelBase.SizeInMetresHalf;
            ProfilerShort.Begin("WOOOORK");

            Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref geomMin, ref geomMax);
            MyCellCoord coord = new MyCellCoord();
            BoundingBox localAabb;
            coord.Lod = NAVMESH_LOD;
            int hits = 0;
            MyIsoMesh gMesh;
            Vector3 offset = originPosition - voxelBase.PositionLeftBottomCorner;

            // Calculate rotation
            Vector3 gravityVector = -Vector3.Normalize(GameSystems.MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition));
            Vector3 forwardVector = Vector3.CalculatePerpendicularVector(gravityVector);
            Quaternion quaternion = Quaternion.CreateFromForwardUp(forwardVector, gravityVector);
            Matrix rotation = Matrix.CreateFromQuaternion(Quaternion.Inverse(quaternion));

            Matrix ownRotation = voxelBase.PositionComp.WorldMatrix.GetOrientation();

            while (it.IsValid())
            {
                ProfilerShort.Begin("ITERATOR");

                if (useCache && cache.TryGetValue(it.Current, out gMesh))
                {
                    if (gMesh != null)
                    {
                        AddMeshTriangles(gMesh, offset, rotation, ownRotation);
                    }
                    it.MoveNext();
                    ProfilerShort.End();
                    continue;
                }
                    
                coord.CoordInLod = it.Current;
                MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out localAabb);
                
                if (!cullBox.Intersects(ref localAabb))
                {
                    hits++;
                    it.MoveNext();
                    ProfilerShort.End();
                    continue;
                }
                ProfilerShort.End();

                var debugBB = new BoundingBoxD(localAabb.Min, localAabb.Max).Translate(-voxelBase.SizeInMetresHalf);
                bbList.Add(debugBB);

                ProfilerShort.Begin("Mesh Calc");
                var voxelStart = coord.CoordInLod * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS - 1;
                var voxelEnd = voxelStart + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS //- 1
                    + 1 // overlap to neighbor so geometry is stitched together within same LOD
                    + 1; // for eg. 9 vertices in row we need 9 + 1 samples (voxels)

                var generatedMesh = MyPrecalcComponent.IsoMesher.Precalc(storage, NAVMESH_LOD, voxelStart, voxelEnd, false, false, true);
                ProfilerShort.End();

                if (useCache)
                    cache[it.Current] = generatedMesh;

                if (generatedMesh != null)
                {
                    ProfilerShort.Begin("Mesh NOT NULL");
                    AddMeshTriangles(generatedMesh, offset, rotation, ownRotation);
                    ProfilerShort.End();
                }
                it.MoveNext();
            }
            ProfilerShort.End();
        }
Пример #28
0
        public void PrefetchShapeOnRay(ref LineD ray)
        {
            Vector3I minCorner, maxCorner;
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref ray.From, out minCorner);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref ray.To, out maxCorner);

            minCorner /= PHYSICS_SECTOR_SIZE_METERS;
            maxCorner /= PHYSICS_SECTOR_SIZE_METERS;

            for (var it = new Vector3I_RangeIterator(ref minCorner, ref maxCorner);
                it.IsValid(); it.MoveNext())
            {
                if (m_physicsShapes.ContainsKey(it.Current))
                {
                    m_physicsShapes[it.Current].PrefetchShapeOnRay(ref ray);
                }
            }
        }
        private void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary <Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List <BoundingBoxD> bbList)
        {
            bool useCache = cache != null;

            if (useCache)
            {
                CheckCacheValidity();
            }

            obb.HalfExtent += new Vector3D(border, 0, border);
            BoundingBoxD bb           = obb.GetAABB();
            int          aabbSideSide = (int)Math.Round(bb.HalfExtents.Max() * 2);

            bb = new BoundingBoxD(bb.Min, bb.Min + aabbSideSide);
            bb.Translate(obb.Center - bb.Center);

            // For debug
            bbList.Add(new BoundingBoxD(bb.Min, bb.Max));

            bb = (BoundingBoxD)bb.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled);
            bb.Translate(voxelBase.SizeInMetresHalf);

            Vector3I min = Vector3I.Round(bb.Min);
            Vector3I max = min + aabbSideSide;
            Vector3I geomMin, geomMax;

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref min, out geomMin);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref max, out geomMax);

            var cullBox = obb;

            cullBox.Transform(voxelBase.PositionComp.WorldMatrixInvScaled);
            cullBox.Center += voxelBase.SizeInMetresHalf;
            ProfilerShort.Begin("WOOOORK");

            Vector3I_RangeIterator it    = new Vector3I_RangeIterator(ref geomMin, ref geomMax);
            MyCellCoord            coord = new MyCellCoord();
            BoundingBox            localAabb;

            coord.Lod = NAVMESH_LOD;
            int       hits = 0;
            MyIsoMesh gMesh;
            Vector3   offset = originPosition - voxelBase.PositionLeftBottomCorner;

            // Calculate rotation
            Vector3    gravityVector = -Vector3.Normalize(GameSystems.MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition));
            Vector3    forwardVector = Vector3.CalculatePerpendicularVector(gravityVector);
            Quaternion quaternion    = Quaternion.CreateFromForwardUp(forwardVector, gravityVector);
            Matrix     rotation      = Matrix.CreateFromQuaternion(Quaternion.Inverse(quaternion));

            Matrix ownRotation = voxelBase.PositionComp.WorldMatrix.GetOrientation();

            while (it.IsValid())
            {
                ProfilerShort.Begin("ITERATOR");

                if (useCache && cache.TryGetValue(it.Current, out gMesh))
                {
                    if (gMesh != null)
                    {
                        AddMeshTriangles(gMesh, offset, rotation, ownRotation);
                    }
                    it.MoveNext();
                    ProfilerShort.End();
                    continue;
                }

                coord.CoordInLod = it.Current;
                MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out localAabb);

                if (!cullBox.Intersects(ref localAabb))
                {
                    hits++;
                    it.MoveNext();
                    ProfilerShort.End();
                    continue;
                }
                ProfilerShort.End();

                var debugBB = new BoundingBoxD(localAabb.Min, localAabb.Max).Translate(-voxelBase.SizeInMetresHalf);
                bbList.Add(debugBB);

                ProfilerShort.Begin("Mesh Calc");
                var voxelStart = coord.CoordInLod * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS - 1;
                var voxelEnd   = voxelStart + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS //- 1
                                 + 1                                                        // overlap to neighbor so geometry is stitched together within same LOD
                                 + 1;                                                       // for eg. 9 vertices in row we need 9 + 1 samples (voxels)

                var generatedMesh = MyPrecalcComponent.IsoMesher.Precalc(storage, NAVMESH_LOD, voxelStart, voxelEnd, false, false, true);
                ProfilerShort.End();

                if (useCache)
                {
                    cache[it.Current] = generatedMesh;
                }

                if (generatedMesh != null)
                {
                    ProfilerShort.Begin("Mesh NOT NULL");
                    AddMeshTriangles(generatedMesh, offset, rotation, ownRotation);
                    ProfilerShort.End();
                }
                it.MoveNext();
            }
            ProfilerShort.End();
        }
Пример #30
0
        private void Process(CommandFeedback feedback, IMyCubeGrid grid)
        {
            if (grid.CustomName == null || !grid.CustomName.StartsWithICase("EqProcBuild"))
            {
                return;
            }
            var ob = grid.GetObjectBuilder(true) as MyObjectBuilder_CubeGrid;

            if (ob == null)
            {
                return;
            }
            this.Info("Begin processing {0}", grid.CustomName);
            feedback?.Invoke("Processing {0}", grid.CustomName);
            try
            {
                var dummyDel  = new List <MyTuple <MyObjectBuilder_CubeBlock, string> >();
                var blockKeep = new List <MyObjectBuilder_CubeBlock>();
                var blockMap  = new Dictionary <Vector3I, MyObjectBuilder_CubeBlock>(Vector3I.Comparer);
                foreach (var block in ob.CubeBlocks)
                {
                    var mount = false;
                    foreach (var name in block.ConfigNames())
                    {
                        if (!name.StartsWithICase(MountDelegated) && !name.StartsWithICase(ReservedSpaceDelegated))
                        {
                            continue;
                        }
                        dummyDel.Add(MyTuple.Create(block, name));
                        mount = true;
                        break;
                    }
                    if (mount)
                    {
                        continue;
                    }

                    var      blockMin = (Vector3I)block.Min;
                    Vector3I blockMax;
                    BlockTransformations.ComputeBlockMax(block, out blockMax);
                    for (var rangeItr = new Vector3I_RangeIterator(ref blockMin, ref blockMax); rangeItr.IsValid(); rangeItr.MoveNext())
                    {
                        blockMap[rangeItr.Current] = block;
                    }
                    blockKeep.Add(block);
                }
                this.Info("Found {0} blocks to keep, {1} block mounts to remap", blockKeep.Count, dummyDel.Count);
                foreach (var pair in dummyDel)
                {
                    var block   = pair.Item1;
                    var useName = pair.Item2;

                    IEnumerable <Base6Directions.Direction> dirs = Base6Directions.EnumDirections;
                    var def       = MyDefinitionManager.Static.GetCubeBlockDefinition(pair.Item1);
                    var transform = new MatrixI(block.BlockOrientation);
                    if (def?.MountPoints != null)
                    {
                        var mountDirs = new HashSet <Base6Directions.Direction>();
                        foreach (var mount in def.MountPoints)
                        {
                            mountDirs.Add(Base6Directions.GetDirection(Vector3I.TransformNormal(mount.Normal, ref transform)));
                        }
                    }

                    var args     = useName.Split(' ');
                    var keepArgs = new List <string>(args.Length);
                    foreach (var arg in args)
                    {
                        if (arg.StartsWithICase(PartDummyUtils.ArgumentMountDirection))
                        {
                            Base6Directions.Direction dir;
                            if (Enum.TryParse(arg.Substring(2), out dir))
                            {
                                dirs = new[] { transform.GetDirection(Base6Directions.GetOppositeDirection(dir)) }
                            }
                            ;
                            else
                            {
                                this.Error("Failed to parse direction argument \"{0}\"", arg);
                                feedback?.Invoke("Error: Failed to parse direction argument \"{0}\"", arg);
                            }
                        }
                        else
                        {
                            keepArgs.Add(arg);
                        }
                    }
                    useName = string.Join(" ", keepArgs);

                    MyObjectBuilder_CubeBlock outputBlock = null;
                    var outputDir = Base6Directions.Direction.Forward;
                    foreach (var dir in dirs)
                    {
                        MyObjectBuilder_CubeBlock tmp;
                        if (!blockMap.TryGetValue(block.Min + Base6Directions.GetIntVector(dir), out tmp))
                        {
                            continue;
                        }
                        if (tmp.ConfigNames().Any(x => x.StartsWithICase(MountDelegated)))
                        {
                            continue;
                        }
                        if (outputBlock != null)
                        {
                            this.Error("Multiple directions found for {0}", pair.Item2);
                            feedback?.Invoke("Error: Multiple directions found for {0}", pair.Item2);
                        }
                        outputBlock = tmp;
                        outputDir   = dir;
                    }
                    if (outputBlock == null || !ApplyDelegate(ob, block, useName, outputBlock, outputDir))
                    {
                        this.Error("Failed to find delegated mount point for {0}", pair.Item2);
                        feedback?.Invoke("Error: Failed to find delegated mount point for {0}", pair.Item2);
                    }
                }
                ob.CubeBlocks = blockKeep;

                // Grab related grids!
                var relatedGrids = new HashSet <IMyCubeGrid> {
                    grid
                };
                var scanRelated           = new Queue <IMyCubeGrid>();
                var relatedGridController = new Dictionary <IMyCubeGrid, IMyCubeBlock>();
                scanRelated.Enqueue(grid);
                while (scanRelated.Count > 0)
                {
                    var          subGrid = scanRelated.Dequeue();
                    IMyCubeBlock controllerForThisGrid = null;
                    relatedGridController.TryGetValue(subGrid, out controllerForThisGrid);

                    subGrid.GetBlocks(null, (y) =>
                    {
                        var x = y?.FatBlock;
                        if (x == null)
                        {
                            return(false);
                        }
                        var childGrid = (x as IMyMechanicalConnectionBlock)?.TopGrid;
                        if (childGrid != null && relatedGrids.Add(childGrid))
                        {
                            scanRelated.Enqueue(childGrid);
                            relatedGridController[childGrid] = x.CubeGrid == grid ? x : controllerForThisGrid;
                        }
                        var parentGrid = (x as IMyAttachableTopBlock)?.Base?.CubeGrid;
                        // ReSharper disable once InvertIf
                        if (parentGrid != null && relatedGrids.Add(parentGrid))
                        {
                            scanRelated.Enqueue(parentGrid);
                            relatedGridController[parentGrid] = x.CubeGrid == grid ? x : controllerForThisGrid;
                        }
                        return(false);
                    });
                }
                relatedGrids.Remove(grid);
                var removedNoController = relatedGrids.RemoveWhere(x => !relatedGridController.ContainsKey(x));
                if (removedNoController > 0)
                {
                    this.Error("Failed to find the mechanical connection block for all subgrids.  {0} will be excluded",
                               removedNoController);
                    feedback?.Invoke("Error: Failed to find the mechanical connection block for all subgrids.  {0} will be excluded",
                                     removedNoController);
                }
                // Need to add reserved space for subgrids so they don't overlap.  So compute that.  Yay!
                foreach (var rel in relatedGrids)
                {
                    IMyCubeBlock root;
                    if (!relatedGridController.TryGetValue(rel, out root))
                    {
                        this.Error("Unable to find the mechanical connection for grid {0}", rel.CustomName);
                        feedback?.Invoke("Error: Unable to find the mechanical connection for grid {0}",
                                         rel.CustomName);
                        continue;
                    }
                    MyObjectBuilder_CubeBlock blockDest;
                    if (blockMap.TryGetValue(root.Min, out blockDest))
                    {
                        var blockLocal = (MatrixD) new MatrixI(blockDest.BlockOrientation).GetFloatMatrix();
                        blockLocal.Translation = (Vector3I)blockDest.Min * grid.GridSize;
                        var blockWorld = MatrixD.Multiply(blockLocal, grid.WorldMatrix);

                        var worldAABB = rel.WorldAABB;
                        worldAABB = Utilities.TransformBoundingBox(worldAABB, MatrixD.Invert(blockWorld));
                        var gridAABB = new BoundingBoxI(Vector3I.Floor(worldAABB.Min / grid.GridSize), Vector3I.Ceiling(worldAABB.Max / grid.GridSize));
                        var code     = $"{PartMetadata.ReservedSpacePrefix} NE:{gridAABB.Min.X}:{gridAABB.Min.Y}:{gridAABB.Min.Z} PE:{gridAABB.Max.X}:{gridAABB.Max.Y}:{gridAABB.Max.Z}";
                        this.Info("Added reserved space for subgrid {0}: Spec is \"{1}\"", rel.CustomName, code);
                        if (blockDest.Name == null || blockDest.Name.Trim().Length == 0)
                        {
                            blockDest.Name = code;
                        }
                        else
                        {
                            blockDest.Name += PartMetadata.MultiUseSentinel + code;
                        }
                    }
                    else
                    {
                        this.Error("Unable to find the OB for grid block {0} ({1}, {2}, {3}).  Is it a delegate?", (root as IMyTerminalBlock)?.CustomName ?? root.Name, root.Min.X, root.Min.Y, root.Min.Z);
                        feedback?.Invoke("Unable to the find OB for grid block {0} ({1}, {2}, {3}).  Was it a delegate?", (root as IMyTerminalBlock)?.CustomName ?? root.Name, root.Min.X, root.Min.Y, root.Min.Z);
                    }
                }

                var allGrids = new List <MyObjectBuilder_CubeGrid>(relatedGrids.Count + 1)
                {
                    ob
                };
                allGrids.AddRange(relatedGrids.Select(relGrid => relGrid.GetObjectBuilder(false)).OfType <MyObjectBuilder_CubeGrid>());

                // Compose description: TODO I'd love if this actually worked :/
                // var storage = new MyPartMetadata();
                // storage.InitFromGrids(ob, allGrids);
                // var data = Convert.ToBase64String(MyAPIGateway.Utilities.SerializeToBinary(storage.GetObjectBuilder()));

                var defOut = new MyObjectBuilder_PrefabDefinition()
                {
                    Id        = new SerializableDefinitionId(typeof(MyObjectBuilder_PrefabDefinition), grid.CustomName),
                    CubeGrids = allGrids.ToArray()
                };

                var fileName = grid.CustomName + ".sbc";
                this.Info("Saving {1} grids as {0}", fileName, defOut.CubeGrids.Length);
                feedback?.Invoke("Saving {1} grids as {0}", fileName, defOut.CubeGrids.Length);

                var mishMash = new MyObjectBuilder_Definitions()
                {
                    Prefabs = new MyObjectBuilder_PrefabDefinition[] { defOut }
                };
                var writer = MyAPIGateway.Utilities.WriteBinaryFileInLocalStorage(fileName, typeof(DesignTools));
                var obCode = MyAPIGateway.Utilities.SerializeToXML(mishMash);
                obCode = obCode.Replace("encoding=\"utf-16\"", "encoding=\"utf-8\"");
                writer.Write(Encoding.UTF8.GetBytes(obCode));
                writer.Close();
            }
            catch (Exception e)
            {
                this.Error("Failed to parse.  Error:\n{0}", e.ToString());
            }
        }
Пример #31
0
        public static ulong FillInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;
            ulong    retValue = 0;

            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

            //voxel must be at least 1 m from side to be closed (e.g. without holes in it)
            minCorner = Vector3I.Max(Vector3I.One, minCorner);
            maxCorner = Vector3I.Max(minCorner, maxCorner);

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

                Vector3I originalMinCorner = cellMinCorner;
                Vector3I originalMaxCorner = cellMaxCorner;

                voxelMap.Storage.ClampVoxelCoord(ref cellMinCorner, 0);
                voxelMap.Storage.ClampVoxelCoord(ref cellMaxCorner, 0);

                ClampingInfo minCornerClamping = CheckForClamping(originalMinCorner, cellMinCorner);
                ClampingInfo maxCornerClamping = CheckForClamping(originalMaxCorner, cellMaxCorner);

                m_cache.Resize(cellMinCorner, cellMaxCorner);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cellMinCorner, ref cellMaxCorner);

                ulong filledSum = 0;

                for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
                {
                    var relPos   = it.Current - cellMinCorner; // get original amount
                    var original = m_cache.Content(ref relPos);

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

                    //if there was some claping, fill the clamp region with material
                    if ((it.Current.X == cellMinCorner.X && minCornerClamping.X) || (it.Current.X == cellMaxCorner.X && maxCornerClamping.X) ||
                        (it.Current.Y == cellMinCorner.Y && minCornerClamping.Y) || (it.Current.Y == cellMaxCorner.Y && maxCornerClamping.Y) ||
                        (it.Current.Z == cellMinCorner.Z && minCornerClamping.Z) || (it.Current.Z == cellMaxCorner.Z && maxCornerClamping.Z))
                    {
                        m_cache.Material(ref relPos, materialIdx);
                        continue;
                    }

                    Vector3D vpos;
                    MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos);
                    var volume = shape.GetVolume(ref vpos);


                    if (volume <= 0f) // there is nothing to fill
                    {
                        continue;
                    }

                    m_cache.Material(ref relPos, materialIdx); // set material

                    var  toFill = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL);
                    long newVal = MathHelper.Clamp(original + toFill, 0, Math.Max(original, toFill));

                    m_cache.Content(ref relPos, (byte)newVal);
                    filledSum += (ulong)(newVal - original);
                }
                if (filledSum > 0)
                {
                    RemoveSmallVoxelsUsingChachedVoxels();
                    voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref cellMinCorner, ref cellMaxCorner);
                }

                retValue += filledSum;
            }

            if (retValue > 0)
            {
                OnVoxelChanged(MyVoxelBase.OperationType.Fill, voxelMap, shape);
            }

            return(retValue);
        }
        private static bool IntersectsInternalExpensive(ref PartFromPrefab partA, ref MatrixI transformA, ref MatrixI invTransformA, ref PartFromPrefab partB, ref MatrixI transformB, ref MatrixI invTransformB, bool testOptional)
        {
            using (partA.LockSharedUsing())
                using (partB.LockSharedUsing())
                {
                    var reservedAAll = Utilities.TransformBoundingBox(partA.ReservedSpace, ref transformA);
                    var reservedBAll = Utilities.TransformBoundingBox(partB.ReservedSpace, ref transformB);

                    var reservedA = new List <MyTuple <ReservedSpace, BoundingBox> >(partA.m_reservedSpaces.Count);
                    // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref)
                    foreach (var aabb in partA.m_reservedSpaces)
                    {
                        if (!aabb.IsOptional || testOptional)
                        {
                            reservedA.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformA)));
                        }
                    }

                    var reservedB = new List <MyTuple <ReservedSpace, BoundingBox> >(partB.m_reservedSpaces.Count);
                    // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref)
                    foreach (var aabb in partB.m_reservedSpaces)
                    {
                        if (!aabb.IsOptional || testOptional)
                        {
                            reservedB.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformB)));
                        }
                    }

                    // Reserved spaces intersect?
                    if (partA.m_reservedSpaces.Count > 0 && partB.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(reservedBAll))
                    {
                        if (reservedA.Any(x => reservedB.Any(y => !y.Item1.IsShared && !x.Item1.IsShared && x.Item2.Intersects(y.Item2))))
                        {
                            return(true);
                        }
                    }

                    var blockAAll = Utilities.TransformBoundingBox(partA.BoundingBox, ref transformA);
                    var blockBAll = Utilities.TransformBoundingBox(partB.BoundingBox, ref transformB);

                    // Block spaces intersect with reserved space?
                    if (partA.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(blockBAll))
                    {
                        foreach (var aabb in reservedA)
                        {
                            var min = Vector3I.Floor(Vector3.Max(aabb.Item2.Min, blockBAll.Min));
                            var max = Vector3I.Ceiling(Vector3.Min(aabb.Item2.Max, blockBAll.Max));
                            for (var vi = new Vector3I_RangeIterator(ref min, ref max); vi.IsValid(); vi.MoveNext())
                            {
                                if (partB.CubeExists(Vector3I.Transform(vi.Current, invTransformB)))
                                {
                                    return(true);
                                }
                            }
                        }
                    }
                    if (partB.m_reservedSpaces.Count > 0 && reservedBAll.Intersects(blockAAll))
                    {
                        foreach (var aabb in reservedB)
                        {
                            var min = Vector3I.Floor(Vector3.Max(aabb.Item2.Min, blockAAll.Min));
                            var max = Vector3I.Ceiling(Vector3.Min(aabb.Item2.Max, blockAAll.Max));
                            for (var vi = new Vector3I_RangeIterator(ref min, ref max); vi.IsValid(); vi.MoveNext())
                            {
                                if (partA.CubeExists(Vector3I.Transform(vi.Current, invTransformA)))
                                {
                                    return(true);
                                }
                            }
                        }
                    }

                    // Block space intersects with block space?
                    if (!blockAAll.Intersects(blockBAll))
                    {
                        return(false);
                    }
                    if (partA.m_blocks.Count < partB.m_blocks.Count)
                    {
                        foreach (var pos in partA.m_blocks.Keys)
                        {
                            if (partB.CubeExists(Vector3I.Transform(Vector3I.Transform(pos, ref transformA), ref invTransformB)))
                            {
                                return(true);
                            }
                        }
                    }
                    else
                    {
                        foreach (var pos in partB.m_blocks.Keys)
                        {
                            if (partA.CubeExists(Vector3I.Transform(Vector3I.Transform(pos, ref transformB), ref invTransformA)))
                            {
                                return(true);
                            }
                        }
                    }
                    return(false);
                }
        }
Пример #33
0
        public static ulong CutOutShape(MyVoxelBase voxelMap, MyShape shape)
        {
            if (MySession.Static.EnableVoxelDestruction == false)
            {
                return(0);
            }

            Vector3I minCorner, maxCorner, numCells;

            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);
            ulong changedVolumeAmount = 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;
                voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
                voxelMap.Storage.ClampVoxelCoord(ref cacheMax);

                ulong removedSum = 0;
                m_cache.Resize(cacheMin, cacheMax);
                voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax);

                for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext())
                {
                    var relPos   = it.Current - cacheMin; // get original amount
                    var original = m_cache.Content(ref relPos);

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

                    Vector3D vpos;
                    MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos);
                    var volume = shape.GetVolume(ref vpos);

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

                    var   toRemove = (int)(MyVoxelConstants.VOXEL_CONTENT_FULL - (volume * MyVoxelConstants.VOXEL_CONTENT_FULL));
                    var   newVal   = Math.Min(toRemove, original);
                    ulong removed  = (ulong)Math.Abs(original - newVal);

                    m_cache.Content(ref relPos, (byte)newVal);
                    removedSum += removed;
                }

                if (removedSum > 0)
                {
                    RemoveSmallVoxelsUsingChachedVoxels(); // must stay because of the around when filling voxels
                    voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax);
                }

                changedVolumeAmount += removedSum;
            }

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

            return(changedVolumeAmount);
        }
Пример #34
0
        public IEnumerable <MyTuple <Vector4I, Vector4D> > TryGetSpawnIn(BoundingBoxD aabb, Func <BoundingBoxD, bool> test = null)
        {
            var rootCellsMin = Vector3I.Floor(aabb.Min / m_cubeSideMax);
            var rootCellsMax = Vector3I.Floor(aabb.Max / m_cubeSideMax);

            for (var rootCells = new Vector3I_RangeIterator(ref rootCellsMin, ref rootCellsMax); rootCells.IsValid(); rootCells.MoveNext())
            {
                foreach (var k in GetSpawnsIn(new Vector4I(rootCells.Current, 0), aabb, test))
                {
                    yield return(k);
                }
            }
        }