private void OnDepositQueryComplete(MyDepositQuery query, ConcurrentCachingList <MyEntityOreDeposit> deposits, List <Vector3I> emptyCells)
        {
            foreach (var deposit in deposits)
            {
                Vector3I depositCell = deposit.CellCoord;
                m_depositsByCellCoord[depositCell] = deposit;
                //RegisterMarker(deposit);
                //MyHud.OreMarkers.RegisterMarker(deposit);
            }

            foreach (var emptyCell in emptyCells)
            {
                m_emptyCellCoord.Add(emptyCell);
            }

            m_tasksRunning--;

            var bb = new BoundingBoxI(query.Min, query.Max);

            m_completed += bb.Size.Size;
            Logger.Instance.LogDebugOnGameThread($"Completed: {m_completed}");

            if (m_tasksRunning == 0)
            {
                Scanning = false;
            }
        }
Esempio n. 2
0
        public ContainmentType Intersect(ref BoundingBoxI box, int lod, bool exhaustiveContainmentCheck = true)
        {
            BoundingBoxI xi = box;

            xi.Translate(-this.m_voxelRangeMin);
            return(this.m_octree.Intersect(ref xi, lod, exhaustiveContainmentCheck));
        }
Esempio n. 3
0
        public void LoadDetailsSync()
        {
            ReadVoxelDetails(SourceVoxelFilepath ?? VoxelFilepath);

            if (_voxelMap != null && (MaterialAssets == null || MaterialAssets.Count == 0))
            {
                Dictionary <string, long> details = _voxelMap.RefreshAssets();
                _contentBounds         = _voxelMap.BoundingContent;
                _inflatedContentBounds = _voxelMap.InflatedBoundingContent;
                _voxCells = _voxelMap.VoxCells;
                Center    = new Vector3D(_voxelMap.ContentCenter.X + 0.5f + PositionX, _voxelMap.ContentCenter.Y + 0.5f + PositionY, _voxelMap.ContentCenter.Z + 0.5f + PositionZ);

                var sum  = details.Values.ToList().Sum();
                var list = new List <VoxelMaterialAssetModel>();

                foreach (var kvp in details)
                {
                    list.Add(new VoxelMaterialAssetModel {
                        MaterialName = kvp.Key, Volume = (double)kvp.Value / 255, Percent = (double)kvp.Value / (double)sum
                    });
                }

                MaterialAssets = list;
            }
        }
Esempio n. 4
0
        public static BoundingBoxI TransformBoundingBox(BoundingBoxI box, ref MatrixI matrix)
        {
            Vector3I a, b;

            Vector3I.Transform(ref box.Min, ref matrix, out a);
            Vector3I.Transform(ref box.Max, ref matrix, out b);
            return(new BoundingBoxI(Vector3I.Min(a, b), Vector3I.Max(a, b)));
        }
        public ContainmentType Intersect(ref BoundingBoxI box, bool lazy)
        {
            BoundingBoxI localCoords = box;

            localCoords.Translate(-m_voxelRangeMin);

            return(m_octree.Intersect(ref localCoords, lazy));
        }
Esempio n. 6
0
        private static bool IntersectsVoxelSurface(OrientedBoundingBoxD box)
        {
            var data = VoxelData;

            using (PoolManager.Get(out List <MyEntity> entities))
            {
                MyGamePruningStructure.GetTopmostEntitiesInBox(box.GetAABB(), entities, MyEntityQueryType.Static);
                foreach (var ent in entities)
                {
                    if (ent is MyVoxelBase voxel && !(ent is MyVoxelPhysics))
                    {
                        var invWorld      = voxel.PositionComp.WorldMatrixInvScaled;
                        var storageBounds = BoundingBoxD.CreateInvalid();
                        var voxelOffset   = (voxel.Size >> 1) + voxel.StorageMin;
                        var storageObb    = box;
                        storageObb.Transform(invWorld);
                        storageObb.HalfExtent /= voxel.VoxelSize;
                        storageObb.Center      = storageObb.Center / voxel.VoxelSize + voxelOffset;
                        storageBounds.Include(storageObb.GetAABB());

                        var storageMin = Vector3I.Max(Vector3I.Floor(storageBounds.Min), voxel.StorageMin);
                        var storageMax = Vector3I.Min(Vector3I.Ceiling(storageBounds.Max), voxel.StorageMax);
                        var localBox   = new BoundingBoxI(storageMin, storageMax);
                        localBox.Inflate(1);
                        var floatBox = new BoundingBox(localBox);
                        if (voxel.IntersectStorage(ref floatBox) == ContainmentType.Disjoint)
                        {
                            continue;
                        }
                        data.Resize(storageMin, storageMax);
                        voxel.Storage.ReadRange(data, MyStorageDataTypeFlags.Content, 0, storageMin, storageMax);
                        foreach (var pt in new BoundingBoxI(Vector3I.Zero, storageMax - storageMin).EnumeratePoints())
                        {
                            var voxelBox    = new BoundingBoxD(storageMin + pt, storageMin + pt + 1);
                            var containment = storageObb.Contains(ref voxelBox);
                            if (containment == ContainmentType.Disjoint)
                            {
                                continue;
                            }
                            var tmpPt   = pt;
                            var index   = data.ComputeLinear(ref tmpPt);
                            var content = data.Content(index);
                            if (containment == ContainmentType.Intersects && content >= 127)
                            {
                                return(true);
                            }
                            if (containment == ContainmentType.Contains && content > 0)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
Esempio n. 7
0
        public ContainmentType Intersect(BoundingBoxI box, int lod)
        {
            if (this.Closed)
            {
                return(ContainmentType.Disjoint);
            }
            BoundingBox box2 = new BoundingBox(box);

            box2.Translate(-this.Shape.Center());
            return(this.Shape.IntersectBoundingBox(ref box2, 1f));
        }
Esempio n. 8
0
        private bool QueryEmptyOrFull(int minX, int minY, int minZ, int maxX, int maxY, int maxZ)
        {
            BoundingBoxI box = new BoundingBoxI(new Vector3I(minX, minY, minZ), new Vector3I(maxX, maxY, maxZ));

            if (box.Volume() < 100f)
            {
                return(false);
            }
            bool         flag = this.m_voxelMap.Storage.Intersect(ref box, 0, true) != ContainmentType.Intersects;
            BoundingBoxD xd   = new BoundingBoxD(new Vector3((float)minX, (float)minY, (float)minZ) * 8f, new Vector3((float)maxX, (float)maxY, (float)maxZ) * 8f);

            xd.TransformFast(base.Entity.WorldMatrix);
            MyOrientedBoundingBoxD xd1 = new MyOrientedBoundingBoxD(xd, base.Entity.WorldMatrix);

            MyRenderProxy.DebugDrawAABB(xd, flag ? Color.Green : Color.Red, 1f, 1f, false, false, false);
            return(flag);
        }
Esempio n. 9
0
        public static void RayCastGrid(this IMyCubeGrid grid, Vector3 rayStart, Vector3 direction, Action <Vector3I> visitor)
        {
            Matrix worldToLocal = Matrix.Invert(grid.WorldMatrix);

            direction.Normalize();
            Vector3 transformedDirection = Vector3.TransformNormal(direction, worldToLocal);

            Vector3  currentPointF = Vector3.Transform(rayStart, worldToLocal) / grid.GridSize;
            Vector3I currentPoint  = Vector3I.Round(currentPointF);

            if (!Inside(grid.Min, grid.Max, currentPoint))
            {
                //find intersection
                BoundingBoxI bbI = new BoundingBoxI(grid.Min, grid.Max);
                var          hit = bbI.Intersects(new Ray(currentPointF, transformedDirection));
                if (!hit.HasValue)
                {
                    //Program.instance.Log($"No misses bounding box");
                    return; //no intersection
                }
                currentPointF += (float)hit.Value * transformedDirection;
                currentPoint   = Vector3I.Round(currentPointF);
            }

            //Program.instance.Log($"Starting at: {currentPoint}");
            //Program.instance.Log($"Direction at: {transformedDirection}");

            while (Inside(grid.Min, grid.Max, currentPoint))
            {
                if (grid.CubeExists(currentPoint))
                {
                    visitor(currentPoint);
                }

                float toXShift = ClosestGridBlockChange(currentPointF.X, transformedDirection.X);
                float toYShift = ClosestGridBlockChange(currentPointF.Y, transformedDirection.Y);
                float toZShift = ClosestGridBlockChange(currentPointF.Z, transformedDirection.Z);

                currentPointF += transformedDirection * Min(toXShift, toYShift, toZShift);
                currentPoint   = Vector3I.Round(currentPointF);

                //Program.instance.Log($"Shift by: {toXShift}, {toYShift}, {toZShift}");
                //Program.instance.Log($"Walk:{currentPoint}");
            }
        }
        public ContainmentType Intersect(BoundingBoxI box, bool lazy)
        {
            ContainmentType ct = ContainmentType.Disjoint;

            BoundingBox    bb = new BoundingBox(box);
            BoundingSphere sp = new BoundingSphere(bb.Center, bb.Extents.Length() / 2f);

            // Check filled shapes.
            foreach (var shape in m_data.FilledShapes)
            {
                var c = shape.Contains(ref bb, ref sp, 1f);

                if (c == ContainmentType.Contains)
                {
                    ct = c;
                }
                else if (c == ContainmentType.Intersects && ct == ContainmentType.Disjoint)
                {
                    ct = c;
                }
            }

            // Check shapes removed, we don't check how they are removed so we only discard if the removed shape covers the whole bb.
            if (ct != ContainmentType.Disjoint)
            {
                foreach (var shape in m_data.RemovedShapes)
                {
                    var c = shape.Contains(ref bb, ref sp, 1f);

                    if (c == ContainmentType.Contains)
                    {
                        ct = ContainmentType.Disjoint;
                        break;
                    }

                    else if (c == ContainmentType.Intersects)
                    {
                        ct = ContainmentType.Intersects;
                    }
                }
            }

            return(ct);
        }
Esempio n. 11
0
        internal MyVoxelPhysicsBody(MyVoxelBase voxelMap, float phantomExtend, float predictionSize = 3f, bool lazyPhysics = false) : base(voxelMap, RigidBodyFlag.RBF_STATIC)
        {
            this.RunningBatchTask     = new MyPrecalcJobPhysicsBatch[2];
            this.m_nearbyEntities     = new HashSet <IMyEntity>();
            this.m_nearbyEntitiesLock = new FastResourceLock();
            this.m_workTracker        = new MyWorkTracker <MyCellCoord, MyPrecalcJobPhysicsPrefetch>(MyCellCoord.Comparer);
            this.m_cellsOffset        = new Vector3I(0, 0, 0);
            this.m_staticForCluster   = true;
            this.m_predictionSize     = 3f;
            this.m_queuedRange        = new BoundingBoxI(-1, -1);
            this.InvalidCells         = new HashSet <Vector3I>[] { new HashSet <Vector3I>(), new HashSet <Vector3I>() };
            this.m_predictionSize     = predictionSize;
            this.m_phantomExtend      = phantomExtend;
            this.m_voxelMap           = voxelMap;
            Vector3I vectori1 = this.m_voxelMap.Size >> 3;

            this.m_cellsOffset = this.m_voxelMap.StorageMin >> 3;
            if (!MyFakes.ENABLE_LAZY_VOXEL_PHYSICS || !lazyPhysics)
            {
                this.CreateRigidBodies();
            }
            base.MaterialType = VRage.Game.MyMaterialType.ROCK;
        }
Esempio n. 12
0
        private void ComputeSectorParameters()
        {
            // face size is the length of an edge of a cube with half diagonal r.
            // this is equal to sqrt(2) * r
            m_sectorFaceSize = MaximumRadius * 1.41421356237309504880;

            // Ensure at least one sector.
            if (m_sectorFaceSize < MIN_SECTOR_SIZE)
            {
                m_numSectors = 1;
                m_sectorSize = m_sectorFaceSize;
            }
            else
            {
                m_numSectors = (int)Math.Floor(m_sectorFaceSize / MIN_SECTOR_SIZE);
                m_sectorSize = m_sectorFaceSize / m_numSectors;
            }

            m_sectorBox = new BoundingBoxI(0, m_numSectors - 1);

            m_sectorDensity = Generator.SectorDensity;

            m_itemsPerSector = m_sectorDensity * m_sectorSize * m_sectorSize;
        }
Esempio n. 13
0
        private void FillOutOfBounds(MyStorageData target, MyStorageDataTypeEnum type, ref Vector3I woffset, int lodIndex, Vector3I minInLod, Vector3I maxInLod)
        {
            var value = MyVoxelConstants.DefaultValue(type);
            var size = new Vector3I((1 << (m_treeHeight + LeafLodCount - lodIndex)) - 1);

            var offset = woffset - minInLod;

            var req = new BoundingBoxI(minInLod, maxInLod);
            var tree = new BoundingBoxI(Vector3I.Zero, size);

            if (req.Intersects(ref tree) != true)
            {
                target.BlockFill(type, offset + minInLod, offset + maxInLod, value);
                return;
            }

            // Left
            if (minInLod.X < 0)
            {
                var min = minInLod;
                var max = maxInLod;

                max.X = -1;
                minInLod.X = 0;

                target.BlockFill(type, min + offset, max + offset, value);
            }

            // Right
            if (maxInLod.X > size.X)
            {
                var min = minInLod;
                var max = maxInLod;

                min.X = size.X+1;
                minInLod.X = size.X;

                target.BlockFill(type, min + offset, max + offset, value);
            }

            // Top
            if (minInLod.Y < 0)
            {
                var min = minInLod;
                var max = maxInLod;

                max.Y = -1;
                minInLod.Y = 0;

                target.BlockFill(type, min + offset, max + offset, value);
            }

            // Bottom
            if (maxInLod.Y > size.Y)
            {
                var min = minInLod;
                var max = maxInLod;

                min.Y = size.Y + 1;
                minInLod.Y = size.Y;

                target.BlockFill(type, min + offset, max + offset, value);
            }

            // Back
            if (minInLod.Y < 0)
            {
                var min = minInLod;
                var max = maxInLod;

                max.Y = -1;
                minInLod.Y = 0;

                target.BlockFill(type, min + offset, max + offset, value);
            }

            // Front
            if (maxInLod.Y > size.Y)
            {
                var min = minInLod;
                var max = maxInLod;

                min.Y = size.Y + 1;
                minInLod.Y = size.Y;

                target.BlockFill(type, min + offset, max + offset, value);
            }
        }
Esempio n. 14
0
            internal void DoClipping_Old(Vector3D localPosition, float farPlaneDistance, RequestCollector collector)
            {
                m_localPosition = localPosition;
                MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex, out m_nearDistance, out m_farDistance);

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum)
                {
                    return;
                }


                //var localFrustum = new BoundingFrustumD(CameraFrustumGetter().Matrix * m_parent.m_invWorldMatrix);
                var frustum = CameraFrustumGetter();

                Vector3I min, max;
                Vector3I ignoreMin, ignoreMax;

                var minD = m_localPosition - m_farDistance;
                var maxD = m_localPosition + m_farDistance;

                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minD, out min);
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxD, out max);

                BoundingBoxI lodBox         = new BoundingBoxI(Vector3I.Zero, m_lodSizeMinusOne);
                bool         intersects     = false;
                bool         intersectsNear = false;

                m_localFarCameraBox  = new BoundingBoxI(min, max);
                m_localNearCameraBox = new BoundingBoxI(min, max);
                if (lodBox.Intersects(m_localFarCameraBox))
                {
                    intersects = true;
                    var intersection = lodBox.Intersect(m_localFarCameraBox);
                    min = intersection.Min;
                    max = intersection.Max;

                    //Optimize only LOD2 and higher by two lods, because neighbour cells shares border cells
                    if (m_lodIndex > 1)
                    {
                        float lowerFar, lowerNear;
                        MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex - 2, out lowerFar, out lowerNear);

                        var minNear = m_localPosition - (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                        var maxNear = m_localPosition + (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                        MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minNear, out ignoreMin);
                        MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxNear, out ignoreMax);

                        m_localNearCameraBox = new BoundingBoxI(ignoreMin, ignoreMax);
                        if (lodBox.Intersects(m_localNearCameraBox))
                        {
                            intersectsNear = false;
                        }
                    }
                }

                if (m_lastMin == min && m_lastMax == max && !m_clipmap.m_updateClipping)
                {
                    return;
                }

                m_lastMin = min;
                m_lastMax = max;

                LodLevel parentLod, childLod;

                GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.
                MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                m_storedCellData.Clear();

                if (intersects)
                {
                    float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex);

                    MyCellCoord cell = new MyCellCoord(m_lodIndex, ref min);
                    for (var it = new Vector3I.RangeIterator(ref min, ref max);
                         it.IsValid(); it.GetNext(out cell.CoordInLod))
                    {
                        if (intersectsNear &&
                            m_localNearCameraBox.Contains(cell.CoordInLod) == ContainmentType.Contains)
                        {
                            continue;
                        }

                        //if (!WasAncestorCellLoaded(parentLod, ref cell))
                        //    continue;


                        Vector3D minAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod - 2)), m_clipmap.m_worldMatrix);
                        Vector3D maxAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod + 2) + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                        if (frustum.Contains(new BoundingBoxD(minAABB, maxAABB)) == ContainmentType.Disjoint)
                        {
                            continue;
                        }

                        var      cellId = cell.PackId64();
                        CellData data;
                        if (m_clippedCells.TryGetValue(cellId, out data))
                        {
                            m_clippedCells.Remove(cellId);
                        }
                        else
                        {
                            var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);
                            data = CellsCache.Read(clipmapCellId);

                            if (data == null) //cache miss
                            {
                                data = new CellData();
                                ClippingCacheMisses++;
                            }
                            else
                            {
                                //cache hit
                                ClippingCacheHits++;

                                //System.Diagnostics.Debug.Assert((!data.InScene && data.Cell != null) || data.Cell == null, "Not allowed cell state");
                                data.InScene = false;
                                if (data.Cell != null)
                                {
                                    m_nonEmptyCells[cellId] = data;
                                }
                            }
                        }

                        if (data.State == CellState.Invalid)
                        {
                            if (!TryAddCellRequest(collector, parentLod, cell, cellId, data))
                            {
                                continue;
                            }
                        }
                        m_storedCellData.Add(cellId, data);
                    }
                }
            }
Esempio n. 15
0
        // To help debug even when using stackalloc
        public unsafe bool IntersectInternalWStack(ref LineD line, MyCellCoord * stack, int stackSize) {
#else

            int stackSize = MySparseOctree.EstimateStackSize(m_treeHeight);
            MyCellCoord* stack = stackalloc MyCellCoord[stackSize];
#endif
            var finalB = BoundingBoxD.CreateInvalid();

            LineD result;
            result.From = line.To;
            result.To = line.From;

            MyCellCoord data = new MyCellCoord(m_treeHeight + LeafLodCount, ref Vector3I.Zero);
            int stackIdx = 0;
            stack[stackIdx++] = data;
            MyCellCoord cell = new MyCellCoord();

            BoundingBoxI bb = new BoundingBoxI(new Vector3I(Vector3.Min(line.From, line.To)), new Vector3I(Vector3.Ceiling(Vector3.Max(line.From, line.To))));

            double startOfft, endOfft;

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

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

                int lodDiff;
                IMyOctreeLeafNode leaf;
                if (m_contentLeaves.TryGetValue(cell.PackId64(), out leaf))
                {
                    lodDiff = data.Lod;
                    var rangeMinInDataLod = bb.Min >> lodDiff;
                    var rangeMaxInDataLod = bb.Max >> lodDiff;
                    if (data.CoordInLod.IsInsideInclusive(ref rangeMinInDataLod, ref rangeMaxInDataLod))
                    {
                        var start = rangeMinInDataLod << data.Lod;
                        var end = (rangeMaxInDataLod) << data.Lod;

                        var leafBounds = new BoundingBoxD(start, end);
                        
                        LineD ll;
                        leafBounds.Intersect(ref line, out ll);



                        if (leaf.Intersect(ref ll, out startOfft, out endOfft))
                        {
                            if (finalB.Contains(ll.From) == ContainmentType.Disjoint)
                            {
                                result.From = ll.From;
                                finalB.Include(ll.From);
                            }
                            if (finalB.Contains(ll.To) == ContainmentType.Disjoint)
                            {
                                result.To = ll.To;
                                finalB.Include(ll.To);
                            }
                        }
                    }
                    continue;
                }

                cell.Lod -= 1;
                lodDiff = data.Lod - 1;
                var node = m_contentNodes[cell.PackId64()];

                var min = bb.Min >> lodDiff;
                var max = bb.Max >> lodDiff;
                var nodePositionInChild = data.CoordInLod << 1;
                min -= nodePositionInChild;
                max -= nodePositionInChild;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    Vector3I childPosRelative;
                    ComputeChildCoord(i, out childPosRelative);
                    if (!childPosRelative.IsInsideInclusive(ref min, ref max))
                        continue;

                    BoundingBoxD nodeBounds;
                    nodeBounds.Min = childPosRelative + cell.CoordInLod << lodDiff;
                    nodeBounds.Max = nodeBounds.Min + (1 << data.Lod);

                    if (finalB.Contains(nodeBounds) == ContainmentType.Contains) continue;

                    if (!nodeBounds.Intersects(ref line))
                        continue;

                    if (node.HasChild(i))
                    {
                        Debug.Assert(stackIdx < stackSize);
                        stack[stackIdx++] = new MyCellCoord(data.Lod - 1, nodePositionInChild + childPosRelative);
                    }
                }
            }

            if (!finalB.Valid) return false;

            line.To = result.To;
            line.From = result.From;
            line.Length = (result.To - result.From).Length();
            return true;
        }
Esempio n. 16
0
        private void MergeAsteroidVolumeInto(ref MyVoxelMap newAsteroid, Vector3D min, StructureVoxelModel modelPrimary, StructureVoxelModel modelSecondary, Vector3D minPrimary, Vector3D minSecondary)
        {
            var      filenameSecondary = modelSecondary.SourceVoxelFilepath ?? modelSecondary.VoxelFilepath;
            var      filenamePrimary   = modelPrimary.SourceVoxelFilepath ?? modelPrimary.VoxelFilepath;
            Vector3I block;
            Vector3I newBlock;
            Vector3I cacheSize;

            var asteroid = new MyVoxelMap();

            asteroid.Load(filenameSecondary);
            BoundingBoxI content = modelSecondary.InflatedContentBounds;

            for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64)
            {
                for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64)
                {
                    for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64)
                    {
                        var cache = new MyStorageData();
                        cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1,
                                                 MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1,
                                                 MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1);

                        cache.Resize(cacheSize);
                        asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1);

                        newBlock = ((minSecondary - min) + (Vector3D)(block - content.Min)).RoundToVector3I();
                        newAsteroid.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1);
                    }
                }
            }

            asteroid.Load(filenamePrimary);
            content = modelPrimary.InflatedContentBounds;
            for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64)
            {
                for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64)
                {
                    for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64)
                    {
                        var cache = new MyStorageData();
                        cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1,
                                                 MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1,
                                                 MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1);

                        cache.Resize(cacheSize);
                        asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1);

                        newBlock = ((minPrimary - min) + (Vector3D)(block - content.Min)).RoundToVector3I();
                        var newCache = new MyStorageData();
                        newCache.Resize(cacheSize);
                        newAsteroid.Storage.ReadRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, newBlock, newBlock + cacheSize - 1);

                        Vector3I p;
                        for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z)
                        {
                            for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y)
                            {
                                for (p.X = 0; p.X < cacheSize.X; ++p.X)
                                {
                                    byte volume   = cache.Content(ref p);
                                    byte material = cache.Material(ref p);
                                    if (volume > 0)
                                    {
                                        byte existingVolume = newCache.Content(ref p);
                                        if (volume > existingVolume)
                                        {
                                            newCache.Content(ref p, volume);
                                        }
                                        // Overwrites secondary material with primary.
                                        newCache.Material(ref p, material);
                                    }
                                    else
                                    {
                                        // try to find cover material.
                                        Vector3I[] points = CreateTestPoints(p, cacheSize - 1);
                                        for (int i = 0; i < points.Length; i++)
                                        {
                                            byte testVolume = cache.Content(ref points[i]);
                                            if (testVolume > 0)
                                            {
                                                material = cache.Material(ref points[i]);
                                                newCache.Material(ref p, material);
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        newAsteroid.Storage.WriteRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1);
                    }
                }
            }
        }
Esempio n. 17
0
        internal void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged, int lod)
        {
            MyPrecalcComponent.AssertUpdateThread();

            // No physics there ever was so we don't care.
            if (!m_bodiesInitialized)
            {
                return;
            }

            if (m_queueInvalidation)
            {
                if (m_queuedRange.Max.X < 0)
                {
                    m_queuedRange = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
                }
                else
                {
                    var bb = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
                    m_queuedRange.Include(ref bb);
                }
                return;
            }

            ProfilerShort.Begin("MyVoxelPhysicsBody.InvalidateRange");
            minVoxelChanged -= 1; // MyPrecalcComponent.InvalidatedRangeInflate;
            maxVoxelChanged += 1; //MyPrecalcComponent.InvalidatedRangeInflate;
            m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged);
            m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged);

            Vector3I minCellChanged, maxCellChanged;

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCellChanged);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCellChanged);

            Vector3I minCellChangedVoxelMap, maxCellChangedVoxelMap;

            minCellChangedVoxelMap = (minCellChanged - m_cellsOffset) >> lod;
            maxCellChangedVoxelMap = (maxCellChanged - m_cellsOffset) >> lod;

            var maxCell = m_voxelMap.Size - 1;

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxCell, out maxCell);
            maxCell >>= lod;
            Vector3I.Min(ref maxCellChangedVoxelMap, ref maxCell, out maxCellChangedVoxelMap);

            Debug.Assert(RigidBody != null, "RigidBody in voxel physics is null! This must not happen.");

            var rb = GetRigidBody(lod);

            Debug.Assert(rb != null, "RigidBody in voxel physics is null! This must not happen.");

            if (rb != null)
            {
                HkUniformGridShape shape = (HkUniformGridShape)rb.GetShape();
                Debug.Assert(shape.Base.IsValid);


                var numCells = (maxCellChangedVoxelMap - minCellChangedVoxelMap + 1).Size;
                if (numCells >= m_cellsToGenerateBuffer.Length)
                {
                    m_cellsToGenerateBuffer = new Vector3I[MathHelper.GetNearestBiggerPowerOfTwo(numCells)];
                }

                var tmpBuffer    = m_cellsToGenerateBuffer;
                int invalidCount = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer);
                Debug.Assert(invalidCount <= tmpBuffer.Length);

                //if (numCells <= 8)
                //shape.InvalidateRangeImmediate(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap);

                Debug.Assert(invalidCount <= tmpBuffer.Length);
                for (int i = 0; i < invalidCount; i++)
                {
                    InvalidCells[lod].Add(tmpBuffer[i]);
                }

                if (RunningBatchTask[lod] == null && InvalidCells[lod].Count != 0)
                {
                    MyPrecalcComponent.PhysicsWithInvalidCells.Add(this);
                }
            }

            if (minCellChangedVoxelMap == Vector3I.Zero && maxCellChangedVoxelMap == maxCell)
            {
                m_workTracker.CancelAll();
            }
            else
            {
                var cell = minCellChanged;
                for (var it = new Vector3I_RangeIterator(ref minCellChanged, ref maxCellChanged);
                     it.IsValid(); it.GetNext(out cell))
                {
                    m_workTracker.Cancel(new MyCellCoord(lod, cell));
                }
            }

            m_needsShapeUpdate = true;

            ProfilerShort.End();

            m_voxelMap.RaisePhysicsChanged();
        }
 public ContainmentType Intersect(BoundingBoxI box, bool lazy)
 {
     if (Closed)
     {
         Debug.Fail("Storage closed!");
         return ContainmentType.Disjoint;
     }
     BoundingBox bbox = new BoundingBox(box);
     bbox.Translate(-Shape.Center()); // Bring to center local
     return Shape.IntersectBoundingBox(ref bbox, 1.0f);
 }
Esempio n. 19
0
        internal unsafe ContainmentType Intersect(ref BoundingBoxI box, bool lazy)
        {
            int          stackIdx  = 0;
            int          stackSize = MySparseOctree.EstimateStackSize(m_treeHeight);
            MyCellCoord *stack     = stackalloc MyCellCoord[stackSize];
            MyCellCoord  data      = new MyCellCoord(m_treeHeight - 1, ref Vector3I.Zero);

            stack[stackIdx++] = data;

            Vector3I minInLod = box.Min;
            Vector3I maxInLod = box.Max;

            MyOctreeNode node;
            Vector3I     childPosRelative, min, max, nodePositionInChild;
            int          lodDiff;

            // TODO(DI): Add support for checking for containment somehow, this needs neighbourhood information which kinda sucks.

            ContainmentType cont = ContainmentType.Disjoint;

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

                lodDiff             = data.Lod;
                min                 = minInLod >> lodDiff;
                max                 = maxInLod >> lodDiff;
                nodePositionInChild = data.CoordInLod << 1;
                min                -= nodePositionInChild;
                max                -= nodePositionInChild;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childPosRelative);
                    if (!childPosRelative.IsInsideInclusive(ref min, ref max))
                    {
                        continue;
                    }
                    if (data.Lod > 0 && node.HasChild(i))
                    {
                        Debug.Assert(stackIdx < stackSize);
                        stack[stackIdx++] = new MyCellCoord(data.Lod - 1, nodePositionInChild + childPosRelative);
                    }
                    else
                    {
                        var nodeData = node.Data[i];
                        if (lodDiff == 0)
                        {
                            if (nodeData != 0)
                            {
                                return(ContainmentType.Intersects);
                            }
                        }
                        else
                        {
                            BoundingBoxI nodeBox;
                            nodeBox.Min   = nodePositionInChild + childPosRelative;
                            nodeBox.Min <<= lodDiff;
                            nodeBox.Max   = nodeBox.Min + (1 << lodDiff) - 1;
                            Vector3I.Max(ref nodeBox.Min, ref minInLod, out nodeBox.Min);
                            Vector3I.Min(ref nodeBox.Max, ref maxInLod, out nodeBox.Max);

                            bool res;
                            nodeBox.Intersects(ref nodeBox, out res);

                            if (res)
                            {
                                return(ContainmentType.Intersects);
                            }
                        }
                    }
                }
            }

            return(cont);
        }
        internal void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged, int lod)
        {
            MyPrecalcComponent.AssertUpdateThread();
            // No physics there ever was so we don't care.
            if (!m_bodiesInitialized)
            {
                return;
            }

            if (m_queueInvalidation)
            {
                if (m_queuedRange.Max.X < 0)
                {
                    m_queuedRange = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
                }
                else
                {
                    var bb = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
                    m_queuedRange.Include(ref bb);
                }
                return;
            }

            ProfilerShort.Begin("MyVoxelPhysicsBody.InvalidateRange");
            minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate;
            maxVoxelChanged += MyPrecalcComponent.InvalidatedRangeInflate;
            m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged);
            m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged);

            Vector3I minCellChanged, maxCellChanged;

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCellChanged);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCellChanged);

            Vector3I minCellChangedVoxelMap, maxCellChangedVoxelMap;

            minCellChangedVoxelMap = (minCellChanged - m_cellsOffset) >> lod;
            maxCellChangedVoxelMap = (maxCellChanged - m_cellsOffset) >> lod;

            var maxCell = m_voxelMap.Size - 1;

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxCell, out maxCell);
            maxCell >>= lod;
            Vector3I.Min(ref maxCellChangedVoxelMap, ref maxCell, out maxCellChangedVoxelMap);

            Debug.Assert(RigidBody != null, "RigidBody in voxel physics is null! This must not happen.");

            var rb = GetRigidBody(lod);

            Debug.Assert(rb != null, "RigidBody in voxel physics is null! This must not happen.");

            if (rb != null)
            {
                HkUniformGridShape shape = (HkUniformGridShape)rb.GetShape();
                Debug.Assert(shape.Base.IsValid);

                var tmpBuffer    = m_cellsToGenerateBuffer;
                int invalidCount = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer);
                if (invalidCount > tmpBuffer.Length)
                {
                    // Not storing this new buffer in static variable since this is just temporary and potentially large.
                    // Static variable could be potentially the same as leak.
                    tmpBuffer = new Vector3I[invalidCount];
                    int invalidCount2 = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer);
                    Debug.Assert(invalidCount == invalidCount2);
                    invalidCount = invalidCount2;
                }

                shape.InvalidateRangeImmediate(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap);
                Debug.Assert(invalidCount <= tmpBuffer.Length);
                for (int i = 0; i < invalidCount; i++)
                {
                    InvalidCells.Add(tmpBuffer[i]);
                }
                if (RunningBatchTask == null && InvalidCells.Count != 0)
                {
                    MyPrecalcComponent.PhysicsWithInvalidCells.Add(this);
                }
            }

            if (minCellChangedVoxelMap == Vector3I.Zero && maxCellChangedVoxelMap == maxCell)
            {
                m_workTracker.CancelAll();
            }
            else
            {
                var cell = minCellChanged;
                for (var it = new Vector3I.RangeIterator(ref minCellChanged, ref maxCellChanged);
                     it.IsValid(); it.GetNext(out cell))
                {
                    m_workTracker.Cancel(new MyCellCoord(lod, cell));
                }
            }

            m_needsShapeUpdate = true;

            ProfilerShort.End();

            m_voxelMap.RaisePhysicsChanged();
        }
        private void ComputeSectorParameters()
        {
            // face size is the length of an edge of a cube with half diagonal r.
            // this is equal to sqrt(2) * r
            m_sectorFaceSize = MaximumRadius * 1.41421356237309504880;

            // Ensure at least one sector.
            if (m_sectorFaceSize < MIN_SECTOR_SIZE)
            {
                m_numSectors = 1;
                m_sectorSize = m_sectorFaceSize;
            }
            else
            {
                m_numSectors = (int)Math.Floor(m_sectorFaceSize / MIN_SECTOR_SIZE);
                m_sectorSize = m_sectorFaceSize / m_numSectors;
            }

            m_sectorBox = new BoundingBoxI(0, m_numSectors - 1);

            m_sectorDensity = Generator.SectorDensity;

            m_itemsPerSector = m_sectorDensity * m_sectorSize * m_sectorSize;
        }
Esempio n. 22
0
        internal unsafe ContainmentType Intersect(ref BoundingBoxI box, int lod, bool exhaustiveContainmentCheck = true)
        {
            MyCellCoord *coordPtr = (MyCellCoord *)stackalloc byte[(((IntPtr)EstimateStackSize(this.m_treeHeight)) * sizeof(MyCellCoord))];
            MyCellCoord  coord    = new MyCellCoord(this.m_treeHeight - 1, ref Vector3I.Zero);
            int          index    = 0 + 1;

            coordPtr[index] = coord;
            Vector3I        min      = box.Min;
            Vector3I        max      = box.Max;
            ContainmentType disjoint = ContainmentType.Disjoint;

            while (index > 0)
            {
                coord = coordPtr[--index];
                MyOctreeNode node     = this.m_nodes[coord.PackId32()];
                int          num3     = coord.Lod;
                Vector3I     vectori6 = coord.CoordInLod << 1;
                Vector3I     vectori4 = (min >> num3) - vectori6;
                Vector3I     vectori5 = (max >> num3) - vectori6;
                for (int i = 0; i < 8; i++)
                {
                    Vector3I vectori3;
                    this.ComputeChildCoord(i, out vectori3);
                    if (vectori3.IsInsideInclusiveEnd(ref vectori4, ref vectori5))
                    {
                        if ((coord.Lod > 0) && node.HasChild(i))
                        {
                            index++;
                            coordPtr[index] = new MyCellCoord(coord.Lod - 1, (Vector3I)(vectori6 + vectori3));
                        }
                        else
                        {
                            byte num5 = &node.Data.FixedElementField[i];
                            if (num3 == 0)
                            {
                                if (num5 != 0)
                                {
                                    return(ContainmentType.Intersects);
                                }
                            }
                            else
                            {
                                BoundingBoxI xi;
                                bool         flag;
                                xi.Min = (Vector3I)(vectori6 + vectori3);
                                Vector3I *vectoriPtr1 = (Vector3I *)ref xi.Min;
                                vectoriPtr1[0] = vectoriPtr1[0] << num3;
                                BoundingBoxI *xiPtr1 = (BoundingBoxI *)ref xi;
                                xiPtr1->Max = (Vector3I)((xi.Min + (1 << (num3 & 0x1f))) - 1);
                                Vector3I.Max(ref xi.Min, ref min, out xi.Min);
                                Vector3I.Min(ref xi.Max, ref max, out xi.Max);
                                ((BoundingBoxI *)ref xi).Intersects(ref xi, out flag);
                                if (flag)
                                {
                                    return(ContainmentType.Intersects);
                                }
                            }
                        }
                    }
                }
            }
            return(disjoint);
        }
Esempio n. 23
0
 internal void UpdateAfterSimulation10()
 {
     this.UpdateRigidBodyShape();
     if (this.m_voxelMap.Storage != null)
     {
         foreach (IMyEntity entity in this.m_nearbyEntities)
         {
             if (entity != null)
             {
                 bool          flag    = false;
                 MyPhysicsBody physics = entity.Physics as MyPhysicsBody;
                 if (((physics != null) && (physics.RigidBody != null)) && ((physics.RigidBody.Layer == 0x17) || (physics.RigidBody.Layer == 10)))
                 {
                     flag = true;
                 }
                 if ((((entity is MyCubeGrid) || flag) && !entity.MarkedForClose) && (entity.Physics != null))
                 {
                     BoundingBoxD xd;
                     this.GetPrediction(entity, out xd);
                     if (xd.Intersects(this.m_voxelMap.PositionComp.WorldAABB))
                     {
                         Vector3I           vectori;
                         Vector3I           vectori2;
                         HkUniformGridShape shape;
                         int num1;
                         if (flag || !UseLod1VoxelPhysics)
                         {
                             num1 = 0;
                         }
                         else
                         {
                             num1 = 1;
                         }
                         int          lod  = num1;
                         int          num2 = 1 << (lod & 0x1f);
                         BoundingBoxD xd2  = xd.TransformFast(this.m_voxelMap.PositionComp.WorldMatrixInvScaled);
                         xd2.Translate(this.m_voxelMap.SizeInMetresHalf);
                         Vector3 max = (Vector3)xd2.Max;
                         Vector3 min = (Vector3)xd2.Min;
                         this.ClampVoxelCoords(ref min, ref max, out vectori, out vectori2);
                         vectori  = vectori >> lod;
                         vectori2 = vectori2 >> lod;
                         int size = ((vectori2 - vectori) + 1).Size;
                         if (size >= m_cellsToGenerateBuffer.Length)
                         {
                             m_cellsToGenerateBuffer = new Vector3I[MathHelper.GetNearestBiggerPowerOfTwo(size)];
                         }
                         if (this.GetShape(lod, out shape))
                         {
                             if (shape.Base.IsZero)
                             {
                                 MyAnalyticsHelper.ReportBug("Null voxel shape", "SE-7366", true, @"E:\Repo1\Sources\Sandbox.Game\Engine\Voxels\MyVoxelPhysicsBody.cs", 680);
                             }
                             else
                             {
                                 int requiredCellsCount = shape.GetMissingCellsInRange(ref vectori, ref vectori2, m_cellsToGenerateBuffer);
                                 if (requiredCellsCount != 0)
                                 {
                                     BoundingBoxI box = new BoundingBoxI((vectori * 8) * num2, (Vector3I)(((vectori2 + 1) * 8) * num2));
                                     box.Translate(this.m_voxelMap.StorageMin);
                                     if ((requiredCellsCount > 0) && (this.m_voxelMap.Storage.Intersect(ref box, lod, true) != ContainmentType.Intersects))
                                     {
                                         this.SetEmptyShapes(lod, ref shape, requiredCellsCount);
                                     }
                                     else
                                     {
                                         for (int i = 0; i < requiredCellsCount; i++)
                                         {
                                             this.StartPrecalcJobPhysicsIfNeeded(lod, i);
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
         this.ScheduleBatchJobs();
         if (this.m_bodiesInitialized)
         {
             this.CheckAndDiscardShapes();
         }
     }
 }
Esempio n. 24
0
 public ContainmentType Intersect(ref BoundingBoxI box, bool lazy = false)
 {
     return m_provider.Intersect(box, lazy);
 }
Esempio n. 25
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());
            }
        }
Esempio n. 26
0
            internal void DoClipping(float camDistanceFromCenter, Vector3D localPosition, float farPlaneDistance, RequestCollector collector, bool frustumCulling, float rangeScale)
            {
                int lodIndex = m_lodIndex;

                if (!ShouldBeThisLodVisible(camDistanceFromCenter))
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                    return;
                }


                m_localPosition = localPosition;
                MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, lodIndex, out m_nearDistance, out m_farDistance);


                farPlaneDistance *= rangeScale;
                m_farDistance *= rangeScale;
                m_nearDistance *= rangeScale;

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum && m_lodIndex == lodIndex)
                    return;


                //var localFrustum = new BoundingFrustumD(CameraFrustumGetter().Matrix * m_parent.m_invWorldMatrix);
                var frustum = CameraFrustumGetter();

                Vector3I min, max;
                // Vector3I ignoreMin, ignoreMax;

                var minD = m_localPosition - (double)m_farDistance;
                var maxD = m_localPosition + (double)m_farDistance;
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref minD, out min);
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref maxD, out max);

                BoundingBoxI lodBox = new BoundingBoxI(Vector3I.Zero, Vector3I.Max(m_lodSizeMinusOne, Vector3I.Zero));
                bool intersects = false;
                //bool intersectsNear = false;

                m_localFarCameraBox = new BoundingBoxI(min, max);
                m_localNearCameraBox = new BoundingBoxI(min, max);
                if (lodBox.Intersects(m_localFarCameraBox))
                {
                    intersects = true;
                    var intersection = lodBox;
                    intersection.IntersectWith(ref m_localFarCameraBox);
                    min = intersection.Min;
                    max = intersection.Max;

                    //Optimize only LOD2 and higher by two lods, because neighbour cells shares border cells
                    //if (m_lodIndex > 1)
                    //{
                    //    float lowerFar, lowerNear;
                    //    MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex - 2, out lowerFar, out lowerNear);

                    //    var minNear = m_localPosition - (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                    //    var maxNear = m_localPosition + (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                    //    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minNear, out ignoreMin);
                    //    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxNear, out ignoreMax);

                    //    m_localNearCameraBox = new BoundingBoxI(ignoreMin, ignoreMax);
                    //    if (lodBox.Intersects(m_localNearCameraBox))
                    //        intersectsNear = false;
                    //}
                }
            
                //if (m_lastMin == min && m_lastMax == max && !m_clipmap.m_updateClipping)
                //    return;

                //m_lastMin = min;
                //m_lastMax = max;

                //LodLevel parentLod, childLod;
                //GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.

                if (frustumCulling)
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                }

                if (intersects)
                {
                    float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(lodIndex);


                    MyCellCoord cell = new MyCellCoord(lodIndex, ref min);

                    for (var it = new Vector3I_RangeIterator(ref min, ref max);
                        it.IsValid(); it.GetNext(out cell.CoordInLod))
                    {
                        //if (intersectsNear &&
                        //    m_localNearCameraBox.Contains(cell.CoordInLod) == ContainmentType.Contains)
                        //    continue;

                        //if (frustumCulling)
                        //{
                        //    Vector3D minAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod - 2)), m_clipmap.m_worldMatrix);
                        //    Vector3D maxAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod + 2) + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                        //    if (frustum.Contains(new BoundingBoxD(minAABB, maxAABB)) == ContainmentType.Disjoint)
                        //    {
                        //        m_outsideCells.Add(cell.CoordInLod);
                        //        continue;
                        //    }
                        //}

                        UnclipCell(collector, cell, true);
                    }

                    //cache cells around frustum
                    if (collector.SentRequestsEmpty)
                    {
                          foreach (var outsideCell in m_outsideCells)
                          {
                              cell.CoordInLod = outsideCell;
                              UnclipCell(collector, cell, frustumCulling);
                          }
                    }

                    m_outsideCells.Clear();
                }
            }
Esempio n. 27
0
 private bool ApplyDelegate(MyObjectBuilder_CubeGrid grid, MyObjectBuilder_CubeBlock source, string srcName, MyObjectBuilder_CubeBlock dest, Base6Directions.Direction destDir)
 {
     if (srcName.StartsWithICase(MountDelegated))
     {
         var     lTransOrig = new MatrixI(source.BlockOrientation);
         var     lTrans     = new MatrixI(dest.BlockOrientation);
         MatrixI iTrans;
         MatrixI.Invert(ref lTrans, out iTrans);
         var arguments = PartDummyUtils.ConfigArguments(srcName.Substring(MountDelegated.Length).Trim()).Select(
             (arg) =>
         {
             if (arg.StartsWithICase(PartDummyUtils.ArgumentBiasDirection))
             {
                 Base6Directions.Direction dir;
                 if (Enum.TryParse(arg.Substring(PartDummyUtils.ArgumentBiasDirection.Length), out dir))
                 {
                     return(PartDummyUtils.ArgumentBiasDirection +
                            iTrans.GetDirection(lTransOrig.GetDirection(dir)));
                 }
                 else
                 {
                     this.Error("Failed to parse bias argument \"{0}\"", arg);
                 }
             }
             else if (arg.StartsWithICase(PartDummyUtils.ArgumentSecondBiasDirection))
             {
                 Base6Directions.Direction dir;
                 if (Enum.TryParse(arg.Substring(PartDummyUtils.ArgumentSecondBiasDirection.Length), out dir))
                 {
                     return(PartDummyUtils.ArgumentSecondBiasDirection +
                            iTrans.GetDirection(lTransOrig.GetDirection(dir)));
                 }
                 else
                 {
                     this.Error("Failed to parse second bias argument \"{0}\"", arg);
                 }
             }
             return(arg);
         }).ToList();
         arguments.Add(PartDummyUtils.ArgumentMountDirection + iTrans.GetDirection(Base6Directions.GetOppositeDirection(destDir)));
         var anchorPoint = source.Min + Base6Directions.GetIntVector(destDir);
         var del         = anchorPoint - dest.Min;
         if (del != Vector3I.Zero)
         {
             arguments.Add(PartDummyUtils.ArgumentAnchorPoint + del.X + ":" + del.Y + ":" + del.Z);
         }
         var outName = PartMetadata.MountPrefix + " " + string.Join(" ", arguments);
         if (string.IsNullOrWhiteSpace(dest.Name))
         {
             dest.Name = outName;
         }
         else
         {
             dest.Name = dest.Name + PartMetadata.MultiUseSentinel + outName;
         }
         return(true);
     }
     if (srcName.StartsWithICase(ReservedSpaceDelegated))
     {
         var baseName = srcName.Substring(ReservedSpaceDelegated.Length).Trim();
         var args     = baseName.Split(' ').Select(x => x.Trim()).Where(x => x.Length > 0).ToArray();
         var box      = PartDummyUtils.ParseReservedSpace(MyDefinitionManager.Static.GetCubeSize(grid.GridSizeEnum), source, args, this.Error);
         var del      = source.Min - (Vector3I)dest.Min;
         box.Box.Max += del;
         box.Box.Min += del;
         var boxLocalFloat = Utilities.TransformBoundingBox(box.Box, Matrix.Invert(new MatrixI(dest.BlockOrientation).GetFloatMatrix()));
         var boxLocal      = new BoundingBoxI(Vector3I.Floor(boxLocalFloat.Min), Vector3I.Ceiling(boxLocalFloat.Max));
         var outName       = $"{PartMetadata.ReservedSpacePrefix} NE:{boxLocal.Min.X}:{boxLocal.Min.Y}:{boxLocal.Min.Z} PE:{boxLocal.Max.X}:{boxLocal.Max.Y}:{boxLocal.Max.Z}";
         if (box.IsShared)
         {
             outName += " shared";
         }
         if (box.IsOptional)
         {
             outName += " optional";
         }
         if (string.IsNullOrWhiteSpace(dest.Name))
         {
             dest.Name = outName;
         }
         else
         {
             dest.Name = dest.Name + PartMetadata.MultiUseSentinel + outName;
         }
         return(true);
     }
     return(false);
 }
 public static BoundingBoxD ToBoundingBoxD(this BoundingBoxI box)
 {
     return(new BoundingBoxD(box.Min, box.Max));
 }
        public ContainmentType Intersect(BoundingBoxI box, bool lazy)
        {
            ContainmentType ct = ContainmentType.Disjoint;

            BoundingBox bb = new BoundingBox(box);
            BoundingSphere sp = new BoundingSphere(bb.Center, bb.Extents.Length() / 2f);

            // Check filled shapes.
            foreach (var shape in m_data.FilledShapes)
            {
                var c = shape.Contains(ref bb, ref sp, 1f);

                if (c == ContainmentType.Contains) ct = c;
                else if (c == ContainmentType.Intersects && ct == ContainmentType.Disjoint) ct = c;
            }

            // Check shapes removed, we don't check how they are removed so we only discard if the removed shape covers the whole bb.
            if (ct != ContainmentType.Disjoint)
            {
                foreach (var shape in m_data.RemovedShapes)
                {
                    var c = shape.Contains(ref bb, ref sp, 1f);

                    if (c == ContainmentType.Contains)
                    {
                        ct = ContainmentType.Disjoint;
                        break;
                    }

                    else if (c == ContainmentType.Intersects)
                    {
                        ct = ContainmentType.Intersects;
                    }
                }
            }

            return ct;
        }
Esempio n. 30
0
            internal void DoClipping_Old(Vector3D localPosition, float farPlaneDistance, RequestCollector collector)
            {
                m_localPosition = localPosition;
                MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex, out m_nearDistance, out m_farDistance);

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum)
                    return;


                //var localFrustum = new BoundingFrustumD(CameraFrustumGetter().Matrix * m_parent.m_invWorldMatrix);
                var frustum = CameraFrustumGetter();

                Vector3I min, max;
                Vector3I ignoreMin, ignoreMax;

                var minD = m_localPosition - m_farDistance;
                var maxD = m_localPosition + m_farDistance;
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minD, out min);
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxD, out max);

                BoundingBoxI lodBox = new BoundingBoxI(Vector3I.Zero, m_lodSizeMinusOne);
                bool intersects = false;
                bool intersectsNear = false;

                m_localFarCameraBox = new BoundingBoxI(min, max);
                m_localNearCameraBox = new BoundingBoxI(min, max);
                if (lodBox.Intersects(m_localFarCameraBox))
                {
                    intersects = true;
                    var intersection = lodBox.Intersect(m_localFarCameraBox);
                    min = intersection.Min;
                    max = intersection.Max;

                    //Optimize only LOD2 and higher by two lods, because neighbour cells shares border cells
                    if (m_lodIndex > 1)
                    {
                        float lowerFar, lowerNear;
                        MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex - 2, out lowerFar, out lowerNear);

                        var minNear = m_localPosition - (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                        var maxNear = m_localPosition + (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                        MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minNear, out ignoreMin);
                        MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxNear, out ignoreMax);

                        m_localNearCameraBox = new BoundingBoxI(ignoreMin, ignoreMax);
                        if (lodBox.Intersects(m_localNearCameraBox))
                            intersectsNear = false;
                    }
                }
            
                if (m_lastMin == min && m_lastMax == max && !m_clipmap.m_updateClipping)
                    return;

                m_lastMin = min;
                m_lastMax = max;

                LodLevel parentLod, childLod;
                GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.
                MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                m_storedCellData.Clear();

                if (intersects)
                {
                    float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex);

                    MyCellCoord cell = new MyCellCoord(m_lodIndex, ref min);
                    for (var it = new Vector3I.RangeIterator(ref min, ref max);
                        it.IsValid(); it.GetNext(out cell.CoordInLod))
                    {
                        if (intersectsNear &&
                            m_localNearCameraBox.Contains(cell.CoordInLod) == ContainmentType.Contains)
                            continue;

                        //if (!WasAncestorCellLoaded(parentLod, ref cell))
                        //    continue;

                        
                        Vector3D minAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod - 2)), m_clipmap.m_worldMatrix);
                        Vector3D maxAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod + 2) + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                         if (frustum.Contains(new BoundingBoxD(minAABB, maxAABB)) == ContainmentType.Disjoint)
                            continue;

                        var cellId = cell.PackId64();
                        CellData data;
                        if (m_clippedCells.TryGetValue(cellId, out data))
                        {
                            m_clippedCells.Remove(cellId);
                        }
                        else
                        {
                            var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);
                            data = CellsCache.Read(clipmapCellId);

                            if (data == null) //cache miss
                            {
                                data = new CellData();
                                ClippingCacheMisses++;
                            }
                            else
                            {
                                //cache hit
                                ClippingCacheHits++;

                                //System.Diagnostics.Debug.Assert((!data.InScene && data.Cell != null) || data.Cell == null, "Not allowed cell state");
                                data.InScene = false;
                                if (data.Cell != null)
                                {
                                    m_nonEmptyCells[cellId] = data;
                                }
                            }
                        }

                        if (data.State == CellState.Invalid)
                        {
                            if (!TryAddCellRequest(collector, parentLod, cell, cellId, data))
                                continue;
                        }
                        m_storedCellData.Add(cellId, data);
                    }
                }
            }
Esempio n. 31
0
        // Iterate over sector boxes in a range.
        private void ForEachSector(Vector3 localPosition, float range, SectorIteration iterator)
        {
            Vector3 sectorPosition;

            LocalPositionToSectorCube(localPosition, out sectorPosition);

            Vector3D referencePoint = localPosition;

            SectorScans.Hit();

            Vector3 rangev = new Vector3(range);

            BoundingBox  probe = new BoundingBox(sectorPosition - rangev, sectorPosition + rangev);
            BoundingBoxI inter = m_sectorBox.Intersect(probe);

            Vector3S min = new Vector3S(inter.Min);
            Vector3S max = new Vector3S(inter.Max);


            // Iterate over each face of the cube that is in the intersection.

            MyPlanetSectorId id = new MyPlanetSectorId();

            // Front
            if (inter.Min.Z == m_sectorBox.Min.Z)
            {
                id.Direction  = Vector3B.Backward;
                id.Position.Z = min.Z;
                for (id.Position.X = min.X; id.Position.X <= max.X; id.Position.X++)
                {
                    for (id.Position.Y = min.Y; id.Position.Y <= max.Y; id.Position.Y++)
                    {
                        iterator(this, ref id, ref referencePoint);
                    }
                }
            }

            // Back
            if (inter.Max.Z == m_sectorBox.Max.Z)
            {
                id.Direction  = Vector3B.Forward;
                id.Position.Z = max.Z;
                for (id.Position.X = min.X; id.Position.X <= max.X; id.Position.X++)
                {
                    for (id.Position.Y = min.Y; id.Position.Y <= max.Y; id.Position.Y++)
                    {
                        iterator(this, ref id, ref referencePoint);
                    }
                }
            }

            // Right
            if (inter.Min.X == m_sectorBox.Min.X)
            {
                id.Direction  = Vector3B.Right;
                id.Position.X = min.X;
                for (id.Position.Y = min.Y; id.Position.Y <= max.Y; id.Position.Y++)
                {
                    for (id.Position.Z = min.Z; id.Position.Z <= max.Z; id.Position.Z++)
                    {
                        iterator(this, ref id, ref referencePoint);
                    }
                }
            }

            // Left
            if (inter.Max.X == m_sectorBox.Max.X)
            {
                id.Direction  = Vector3B.Left;
                id.Position.X = max.X;
                for (id.Position.Y = min.Y; id.Position.Y <= max.Y; id.Position.Y++)
                {
                    for (id.Position.Z = min.Z; id.Position.Z <= max.Z; id.Position.Z++)
                    {
                        iterator(this, ref id, ref referencePoint);
                    }
                }
            }

            // Up
            if (inter.Min.Y == m_sectorBox.Min.Y)
            {
                id.Direction  = Vector3B.Up;
                id.Position.Y = min.Y;
                for (id.Position.X = min.X; id.Position.X <= max.X; id.Position.X++)
                {
                    for (id.Position.Z = min.Z; id.Position.Z <= max.Z; id.Position.Z++)
                    {
                        iterator(this, ref id, ref referencePoint);
                    }
                }
            }

            // Down
            if (inter.Max.Y == m_sectorBox.Max.Y)
            {
                id.Direction  = Vector3B.Down;
                id.Position.Y = max.Y;
                for (id.Position.X = min.X; id.Position.X <= max.X; id.Position.X++)
                {
                    for (id.Position.Z = min.Z; id.Position.Z <= max.Z; id.Position.Z++)
                    {
                        iterator(this, ref id, ref referencePoint);
                    }
                }
            }
        }
Esempio n. 32
0
 internal unsafe void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged, int lod)
 {
     if (this.m_bodiesInitialized)
     {
         if (this.m_queueInvalidation)
         {
             if (this.m_queuedRange.Max.X < 0)
             {
                 this.m_queuedRange = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
             }
             else
             {
                 BoundingBoxI box = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
                 this.m_queuedRange.Include(ref box);
             }
         }
         else
         {
             Vector3I vectori;
             Vector3I vectori2;
             minVoxelChanged -= 2;
             maxVoxelChanged  = (Vector3I)(maxVoxelChanged + 1);
             this.m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged, 1);
             this.m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged, 1);
             MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out vectori);
             MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out vectori2);
             Vector3I  minChanged        = (vectori - this.m_cellsOffset) >> lod;
             Vector3I  result            = (vectori2 - this.m_cellsOffset) >> lod;
             Vector3I  geometryCellCoord = this.m_voxelMap.Size - 1;
             Vector3I *vectoriPtr1       = (Vector3I *)ref geometryCellCoord;
             MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref (Vector3I) ref vectoriPtr1, out geometryCellCoord);
             geometryCellCoord = geometryCellCoord >> lod;
             Vector3I *vectoriPtr2 = (Vector3I *)ref result;
             Vector3I.Min(ref (Vector3I) ref vectoriPtr2, ref geometryCellCoord, out result);
             HkRigidBody rigidBody = this.GetRigidBody(lod);
             if ((minChanged == Vector3I.Zero) && (result == geometryCellCoord))
             {
                 this.m_workTracker.CancelAll();
             }
             else
             {
                 using (MyUtils.ReuseCollection <MyCellCoord>(ref m_toBeCancelledCache))
                 {
                     BoundingBoxI xi2 = new BoundingBoxI(vectori, vectori2);
                     foreach (KeyValuePair <MyCellCoord, MyPrecalcJobPhysicsPrefetch> pair in this.m_workTracker)
                     {
                         if (xi2.Contains(pair.Key.CoordInLod) != ContainmentType.Disjoint)
                         {
                             m_toBeCancelledCache.Add(pair.Key);
                         }
                     }
                     foreach (MyCellCoord coord in m_toBeCancelledCache)
                     {
                         this.m_workTracker.CancelIfStarted(coord);
                     }
                 }
             }
             if (rigidBody != null)
             {
                 HkUniformGridShape shape = (HkUniformGridShape)rigidBody.GetShape();
                 int size = ((result - minChanged) + 1).Size;
                 if (size >= m_cellsToGenerateBuffer.Length)
                 {
                     m_cellsToGenerateBuffer = new Vector3I[MathHelper.GetNearestBiggerPowerOfTwo(size)];
                 }
                 int num2 = shape.InvalidateRange(ref minChanged, ref result, m_cellsToGenerateBuffer);
                 for (int i = 0; i < num2; i++)
                 {
                     this.StartPrecalcJobPhysicsIfNeeded(lod, i);
                 }
             }
             this.m_voxelMap.RaisePhysicsChanged();
         }
     }
 }
Esempio n. 33
0
 public bool GetBlockStates(Dictionary <Vector3I, BlockState> blockStates, long projectorId, int subgridIndex, BoundingBoxI box, int mask)
 {
     return((bool)(_miGetBlockStates?.Invoke(Api, new object[] { blockStates, projectorId, subgridIndex, box, mask }) ?? false));
 }
Esempio n. 34
0
        public override unsafe ContainmentType IntersectInternal(ref BoundingBox box, bool lazy)
        {
            int stackIdx = 0;
            int stackSize = MySparseOctree.EstimateStackSize(m_treeHeight);
            MyCellCoord* stack = stackalloc MyCellCoord[stackSize];
            MyCellCoord data = new MyCellCoord(m_treeHeight + LeafLodCount, ref Vector3I.Zero);
            stack[stackIdx++] = data;
            MyCellCoord cell = new MyCellCoord();

            BoundingBoxI bb = new BoundingBoxI(new Vector3I(box.Min), new Vector3I(Vector3.Ceiling(box.Max)));

            const ContainmentType invalid = (ContainmentType)(-1);

            ContainmentType inter = invalid;

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

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

                int lodDiff;
                IMyOctreeLeafNode leaf;
                if (m_contentLeaves.TryGetValue(cell.PackId64(), out leaf))
                {
                    lodDiff = data.Lod;
                    var rangeMinInDataLod = bb.Min >> lodDiff;
                    var rangeMaxInDataLod = bb.Max >> lodDiff;
                    if (data.CoordInLod.IsInsideInclusive(ref rangeMinInDataLod, ref rangeMaxInDataLod))
                    {
                        var leafMin = cell.CoordInLod << lodDiff;
                        BoundingBoxI localBox = new BoundingBoxI(leafMin, leafMin + (1 << lodDiff));

                        localBox.IntersectWith(ref bb);
                        var lint = leaf.Intersect(ref localBox);

                        if (inter == invalid) inter = lint;
                        if (lint == ContainmentType.Intersects) return ContainmentType.Intersects;
                        if (lint != inter || (inter == ContainmentType.Contains && lazy)) return ContainmentType.Intersects;
                    }
                    continue;
                }

                cell.Lod -= 1;
                lodDiff = data.Lod - 1;
                var node = m_contentNodes[cell.PackId64()];

                var min = bb.Min >> lodDiff;
                var max = bb.Max >> lodDiff;
                var nodePositionInChild = data.CoordInLod << 1;
                min -= nodePositionInChild;
                max -= nodePositionInChild;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    Vector3I childPosRelative;
                    ComputeChildCoord(i, out childPosRelative);
                    if (!childPosRelative.IsInsideInclusive(ref min, ref max))
                        continue;
                    if (data.Lod == 0)
                    {
                        //if(node.AllDataSame(0)) return 
                        return ContainmentType.Intersects;
                    }
                    else if (node.HasChild(i))
                    {
                        Debug.Assert(stackIdx < stackSize);
                        stack[stackIdx++] = new MyCellCoord(data.Lod - 1, nodePositionInChild + childPosRelative);
                    }
                }
            }
            if (inter == invalid) inter = ContainmentType.Disjoint;

            return inter;
        }
        internal void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged, int lod)
        {
            MyPrecalcComponent.AssertUpdateThread();

            // No physics there ever was so we don't care.
            if (!m_bodiesInitialized) return;

            if (m_queueInvalidation)
            {
                if (m_queuedRange.Max.X < 0)
                {
                    m_queuedRange = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
                }
                else
                {
                    var bb = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
                    m_queuedRange.Include(ref bb);
                }
                return;
            }

            ProfilerShort.Begin("MyVoxelPhysicsBody.InvalidateRange");
            minVoxelChanged -= 1;// MyPrecalcComponent.InvalidatedRangeInflate;
            maxVoxelChanged += 1;//MyPrecalcComponent.InvalidatedRangeInflate;
            m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged);
            m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged);

            Vector3I minCellChanged, maxCellChanged;
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCellChanged);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCellChanged);

            Vector3I minCellChangedVoxelMap, maxCellChangedVoxelMap;
            minCellChangedVoxelMap = (minCellChanged - m_cellsOffset) >> lod;
            maxCellChangedVoxelMap = (maxCellChanged - m_cellsOffset) >> lod;

            var maxCell = m_voxelMap.Size - 1;
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxCell, out maxCell);
            maxCell >>= lod;
            Vector3I.Min(ref maxCellChangedVoxelMap, ref maxCell, out maxCellChangedVoxelMap);

            Debug.Assert(RigidBody != null, "RigidBody in voxel physics is null! This must not happen.");

            var rb = GetRigidBody(lod);
            Debug.Assert(rb != null, "RigidBody in voxel physics is null! This must not happen.");

            if (rb != null)
            {
                HkUniformGridShape shape = (HkUniformGridShape)rb.GetShape();
                Debug.Assert(shape.Base.IsValid);


                var numCells = (maxCellChangedVoxelMap - minCellChangedVoxelMap + 1).Size;
                if (numCells >= m_cellsToGenerateBuffer.Length)
                {
                    m_cellsToGenerateBuffer = new Vector3I[MathHelper.GetNearestBiggerPowerOfTwo(numCells)];
                }

                var tmpBuffer = m_cellsToGenerateBuffer;
                int invalidCount = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer);
                Debug.Assert(invalidCount <= tmpBuffer.Length);

                //if (numCells <= 8)
                //shape.InvalidateRangeImmediate(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap);

                Debug.Assert(invalidCount <= tmpBuffer.Length);
                for (int i = 0; i < invalidCount; i++)
                {
                    InvalidCells[lod].Add(tmpBuffer[i]);
                }

                if (RunningBatchTask[lod] == null && InvalidCells[lod].Count != 0)
                {
                    MyPrecalcComponent.PhysicsWithInvalidCells.Add(this);
                }
            }

            if (minCellChangedVoxelMap == Vector3I.Zero && maxCellChangedVoxelMap == maxCell)
            {
                m_workTracker.CancelAll();
            }
            else
            {
                var cell = minCellChanged;
                for (var it = new Vector3I_RangeIterator(ref minCellChanged, ref maxCellChanged);
                    it.IsValid(); it.GetNext(out cell))
                {
                    m_workTracker.Cancel(new MyCellCoord(lod, cell));
                }
            }

            m_needsShapeUpdate = true;

            ProfilerShort.End();

            m_voxelMap.RaisePhysicsChanged();
        }
        public ContainmentType Intersect(ref BoundingBoxI box, bool lazy)
        {
            BoundingBoxI localCoords = box;
            localCoords.Translate(-m_voxelRangeMin);

            return m_octree.Intersect(ref localCoords, lazy);
        }
Esempio n. 37
0
            internal void DoClipping(float camDistanceFromCenter, Vector3D localPosition, float farPlaneDistance, RequestCollector collector, bool frustumCulling, float rangeScale)
            {
                int lodIndex = m_lodIndex;

                if (!ShouldBeThisLodVisible(camDistanceFromCenter))
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                    return;
                }


                m_localPosition = localPosition;
                MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, lodIndex, out m_nearDistance, out m_farDistance);


                farPlaneDistance *= rangeScale;
                m_farDistance    *= rangeScale;
                m_nearDistance   *= rangeScale;

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum && m_lodIndex == lodIndex)
                {
                    return;
                }


                //var localFrustum = new BoundingFrustumD(CameraFrustumGetter().Matrix * m_parent.m_invWorldMatrix);
                var frustum = CameraFrustumGetter();

                Vector3I min, max;
                // Vector3I ignoreMin, ignoreMax;

                var minD = m_localPosition - m_farDistance;
                var maxD = m_localPosition + m_farDistance;

                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref minD, out min);
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref maxD, out max);

                BoundingBoxI lodBox     = new BoundingBoxI(Vector3I.Zero, Vector3I.Max(m_lodSizeMinusOne, Vector3I.Zero));
                bool         intersects = false;

                //bool intersectsNear = false;

                m_localFarCameraBox  = new BoundingBoxI(min, max);
                m_localNearCameraBox = new BoundingBoxI(min, max);
                if (lodBox.Intersects(m_localFarCameraBox))
                {
                    intersects = true;
                    var intersection = lodBox;
                    intersection.IntersectWith(ref m_localFarCameraBox);
                    min = intersection.Min;
                    max = intersection.Max;

                    //Optimize only LOD2 and higher by two lods, because neighbour cells shares border cells
                    //if (m_lodIndex > 1)
                    //{
                    //    float lowerFar, lowerNear;
                    //    MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex - 2, out lowerFar, out lowerNear);

                    //    var minNear = m_localPosition - (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                    //    var maxNear = m_localPosition + (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                    //    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minNear, out ignoreMin);
                    //    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxNear, out ignoreMax);

                    //    m_localNearCameraBox = new BoundingBoxI(ignoreMin, ignoreMax);
                    //    if (lodBox.Intersects(m_localNearCameraBox))
                    //        intersectsNear = false;
                    //}
                }

                //if (m_lastMin == min && m_lastMax == max && !m_clipmap.m_updateClipping)
                //    return;

                //m_lastMin = min;
                //m_lastMax = max;

                //LodLevel parentLod, childLod;
                //GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.

                if (frustumCulling)
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                }

                if (intersects)
                {
                    float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(lodIndex);


                    MyCellCoord cell = new MyCellCoord(lodIndex, ref min);

                    for (var it = new Vector3I.RangeIterator(ref min, ref max);
                         it.IsValid(); it.GetNext(out cell.CoordInLod))
                    {
                        //if (intersectsNear &&
                        //    m_localNearCameraBox.Contains(cell.CoordInLod) == ContainmentType.Contains)
                        //    continue;

                        //if (frustumCulling)
                        //{
                        //    Vector3D minAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod - 2)), m_clipmap.m_worldMatrix);
                        //    Vector3D maxAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod + 2) + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                        //    if (frustum.Contains(new BoundingBoxD(minAABB, maxAABB)) == ContainmentType.Disjoint)
                        //    {
                        //        m_outsideCells.Add(cell.CoordInLod);
                        //        continue;
                        //    }
                        //}

                        UnclipCell(collector, cell, true);
                    }

                    //cache cells around frustum
                    if (collector.SentRequestsEmpty)
                    {
                        foreach (var outsideCell in m_outsideCells)
                        {
                            cell.CoordInLod = outsideCell;
                            UnclipCell(collector, cell, frustumCulling);
                        }
                    }

                    m_outsideCells.Clear();
                }
            }
Esempio n. 38
0
        public bool GetBlockStates(Dictionary <Vector3I, BlockState> blockStates, long projectorId, int subgridIndex, BoundingBoxI box, int mask)
        {
            if (!Available)
            {
                return(false);
            }

            var blockIntStates = new Dictionary <Vector3I, int>();
            var fn             = (Func <Dictionary <Vector3I, int>, long, int, BoundingBoxI, int, bool>)api[6];

            if (!fn(blockIntStates, projectorId, subgridIndex, box, mask))
            {
                return(false);
            }

            foreach (var pair in blockIntStates)
            {
                blockStates[pair.Key] = (BlockState)pair.Value;
            }

            return(true);
        }
Esempio n. 39
0
        private void MergeAsteroidMaterialFrom(ref MyVoxelMap newAsteroid, Vector3 min, StructureVoxelModel modelPrimary, StructureVoxelModel modelSecondary, Vector3 minPrimary, Vector3 minSecondary)
        {
            var      filenameSecondary = modelSecondary.SourceVoxelFilepath ?? modelSecondary.VoxelFilepath;
            var      filenamePrimary   = modelPrimary.SourceVoxelFilepath ?? modelPrimary.VoxelFilepath;
            Vector3I block;
            Vector3I newBlock;
            Vector3I cacheSize;

            var asteroid = new MyVoxelMap();

            asteroid.Load(filenamePrimary);
            BoundingBoxI content = modelPrimary.InflatedContentBounds;

            for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64)
            {
                for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64)
                {
                    for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64)
                    {
                        var cache = new MyStorageData();
                        cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1,
                                                 MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1,
                                                 MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1);

                        cache.Resize(cacheSize);
                        asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1);

                        newBlock = ((minPrimary - min) + (Vector3D)(block - content.Min)).RoundToVector3I();
                        newAsteroid.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1);
                    }
                }
            }

            asteroid.Load(filenameSecondary);
            content = modelSecondary.InflatedContentBounds;
            for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64)
            {
                for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64)
                {
                    for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64)
                    {
                        var cache = new MyStorageData();
                        cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1,
                                                 MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1,
                                                 MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1);

                        cache.Resize(cacheSize);
                        asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1);

                        newBlock = ((minSecondary - min) + (Vector3D)(block - content.Min)).RoundToVector3I();
                        var newCache = new MyStorageData();
                        newCache.Resize(cacheSize);
                        newAsteroid.Storage.ReadRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, newBlock, newBlock + cacheSize - 1);

                        Vector3I p;
                        for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z)
                        {
                            for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y)
                            {
                                for (p.X = 0; p.X < cacheSize.X; ++p.X)
                                {
                                    byte volume   = cache.Content(ref p);
                                    byte material = cache.Material(ref p);
                                    if (volume > 0)
                                    {
                                        newCache.Material(ref p, material);
                                    }
                                }
                            }
                        }

                        newAsteroid.Storage.WriteRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1);
                    }
                }
            }
        }
Esempio n. 40
0
 public ContainmentType Intersect(ref BoundingBoxI box, bool lazy = false)
 {
     return(m_provider.Intersect(box, lazy));
 }
        internal void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged, int lod)
        {
            MyPrecalcComponent.AssertUpdateThread();
            // No physics there ever was so we don't care.
            if (!m_bodiesInitialized) return;

            if (m_queueInvalidation)
            {
                if (m_queuedRange.Max.X < 0)
                {
                    m_queuedRange = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
                }
                else
                {
                    var bb = new BoundingBoxI(minVoxelChanged, maxVoxelChanged);
                    m_queuedRange.Include(ref bb);
                }
                return;
            }

            ProfilerShort.Begin("MyVoxelPhysicsBody.InvalidateRange");
            minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate;
            maxVoxelChanged += MyPrecalcComponent.InvalidatedRangeInflate;
            m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged);
            m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged);

            Vector3I minCellChanged, maxCellChanged;
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCellChanged);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCellChanged);

            Vector3I minCellChangedVoxelMap, maxCellChangedVoxelMap;
            minCellChangedVoxelMap = (minCellChanged - m_cellsOffset) >> lod;
            maxCellChangedVoxelMap = (maxCellChanged - m_cellsOffset) >> lod;

            var maxCell = m_voxelMap.Size - 1;
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxCell, out maxCell);
            maxCell >>= lod;
            Vector3I.Min(ref maxCellChangedVoxelMap, ref maxCell, out maxCellChangedVoxelMap);

            Debug.Assert(RigidBody != null, "RigidBody in voxel physics is null! This must not happen.");

            var rb = GetRigidBody(lod);
            Debug.Assert(rb != null, "RigidBody in voxel physics is null! This must not happen.");
            
            if (rb != null)
            {
                HkUniformGridShape shape = (HkUniformGridShape) rb.GetShape();
                Debug.Assert(shape.Base.IsValid);

                var tmpBuffer = m_cellsToGenerateBuffer;
                int invalidCount = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer);
                if (invalidCount > tmpBuffer.Length)
                {
                    // Not storing this new buffer in static variable since this is just temporary and potentially large.
                    // Static variable could be potentially the same as leak.
                    tmpBuffer = new Vector3I[invalidCount];
                    int invalidCount2 = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer);
                    Debug.Assert(invalidCount == invalidCount2);
                    invalidCount = invalidCount2;
                }
                
                shape.InvalidateRangeImmediate(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap);
                Debug.Assert(invalidCount <= tmpBuffer.Length);
                for (int i = 0; i < invalidCount; i++)
                {
                    InvalidCells.Add(tmpBuffer[i]);
                }
                if (RunningBatchTask == null && InvalidCells.Count != 0)
                {
                    MyPrecalcComponent.PhysicsWithInvalidCells.Add(this);
                }
            }

            if (minCellChangedVoxelMap == Vector3I.Zero && maxCellChangedVoxelMap == maxCell)
            {
                m_workTracker.CancelAll();
            }
            else
            {
                var cell = minCellChanged;
                for (var it = new Vector3I.RangeIterator(ref minCellChanged, ref maxCellChanged);
                    it.IsValid(); it.GetNext(out cell))
                {
                    m_workTracker.Cancel(new MyCellCoord(lod, cell));
                }
            }

            m_needsShapeUpdate = true;

            ProfilerShort.End();

            m_voxelMap.RaisePhysicsChanged();
        }
Esempio n. 42
0
        public static ContainmentType Intersect(this VRage.Game.Voxels.IMyStorage self, ref BoundingBox box, bool lazy = true)
        {
            BoundingBoxI xi = new BoundingBoxI(box);

            return(self.Intersect(ref xi, 0, lazy));
        }