private void Segment()
        {
            m_segmentation.ClearInput();

            foreach (var block in m_grid.CubeBlocks)
            {
                Vector3I begin = block.Min;
                Vector3I end   = block.Max;
                Vector3I pos   = begin;
                for (var it = new Vector3I_RangeIterator(ref begin, ref end); it.IsValid(); it.GetNext(out pos))
                {
                    m_segmentation.AddInput(pos);
                }
            }

            var segmentList = m_segmentation.FindSegments(MyVoxelSegmentationType.Simple2);

            m_segments = new List <BoundingBox>(segmentList.Count);
            for (int i = 0; i < segmentList.Count; ++i)
            {
                BoundingBox bb = new BoundingBox();
                bb.Min = (new Vector3(segmentList[i].Min) - Vector3.Half) * m_grid.GridSize - Vector3.Half; // The another half is here to just add some head space
                bb.Max = (new Vector3(segmentList[i].Max) + Vector3.Half) * m_grid.GridSize + Vector3.Half;
                m_segments.Add(bb);
            }

            m_segmentation.ClearInput();
        }
Exemple #2
0
        public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;

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

            for (var itCells = new Vector3I_RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

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

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

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

                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, ref cellMinCorner, ref cellMaxCorner);
            }
        }
Exemple #3
0
        private void Segment()
        {
            m_segmentation.ClearInput();
            foreach (MySlimBlock local1 in this.m_grid.CubeBlocks)
            {
                Vector3I min   = local1.Min;
                Vector3I max   = local1.Max;
                Vector3I input = min;
                Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref min, ref max);
                while (iterator.IsValid())
                {
                    m_segmentation.AddInput(input);
                    iterator.GetNext(out input);
                }
            }
            List <Sandbox.Engine.Utils.MyVoxelSegmentation.Segment> list = m_segmentation.FindSegments(MyVoxelSegmentationType.Simple2, 1);

            this.m_segments = new List <BoundingBox>(list.Count);
            for (int i = 0; i < list.Count; i++)
            {
                BoundingBox item = new BoundingBox {
                    Min = ((new Vector3(list[i].Min) - Vector3.Half) * this.m_grid.GridSize) - Vector3.Half,
                    Max = ((new Vector3(list[i].Max) + Vector3.Half) * this.m_grid.GridSize) + Vector3.Half
                };
                this.m_segments.Add(item);
            }
            m_segmentation.ClearInput();
        }
Exemple #4
0
        /// <summary>
        /// Non-allocating version of Sandbox.Game.Entities.MyCubeGrid.GetBlocksInsideSphere()
        /// </summary>
        public void GetBlocksInsideSphere(IMyCubeGrid grid, List <IMySlimBlock> blockList, ref BoundingSphereD sphere)
        {
            if (grid.PositionComp != null)
            {
                MatrixD  matrix = grid.PositionComp.WorldMatrixNormalizedInv;
                Vector3D result;

                Vector3D.Transform(ref sphere.Center, ref matrix, out result);
                BoundingSphere localSphere = new BoundingSphere(result, (float)sphere.Radius);
                BoundingBox    boundingBox = BoundingBox.CreateFromSphere(localSphere);
                double         gridSizeR   = 1d / grid.GridSize;

                Vector3I searchMin = new Vector3I
                                     (
                    (int)Math.Round(boundingBox.Min.X * gridSizeR),
                    (int)Math.Round(boundingBox.Min.Y * gridSizeR),
                    (int)Math.Round(boundingBox.Min.Z * gridSizeR)
                                     );
                Vector3I searchMax = new Vector3I
                                     (
                    (int)Math.Round(boundingBox.Max.X * gridSizeR),
                    (int)Math.Round(boundingBox.Max.Y * gridSizeR),
                    (int)Math.Round(boundingBox.Max.Z * gridSizeR)
                                     );

                Vector3I start = Vector3I.Max(Vector3I.Min(searchMin, searchMax), grid.Min);
                Vector3I end   = Vector3I.Min(Vector3I.Max(searchMin, searchMax), grid.Max);

                var      gridIterator = new Vector3I_RangeIterator(ref start, ref end);
                Vector3I next         = gridIterator.Current;

                blockHashBuffer.Clear();

                while (gridIterator.IsValid())
                {
                    IMySlimBlock cube         = grid.GetCubeBlock(next);
                    float        gridSizeHalf = grid.GridSize / 2f;

                    if (cube != null)
                    {
                        var cubeBounds = new BoundingBox((cube.Min * grid.GridSize) - gridSizeHalf, (cube.Max * grid.GridSize) + gridSizeHalf);

                        if (cubeBounds.Intersects(localSphere))
                        {
                            blockHashBuffer.Add(cube);
                        }
                    }

                    gridIterator.GetNext(out next);
                }

                blockList.Clear();
                blockList.EnsureCapacity(blockHashBuffer.Count);

                foreach (IMySlimBlock block in blockHashBuffer)
                {
                    blockList.Add(block);
                }
            }
        }
Exemple #5
0
 internal void GenerateAllShapes()
 {
     if (this.m_mesher != null)
     {
         if (!this.m_bodiesInitialized)
         {
             this.CreateRigidBodies();
         }
         Vector3I zero = Vector3I.Zero;
         Vector3I size = this.m_voxelMap.Size;
         Vector3I end  = new Vector3I(0, 0, 0)
         {
             X = size.X >> 3,
             Y = size.Y >> 3,
             Z = size.Z >> 3
         };
         end = (Vector3I)(end + zero);
         MyPrecalcJobPhysicsPrefetch.Args args = new MyPrecalcJobPhysicsPrefetch.Args {
             GeometryCell  = new MyCellCoord(1, zero),
             Storage       = this.m_voxelMap.Storage,
             TargetPhysics = this,
             Tracker       = this.m_workTracker
         };
         Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref zero, ref end);
         while (iterator.IsValid())
         {
             MyPrecalcJobPhysicsPrefetch.Start(args);
             iterator.GetNext(out args.GeometryCell.CoordInLod);
         }
     }
 }
Exemple #6
0
        public void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged)
        {
            Vector3I vectori;
            Vector3I vectori2;

            minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate;
            maxVoxelChanged  = (Vector3I)(maxVoxelChanged + MyPrecalcComponent.InvalidatedRangeInflate);
            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 position = vectori;
            Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori, ref vectori2);

            while (iterator.IsValid())
            {
                if (!this.m_processedCells.Contains(ref position))
                {
                    this.m_higherLevelHelper.TryClearCell(new MyCellCoord(0, position).PackId64());
                }
                else if (!this.m_cellsToChangeSet.Contains(ref position))
                {
                    this.m_cellsToChange.AddLast(position);
                    this.m_cellsToChangeSet.Add(position);
                }
                iterator.GetNext(out position);
            }
        }
            private int GetDivideIndex(ref Vector3I renderCellCoord)
            {
                // TODO: Optimize
                int divideIndex = 0;

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

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

            MyVoxelPhysics voxelMap;

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

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

            OnRangeChanged(minChanged, maxChanged, dataChanged);
            ProfilerShort.End();
        }
        private MyVoxelPhysics CreateVoxelPhysics(ref Vector3I increment, ref Vector3I_RangeIterator it)
        {
            if (m_physicsShapes == null)
            {
                m_physicsShapes = new MyConcurrentDictionary <Vector3I, MyVoxelPhysics>();
            }

            MyVoxelPhysics voxelMap = null;

            if (!m_physicsShapes.TryGetValue(it.Current, out voxelMap))
            {
                Vector3I storageMin = it.Current * increment;
                Vector3I storageMax = storageMin + increment;

                BoundingBox check = new BoundingBox(storageMin, storageMax);

                if (Storage.Intersect(ref check, false) == ContainmentType.Intersects)
                {
                    voxelMap = new MyVoxelPhysics();

                    voxelMap.Init(m_storage,
                                  this.PositionLeftBottomCorner + storageMin * MyVoxelConstants.VOXEL_SIZE_IN_METRES, storageMin,
                                  storageMax, this);
                    voxelMap.Save = false;
                    MyEntities.Add(voxelMap);
                }

                m_physicsShapes.Add(it.Current, voxelMap);
            }
            return(voxelMap);
        }
Exemple #10
0
        public unsafe void MarkBoxForAddition(BoundingBoxD box)
        {
            Vector3I vectori;
            Vector3I vectori2;

            MyVoxelCoordSystems.WorldPositionToVoxelCoord(this.m_voxelMap.PositionLeftBottomCorner, ref box.Min, out vectori);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(this.m_voxelMap.PositionLeftBottomCorner, ref box.Max, out vectori2);
            this.m_voxelMap.Storage.ClampVoxelCoord(ref vectori, 1);
            this.m_voxelMap.Storage.ClampVoxelCoord(ref vectori2, 1);
            Vector3I *vectoriPtr1 = (Vector3I *)ref vectori;

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref (Vector3I) ref vectoriPtr1, out vectori);
            Vector3I *vectoriPtr2 = (Vector3I *)ref vectori2;

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref (Vector3I) ref vectoriPtr2, out vectori2);
            Vector3 vector = (vectori + vectori2) * 0.5f;

            vectori  = (Vector3I)(vectori / 1);
            vectori2 = (Vector3I)(vectori2 / 1);
            Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori, ref vectori2);

            while (iterator.IsValid())
            {
                if (Vector3.RectangularDistance((Vector3)vectori, vector) <= 1f)
                {
                    this.MarkCellForAddition(vectori, PresentEntityWeight);
                }
                iterator.GetNext(out vectori);
            }
        }
Exemple #11
0
            /// <summary>
            /// Checks only immediate children (any deeper would take too long).
            /// </summary>
            private static bool ChildrenWereLoaded(LodLevel childLod, ref MyCellCoord thisLodCell)
            {
                if (childLod == null)
                {
                    return(false);
                }

                Debug.Assert(thisLodCell.Lod == childLod.m_lodIndex + 1);

                var childLodCell = new MyCellCoord();

                childLodCell.Lod = childLod.m_lodIndex;
                var shiftToChild = MyVoxelCoordSystems.RenderCellSizeShiftToMoreDetailed(thisLodCell.Lod);
                var start        = thisLodCell.CoordInLod << shiftToChild;
                var end          = start + ((1 << shiftToChild) >> 1);

                Vector3I.Max(ref childLod.m_lodSizeMinusOne, ref Vector3I.Zero, out childLod.m_lodSizeMinusOne);
                Vector3I.Min(ref end, ref childLod.m_lodSizeMinusOne, out end);
                childLodCell.CoordInLod = start;
                for (var it = new Vector3I_RangeIterator(ref start, ref end);
                     it.IsValid(); it.GetNext(out childLodCell.CoordInLod))
                {
                    var key = childLodCell.PackId64();
                    MyClipmap_CellData data;
                    if (!childLod.m_storedCellData.TryGetValue(key, out data) || !data.WasLoaded)
                    {
                        return(false);
                    }
                }

                return(true);
            }
Exemple #12
0
            internal void InvalidateRange(Vector3I lodMin, Vector3I lodMax)
            {
                //              MyLog.Default.WriteLine("InvalidateRange Lod: " + m_lodIndex + " Min: " + lodMin + " Max: " + lodMax);

                var cell = new MyCellCoord(m_lodIndex, lodMin);

                for (var it = new Vector3I_RangeIterator(ref lodMin, ref lodMax);
                     it.IsValid(); it.GetNext(out cell.CoordInLod))
                {
                    MyClipmap_CellData data;
                    var id = cell.PackId64();
//                    MyLog.Default.WriteLine("Setting to: m_lodIndex " + cell.Lod + " Coord: " + cell.CoordInLod);


                    if (m_storedCellData.TryGetValue(id, out data))
                    {
                        data.State = CellState.Invalid;
                        //MyLog.Default.WriteLine("Really set to: m_lodIndex " + cell.Lod + " Coord: " + cell.CoordInLod);
                    }

                    if (MyClipmap.UseCache)
                    {
                        var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, id);
                        var cachedCell    = MyClipmap.CellsCache.Read(clipmapCellId);
                        if (cachedCell != null)
                        {
                            cachedCell.State = CellState.Invalid;
                        }
                    }
                }
            }
        private Vector3I FindTriangleCube(int triIndex, ref Vector3I edgePositionA, ref Vector3I edgePositionB)
        {
            Vector3I min, max;

            Vector3I.Min(ref edgePositionA, ref edgePositionB, out min);
            Vector3I.Max(ref edgePositionA, ref edgePositionB, out max);
            min = Vector3I.Round(new Vector3(min) / 256.0f - Vector3.Half);
            max = Vector3I.Round(new Vector3(max) / 256.0f + Vector3.Half);

            for (var it = new Vector3I_RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out min))
            {
                List <int> list;
                m_smallTriangleRegistry.TryGetValue(min, out list);
                if (list == null)
                {
                    continue;
                }

                if (list.Contains(triIndex))
                {
                    return(min);
                }
            }

            Debug.Assert(false, "Could not find navmesh triangle cube. Shouldn't get here!");
            return(Vector3I.Zero);
        }
        protected override void Init(MyObjectBuilder_DefinitionBase ob)
        {
            base.Init(ob);

            var objectBuilder = ob as MyObjectBuilder_BlockNavigationDefinition;

            Debug.Assert(ob != null);
            if (ob == null)
            {
                return;
            }

            if (objectBuilder.NoEntry || objectBuilder.Triangles == null)
            {
                NoEntry = true;
            }
            else
            {
                NoEntry = false;
                var newMesh = new MyGridNavigationMesh(null, null, objectBuilder.Triangles.Length);

                Vector3I maxPos = objectBuilder.Size - Vector3I.One - objectBuilder.Center;
                Vector3I minPos = -(Vector3I)(objectBuilder.Center);

                foreach (var triOb in objectBuilder.Triangles)
                {
                    Vector3 pa = (Vector3)triOb.Points[0];
                    Vector3 pb = (Vector3)triOb.Points[1];
                    Vector3 pc = (Vector3)triOb.Points[2];

                    var tri = newMesh.AddTriangle(ref pa, ref pb, ref pc);

                    var center = (pa + pb + pc) / 3.0f;

                    // We want to move the triangle vertices more towards the triangle center to ensure correct calculation of containing cube
                    Vector3  cvA      = (center - pa) * 0.0001f;
                    Vector3  cvB      = (center - pb) * 0.0001f;
                    Vector3  cvC      = (center - pc) * 0.0001f;
                    Vector3I gridPosA = Vector3I.Round(pa + cvA);
                    Vector3I gridPosB = Vector3I.Round(pb + cvB);
                    Vector3I gridPosC = Vector3I.Round(pc + cvC);
                    Vector3I.Clamp(ref gridPosA, ref minPos, ref maxPos, out gridPosA);
                    Vector3I.Clamp(ref gridPosB, ref minPos, ref maxPos, out gridPosB);
                    Vector3I.Clamp(ref gridPosC, ref minPos, ref maxPos, out gridPosC);
                    Vector3I min, max;
                    Vector3I.Min(ref gridPosA, ref gridPosB, out min);
                    Vector3I.Min(ref min, ref gridPosC, out min);
                    Vector3I.Max(ref gridPosA, ref gridPosB, out max);
                    Vector3I.Max(ref max, ref gridPosC, out max);

                    Vector3I pos = min;
                    for (var it = new Vector3I_RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos))
                    {
                        newMesh.RegisterTriangle(tri, ref pos);
                    }
                }

                m_mesh = newMesh;
            }
        }
Exemple #15
0
        internal void GenerateAllShapes()
        {
            if (!m_bodiesInitialized)
            {
                CreateRigidBodies();
            }

            var min = Vector3I.Zero;

            Vector3I storageSize = m_voxelMap.Size;
            Vector3I max         = new Vector3I(0, 0, 0);

            max.X = storageSize.X >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            max.Y = storageSize.Y >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            max.Z = storageSize.Z >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;

            max += min;

            var args = new MyPrecalcJobPhysicsPrefetch.Args
            {
                GeometryCell  = new MyCellCoord(1, min),
                Storage       = m_voxelMap.Storage,
                TargetPhysics = this,
                Tracker       = m_workTracker
            };

            for (var it = new Vector3I_RangeIterator(ref min, ref max);
                 it.IsValid();
                 it.GetNext(out args.GeometryCell.CoordInLod))
            {
                MyPrecalcJobPhysicsPrefetch.Start(args);
            }
        }
Exemple #16
0
        private unsafe void storage_RangeChanged(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags changedData)
        {
            Vector3I voxelCoord = minChanged - MyPrecalcComponent.InvalidatedRangeInflate;
            Vector3I vectori2   = (Vector3I)(maxChanged + MyPrecalcComponent.InvalidatedRangeInflate);

            this.m_storage.ClampVoxelCoord(ref voxelCoord, 1);
            this.m_storage.ClampVoxelCoord(ref vectori2, 1);
            Vector3I start = voxelCoord >> 3;
            Vector3I end   = vectori2 >> 3;

            using (this.m_lock.AcquireExclusiveUsing())
            {
                if ((start == Vector3I.Zero) && (end == (this.m_cellsCount - 1)))
                {
                    this.m_cellsByCoordinate.Clear();
                    this.m_coordinateToMesh.Clear();
                    this.m_isEmptyCache.Reset();
                }
                else
                {
                    MyCellCoord cell = new MyCellCoord();
                    if ((this.m_cellsByCoordinate.Count > 0) || (this.m_coordinateToMesh.Count > 0))
                    {
                        cell.CoordInLod = start;
                        Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref start, ref end);
                        while (iterator.IsValid())
                        {
                            ulong key = cell.PackId64();
                            this.m_cellsByCoordinate.Remove(key);
                            this.m_coordinateToMesh.Remove(key);
                            iterator.GetNext(out cell.CoordInLod);
                        }
                    }
                    if ((end - start).Volume() <= 0x186a0)
                    {
                        Vector3I_RangeIterator iterator3 = new Vector3I_RangeIterator(ref start, ref end);
                        while (iterator3.IsValid())
                        {
                            this.SetEmpty(ref cell, false);
                            iterator3.GetNext(out cell.CoordInLod);
                        }
                    }
                    else
                    {
                        Vector3I vectori6 = start >> 2;
                        Vector3I vectori7 = (Vector3I)((end >> 2) + 1);
                        cell.CoordInLod = vectori6;
                        Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori6, ref vectori7);
                        while (iterator2.IsValid())
                        {
                            Vector3I *vectoriPtr1 = (Vector3I *)ref cell.CoordInLod;
                            vectoriPtr1[0] = vectoriPtr1[0] << 2;
                            this.RemoveEmpty(ref cell);
                            iterator2.GetNext(out cell.CoordInLod);
                        }
                    }
                }
            }
        }
 private static void GetCellCorners(ref Vector3I minCorner, ref Vector3I maxCorner,
                                    ref Vector3I_RangeIterator it, out Vector3I cellMinCorner, out Vector3I cellMaxCorner)
 {
     cellMinCorner = new Vector3I(minCorner.X + it.Current.X * 16, minCorner.Y + it.Current.Y * 16,
                                  minCorner.Z + it.Current.Z * 16);
     cellMaxCorner = new Vector3I(Math.Min(maxCorner.X, cellMinCorner.X + 16),
                                  Math.Min(maxCorner.Y, cellMinCorner.Y + 16), Math.Min(maxCorner.Z, cellMinCorner.Z + 16));
 }
        protected override MyProceduralCell GenerateCellSeeds(Vector3I cellId)
        {
            if (m_loadedCells.ContainsKey(cellId))
            {
                return(null);
            }

            var settings = MySettingsSession.Static.Settings.GeneratorSettings;

            if (settings.AsteroidGenerator == AsteroidGenerationMethod.VANILLA)
            {
                return(null);
            }

            MyProceduralCell cell = new MyProceduralCell(cellId, CELL_SIZE);
            int    cellSeed       = CalculateCellSeed(cellId);
            int    index          = 0;
            double subCellSize    = OBJECT_SIZE_MAX * 1f / settings.AsteroidDensity;
            int    subcells       = (int)(CELL_SIZE / subCellSize);

            using (MyRandom.Instance.PushSeed(cellSeed))
            {
                Vector3I subcellId = Vector3I.Zero;
                Vector3I max       = new Vector3I(subcells - 1);

                for (var it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref max); it.IsValid(); it.GetNext(out subcellId))
                {
                    Vector3D position = new Vector3D(MyRandom.Instance.NextDouble(), MyRandom.Instance.NextDouble(), MyRandom.Instance.NextDouble());
                    position += (Vector3D)subcellId;
                    position *= subCellSize;
                    position += ((Vector3D)cellId) * CELL_SIZE;

                    if (!MyEntities.IsInsideWorld(position) || (settings.WorldSize >= 0 && position.Length() > settings.WorldSize))
                    {
                        continue;
                    }

                    var ring = GetAsteroidObjectAt(position);

                    if (ring == null)
                    {
                        continue;
                    }

                    var cellObjectSeed = new MyObjectSeed(cell, position, MyRandom.Instance.Next(ring.AsteroidSize.Min, ring.AsteroidSize.Max));
                    cellObjectSeed.Params.Type          = VRage.Game.MyObjectSeedType.Asteroid;
                    cellObjectSeed.Params.Seed          = MyRandom.Instance.Next();
                    cellObjectSeed.Params.Index         = index++;
                    cellObjectSeed.Params.GeneratorSeed = m_definition.UseGeneratorSeed ? MyRandom.Instance.Next() : 0;

                    cell.AddObject(cellObjectSeed);

                    MyPluginLog.Debug("Adding seed");
                }
            }

            return(cell);
        }
        public override MyProceduralCell GenerateCell(ref Vector3I id)
        {
            MyProceduralCell cell = new MyProceduralCell(id, CELL_SIZE_);
            int cellSeed          = GetCellSeed(ref id);

            using (MyRandom.Instance.PushSeed(cellSeed))
            {
                int index = 0;

                int subCellSize = (int)(OBJECT_SIZE_MAX * 2 / m_density);
                int subcells    = CELL_SIZE_ / subCellSize;

                Vector3I subcellId = Vector3I.Zero;
                Vector3I max       = new Vector3I(subcells - 1);

                for (var it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref max); it.IsValid(); it.GetNext(out subcellId))
                {
                    Vector3D position = new Vector3D(MyRandom.Instance.NextDouble(), MyRandom.Instance.NextDouble(), MyRandom.Instance.NextDouble());
                    position += (Vector3D)subcellId;
                    position *= subCellSize;
                    position += id * CELL_SIZE_;

                    if (!MyEntities.IsInsideWorld(position))
                    {
                        continue;
                    }

                    MySystemItem obj = IsInsideRing(position);

                    if (obj == null)
                    {
                        continue;
                    }
                    int minSize = OBJECT_SIZE_MIN;
                    int maxSize = OBJECT_SIZE_MAX;

                    if (obj.Type == SystemObjectType.BELT)
                    {
                        minSize = ((MySystemBeltItem)obj).RoidSize;
                    }

                    if (obj.Type == SystemObjectType.RING)
                    {
                        minSize = ((MyPlanetRingItem)obj).RoidSize;
                        maxSize = ((MyPlanetRingItem)obj).RoidSizeMax;
                    }

                    var cellObject = new MyObjectSeed(cell, position, MyRandom.Instance.Next(Math.Min(maxSize, minSize), Math.Max(maxSize, minSize)));
                    cellObject.Params.Type  = MyObjectSeedType.Asteroid;
                    cellObject.Params.Seed  = MyRandom.Instance.Next();
                    cellObject.Params.Index = index++;

                    cell.AddObject(cellObject);
                }
            }

            return(cell);
        }
Exemple #20
0
        private MyShipMergeBlock GetOtherMergeBlock()
        {
            Vector3I minI, maxI;

            CalculateMergeArea(out minI, out maxI);

            Vector3I pos = minI;

            for (Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref minI, ref maxI); it.IsValid(); it.GetNext(out pos))
            {
                var block = this.CubeGrid.GetCubeBlock(pos);
                if (block != null && block.FatBlock != null)
                {
                    var mergeBlock = block.FatBlock as MyShipMergeBlock;
                    if (mergeBlock == null)
                    {
                        continue;
                    }

                    Vector3I otherMinI, otherMaxI;
                    mergeBlock.CalculateMergeArea(out otherMinI, out otherMaxI);
                    Vector3I faceNormal = Base6Directions.GetIntVector(this.Orientation.TransformDirection(m_forward));

                    // Bounding box test of minI <-> maxI and otherMinI(shifted by faceNormal) <-> otherMaxI(shifted by faceNormal)
                    otherMinI = maxI - (otherMinI + faceNormal);
                    otherMaxI = otherMaxI + faceNormal - minI;
                    if (otherMinI.X < 0)
                    {
                        continue;
                    }
                    if (otherMinI.Y < 0)
                    {
                        continue;
                    }
                    if (otherMinI.Z < 0)
                    {
                        continue;
                    }
                    if (otherMaxI.X < 0)
                    {
                        continue;
                    }
                    if (otherMaxI.Y < 0)
                    {
                        continue;
                    }
                    if (otherMaxI.Z < 0)
                    {
                        continue;
                    }

                    return(mergeBlock);
                }
            }

            return(null);
        }
Exemple #21
0
        public static IEnumerable <Vector3I> IterateTo(this Vector3I start, Vector3I end)
        {
            Vector3I pos = new Vector3I();

            for (var it = new Vector3I_RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out pos))
            {
                yield return(pos);
            }
        }
Exemple #22
0
 public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
 {
     using (voxelMap.Pin())
     {
         if (!voxelMap.MarkedForClose)
         {
             Vector3I vectori;
             Vector3I maxCorner;
             Vector3I minCorner;
             GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori);
             if (m_cache == null)
             {
                 m_cache = new MyStorageData(MyStorageDataTypeFlags.All);
             }
             Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref vectori);
             while (true)
             {
                 Vector3I vectori2;
                 Vector3I vectori3;
                 if (!it.IsValid())
                 {
                     MySandboxGame.Static.Invoke(delegate {
                         if (voxelMap.Storage != null)
                         {
                             voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All);
                         }
                     }, "PaintInShape notify");
                     break;
                 }
                 GetCellCorners(ref minCorner, ref maxCorner, ref it, out vectori2, out vectori3);
                 m_cache.Resize(vectori2, vectori3);
                 MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent;
                 voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, vectori2, vectori3, ref considerContent);
                 Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori2, ref vectori3);
                 while (true)
                 {
                     Vector3D vectord;
                     if (!iterator2.IsValid())
                     {
                         voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, vectori2, vectori3, false, true);
                         it.MoveNext();
                         break;
                     }
                     Vector3I p = iterator2.Current - vectori2;
                     MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref iterator2.Current, out vectord);
                     if ((shape.GetVolume(ref vectord) > 0.5f) && (m_cache.Material(ref p) != 0xff))
                     {
                         m_cache.Material(ref p, materialIdx);
                     }
                     iterator2.MoveNext();
                 }
             }
         }
     }
 }
        private float GetDensity(ref Vector3D voxelCoord, int iterations)
        {
            // ReSharper disable once ImpureMethodCallOnReadonlyValueField
            if (Box.Contains(voxelCoord) == ContainmentType.Disjoint)
            {
                return(0f);
            }
            var inflatedBox = new BoundingBoxD(voxelCoord - 0.5f, voxelCoord + 0.5f);
            var queryBox    = new BoundingBoxD(inflatedBox.Min - 0.1f, inflatedBox.Max + 0.1f + QueryDir * 1000);

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

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

            List <int> tmp;

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

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

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

            _stackBorrow.Push(tmp);
            return(hit / (float)((iterations + 1) * (iterations + 1) * (iterations + 1)));
        }
Exemple #24
0
        private void ComputeBlockMap(MyObjectBuilder_CubeGrid primaryGrid, IEnumerable <MyObjectBuilder_CubeGrid> allGrids, BlockSetInfo info)
        {
            m_blocks.Clear();
            info.BlockCountByType.Clear();
            info.ComponentCost.Clear();
            info.PowerConsumptionByGroup.Clear();

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

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

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

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

                    var powerUsage = PowerUtilities.MaxPowerConsumption(def);
                    // if it is off, ignore it.
                    if (Math.Abs(powerUsage.Consumption) > 1e-8 && ((block as MyObjectBuilder_FunctionalBlock)?.Enabled ?? true))
                    {
                        info.PowerConsumptionByGroup.AddValue(powerUsage.ResourceGroup, powerUsage.Consumption);
                    }
                }
            }
        }
Exemple #25
0
            public SphereQuery(MyVector3Grid <T> parent, ref Vector3 point, float dist)
            {
                this.m_parent = parent;
                this.m_point  = point;
                this.m_distSq = dist * dist;
                Vector3  vector   = new Vector3(dist);
                Vector3I binIndex = this.m_parent.GetBinIndex(((Vector3)point) - vector);
                Vector3I end      = this.m_parent.GetBinIndex(((Vector3)point) + vector);

                this.m_rangeIterator = new Vector3I_RangeIterator(ref binIndex, ref end);
                this.m_previousIndex = -1;
                this.m_storageIndex  = -1;
            }
Exemple #26
0
            public Enumerator(MyVector3DGrid <T> parent, ref Vector3D point, double dist)
            {
                this.m_parent = parent;
                this.m_point  = point;
                this.m_distSq = dist * dist;
                Vector3D vectord = new Vector3D(dist);
                Vector3I start   = Vector3I.Floor((Vector3D)((point - vectord) * parent.m_divisor));
                Vector3I end     = Vector3I.Floor((Vector3D)((point + vectord) * parent.m_divisor));

                this.m_rangeIterator = new Vector3I_RangeIterator(ref start, ref end);
                this.m_previousIndex = -1;
                this.m_storageIndex  = -1;
            }
Exemple #27
0
        public IEnumerable <MyTuple <Vector4I, Vector4D> > TryGetSpawnIn(BoundingBoxD aabb, Func <BoundingBoxD, bool> test = null)
        {
            var rootCellsMin = Vector3I.Floor(aabb.Min / m_cubeSideMax);
            var rootCellsMax = Vector3I.Floor(aabb.Max / m_cubeSideMax);

            for (var rootCells = new Vector3I_RangeIterator(ref rootCellsMin, ref rootCellsMax); rootCells.IsValid(); rootCells.MoveNext())
            {
                foreach (var k in GetSpawnsIn(new Vector4I(rootCells.Current, 0), aabb, test))
                {
                    yield return(k);
                }
            }
        }
        public static MyDefinitionId?VoxelMaterialAt(this MyVoxelBase voxel, Vector3D min, Vector3D grow,
                                                     ref MyStorageData cache)
        {
            if (cache == null)
            {
                cache = new MyStorageData();
            }
            var      shape = new BoundingBoxD(Vector3D.Min(min, min + grow), Vector3D.Max(min, min + grow));
            Vector3I voxMin;
            Vector3I voxMax;
            Vector3I voxCells;

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

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

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

            return(null);
        }
            public Enumerator(MyVector3DGrid <T> parent, ref Vector3D point, double dist)
            {
                m_parent = parent;
                m_point  = point;
                m_distSq = dist * dist;

                Vector3D offset = new Vector3D(dist);
                Vector3I start  = Vector3I.Floor((point - offset) * parent.m_divisor);
                Vector3I end    = Vector3I.Floor((point + offset) * parent.m_divisor);

                m_rangeIterator = new Vector3I_RangeIterator(ref start, ref end);

                m_previousIndex = -1;
                m_storageIndex  = -1;
            }
Exemple #30
0
            public SphereQuery(MyVector3Grid <T> parent, ref Vector3 point, float dist)
            {
                m_parent = parent;
                m_point  = point;
                m_distSq = dist * dist;

                Vector3  offset = new Vector3(dist);
                Vector3I start  = m_parent.GetBinIndex(point - offset);
                Vector3I end    = m_parent.GetBinIndex(point + offset);

                m_rangeIterator = new Vector3I_RangeIterator(ref start, ref end);

                m_previousIndex = -1;
                m_storageIndex  = -1;
            }
        // Actually, this function marks even cubes around the block to make sure that any changes caused in their triangles
        // will be reflected in the navigation mesh.
        public void MarkBlockChanged(MySlimBlock block)
        {
            Vector3I min = block.Min - Vector3I.One;
            Vector3I max = block.Max + Vector3I.One;

            Vector3I pos = min;
            for (var it = new Vector3I_RangeIterator(ref block.Min, ref block.Max); it.IsValid(); it.GetNext(out pos))
            {
                m_changedCubes.Add(pos);
            }

            Vector3I minCell = CubeToCell(ref min);
            Vector3I maxCell = CubeToCell(ref max);

            pos = minCell;
            for (var it = new Vector3I_RangeIterator(ref minCell, ref maxCell); it.IsValid(); it.GetNext(out pos))
            {
                m_changedCells.Add(pos);
            }
        }
Exemple #32
0
        private void storage_RangeChangedPlanet(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags dataChanged)
        {
            ProfilerShort.Begin("MyVoxelMap::storage_RangeChanged");
            Vector3I minSector = minChanged / PHYSICS_SECTOR_SIZE_METERS;
            Vector3I maxSector = maxChanged / PHYSICS_SECTOR_SIZE_METERS;

            MyVoxelPhysics voxelMap;

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

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

            OnRangeChanged(minChanged, maxChanged, dataChanged);
            ProfilerShort.End();
        }
        /// <param name="minVoxelChanged">Inclusive min.</param>
        /// <param name="maxVoxelChanged">Inclusive max.</param>
        private void storage_RangeChanged(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags changedData)
        {
            MyPrecalcComponent.AssertUpdateThread();

            ProfilerShort.Begin("MyVoxelGeometry.storage_RangeChanged");

            minChanged -= MyPrecalcComponent.InvalidatedRangeInflate;
            maxChanged += MyPrecalcComponent.InvalidatedRangeInflate;
            m_storage.ClampVoxelCoord(ref minChanged);
            m_storage.ClampVoxelCoord(ref maxChanged);
            var minCellChanged = minChanged >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            var maxCellChanged = maxChanged >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            using (m_lock.AcquireExclusiveUsing())
            {
                if (minCellChanged == Vector3I.Zero && maxCellChanged == m_cellsCount - 1)
                {
                    m_cellsByCoordinate.Clear();
                    m_coordinateToMesh.Clear();
                    m_isEmptyCache.Reset();
                }
                else
                {
                    MyCellCoord cell = new MyCellCoord();
                    cell.CoordInLod = minCellChanged;
                    for (var it = new Vector3I_RangeIterator(ref minCellChanged, ref maxCellChanged); it.IsValid(); it.GetNext(out cell.CoordInLod))
                    {
                        var key = cell.PackId64();
                        m_cellsByCoordinate.Remove(key);
                        m_coordinateToMesh.Remove(key);
                        SetEmpty(ref cell, false);
                    }
                }
            }

            ProfilerShort.End();
        }
            /// <summary>
            /// Checks only immediate children (any deeper would take too long).
            /// </summary>
            private static bool ChildrenWereLoaded(LodLevel childLod, ref MyCellCoord thisLodCell)
            {
                if (childLod == null)
                    return false;

                Debug.Assert(thisLodCell.Lod == childLod.m_lodIndex + 1);

                var childLodCell = new MyCellCoord();
                childLodCell.Lod = childLod.m_lodIndex;
                var shiftToChild = MyVoxelCoordSystems.RenderCellSizeShiftToMoreDetailed(thisLodCell.Lod);
                var start = thisLodCell.CoordInLod << shiftToChild;
                var end = start + ((1 << shiftToChild) >> 1);

                Vector3I.Max(ref childLod.m_lodSizeMinusOne, ref Vector3I.Zero, out childLod.m_lodSizeMinusOne);
                Vector3I.Min(ref end, ref childLod.m_lodSizeMinusOne, out end);
                childLodCell.CoordInLod = start;
                for (var it = new Vector3I_RangeIterator(ref start, ref end);
                    it.IsValid(); it.GetNext(out childLodCell.CoordInLod))
                {
                    var key = childLodCell.PackId64();
                    MyClipmap_CellData data;
                    if (!childLod.m_storedCellData.TryGetValue(key, out data) || !data.WasLoaded)
                    {
                        return false;
                    }
                }

                return true;
            }
            internal void InvalidateRange(Vector3I lodMin, Vector3I lodMax)
            {
  //              MyLog.Default.WriteLine("InvalidateRange Lod: " + m_lodIndex + " Min: " + lodMin + " Max: " + lodMax);

                var cell = new MyCellCoord(m_lodIndex, lodMin);
                for (var it = new Vector3I_RangeIterator(ref lodMin, ref lodMax);
                    it.IsValid(); it.GetNext(out cell.CoordInLod))
                {
                    MyClipmap_CellData data;
                    var id = cell.PackId64();
//                    MyLog.Default.WriteLine("Setting to: m_lodIndex " + cell.Lod + " Coord: " + cell.CoordInLod);


                    if (m_storedCellData.TryGetValue(id, out data))
                    {
                        data.State = CellState.Invalid;
                        //MyLog.Default.WriteLine("Really set to: m_lodIndex " + cell.Lod + " Coord: " + cell.CoordInLod);
                    }

                    if (MyClipmap.UseCache)
                    {
                        var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, id);
                        var cachedCell = MyClipmap.CellsCache.Read(clipmapCellId);
                        if (cachedCell != null)
                        {
                            cachedCell.State = CellState.Invalid;
                        }
                    }
                }
            }
        private void Segment()
        {
            m_segmentation.ClearInput();

            foreach (var block in m_grid.CubeBlocks)
            {
                Vector3I begin = block.Min;
                Vector3I end = block.Max;
                Vector3I pos = begin;
                for (var it = new Vector3I_RangeIterator(ref begin, ref end); it.IsValid(); it.GetNext(out pos))
                    m_segmentation.AddInput(pos);
            }

            var segmentList = m_segmentation.FindSegments(MyVoxelSegmentationType.Simple2);
            m_segments = new List<BoundingBox>(segmentList.Count);
            for (int i = 0; i < segmentList.Count; ++i)
            {
                BoundingBox bb = new BoundingBox();
                bb.Min = (new Vector3(segmentList[i].Min) - Vector3.Half) * m_grid.GridSize - Vector3.Half; // The another half is here to just add some head space
                bb.Max = (new Vector3(segmentList[i].Max) + Vector3.Half) * m_grid.GridSize + Vector3.Half;
                m_segments.Add(bb);
            }

            m_segmentation.ClearInput();
        }
        private MySlimBlock GetBlockInMergeArea()
        {
            Vector3I minI, maxI;
            CalculateMergeArea(out minI, out maxI);

            Vector3I pos = minI;
            for (Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref minI, ref maxI); it.IsValid(); it.GetNext(out pos))
            {
                var block = this.CubeGrid.GetCubeBlock(pos);
                if (block != null)
                    return block;
            }

            return null;
        }
        public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

            for (var itCells = new Vector3I_RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

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

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

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

                voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, ref cellMinCorner, ref cellMaxCorner);
            }
        }
        private void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary<Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> bbList)
        {
            bool useCache = cache != null;
            if (useCache)
                CheckCacheValidity();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                if (generatedMesh != null)
                {
                    ProfilerShort.Begin("Mesh NOT NULL");
                    AddMeshTriangles(generatedMesh, offset, rotation, ownRotation);
                    ProfilerShort.End();
                }
                it.MoveNext();
            }
            ProfilerShort.End();
        }
Exemple #40
0
 public static void GetAllBlocksPositions(HashSet<Tuple<MySlimBlock, ushort?>> blockInCompoundIDs, HashSet<Vector3I> outPositions)
 {
     foreach (var blockInCompoundID in blockInCompoundIDs)
     {
         Vector3I cube = blockInCompoundID.Item1.Min;
         for (Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref blockInCompoundID.Item1.Min, ref blockInCompoundID.Item1.Max); it.IsValid(); it.GetNext(out cube))
         {
             outPositions.Add(cube);
         }
     }
 }
 private static void GetCellCorners(ref Vector3I minCorner, ref Vector3I maxCorner, ref Vector3I_RangeIterator it, out Vector3I cellMinCorner, out Vector3I cellMaxCorner)
 {
     cellMinCorner = new Vector3I(minCorner.X + it.Current.X * CELL_SIZE, minCorner.Y + it.Current.Y * CELL_SIZE, minCorner.Z + it.Current.Z * CELL_SIZE);
     cellMaxCorner = new Vector3I(Math.Min(maxCorner.X, cellMinCorner.X + CELL_SIZE), Math.Min(maxCorner.Y, cellMinCorner.Y + CELL_SIZE), Math.Min(maxCorner.Z, cellMinCorner.Z + CELL_SIZE));
 }
Exemple #42
0
        public void PrefetchShapeOnRay(ref LineD ray)
        {
            Vector3I minCorner, maxCorner;
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref ray.From, out minCorner);
            MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref ray.To, out maxCorner);

            minCorner /= PHYSICS_SECTOR_SIZE_METERS;
            maxCorner /= PHYSICS_SECTOR_SIZE_METERS;

            for (var it = new Vector3I_RangeIterator(ref minCorner, ref maxCorner);
                it.IsValid(); it.MoveNext())
            {
                if (m_physicsShapes.ContainsKey(it.Current))
                {
                    m_physicsShapes[it.Current].PrefetchShapeOnRay(ref ray);
                }
            }
        }
        protected override void Init(MyObjectBuilder_DefinitionBase ob)
        {
            base.Init(ob);

            var objectBuilder = ob as MyObjectBuilder_BlockNavigationDefinition;
            Debug.Assert(ob != null);
            if (ob == null) return;

            if (objectBuilder.NoEntry || objectBuilder.Triangles == null)
            {
                NoEntry = true;
            }
            else
            {
                NoEntry = false;
                var newMesh = new MyGridNavigationMesh(null, null, objectBuilder.Triangles.Length);

                Vector3I maxPos = objectBuilder.Size - Vector3I.One - objectBuilder.Center;
                Vector3I minPos = - (Vector3I)(objectBuilder.Center);

                foreach (var triOb in objectBuilder.Triangles)
                {
                    Vector3 pa = (Vector3)triOb.Points[0];
                    Vector3 pb = (Vector3)triOb.Points[1];
                    Vector3 pc = (Vector3)triOb.Points[2];

                    var tri = newMesh.AddTriangle(ref pa, ref pb, ref pc);

                    var center = (pa + pb + pc) / 3.0f;

                    // We want to move the triangle vertices more towards the triangle center to ensure correct calculation of containing cube
                    Vector3 cvA = (center - pa) * 0.0001f;
                    Vector3 cvB = (center - pb) * 0.0001f;
                    Vector3 cvC = (center - pc) * 0.0001f;
                    Vector3I gridPosA = Vector3I.Round(pa + cvA);
                    Vector3I gridPosB = Vector3I.Round(pb + cvB);
                    Vector3I gridPosC = Vector3I.Round(pc + cvC);
                    Vector3I.Clamp(ref gridPosA, ref minPos, ref maxPos, out gridPosA);
                    Vector3I.Clamp(ref gridPosB, ref minPos, ref maxPos, out gridPosB);
                    Vector3I.Clamp(ref gridPosC, ref minPos, ref maxPos, out gridPosC);
                    Vector3I min, max;
                    Vector3I.Min(ref gridPosA, ref gridPosB, out min);
                    Vector3I.Min(ref min, ref gridPosC, out min);
                    Vector3I.Max(ref gridPosA, ref gridPosB, out max);
                    Vector3I.Max(ref max, ref gridPosC, out max);

                    Vector3I pos = min;
                    for (var it = new Vector3I_RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos))
                    {
                        newMesh.RegisterTriangle(tri, ref pos);
                    }
                }

                m_mesh = newMesh;
            }
        }
        private void FindForestInitialCandidate()
        {
            BoundingBoxD groundBox = m_ground.PositionComp.WorldAABB;
            Vector3D boxSize = groundBox.Size;
            boxSize *= 0.1f;
            groundBox.Inflate(-boxSize);
            MyBBSetSampler sampler = new MyBBSetSampler(groundBox.Min, groundBox.Max);

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

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

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

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

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

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

                    it.MoveNext();
                }
            }
        }
        public void TestVoxelNavmeshTriangle(ref Vector3D a, ref Vector3D b, ref Vector3D c, List<MyCubeGrid> gridsToTest, List<MyGridPathfinding.CubeId> linkCandidatesOutput, out bool intersecting)
        {
            ProfilerShort.Begin("TestVoxelNavmeshTriangle");

            ProfilerShort.Begin("Triangle-obstacle tests");
            Vector3D s = (a + b + c) / 3.0;
            if (m_obstacles.IsInObstacle(s))
            {
                intersecting = true;
                ProfilerShort.End();
                ProfilerShort.End();
                return;
            }
            ProfilerShort.End();

            BoundingBoxD triBB;
            Vector3D aLocal, bLocal, cLocal, gLocal;
            Vector3D g = Vector3D.Zero;
            if (MyPerGameSettings.NavmeshPresumesDownwardGravity)
            {
                g = Vector3.Down * 2.0f;
            }

            m_tmpLinkCandidates.Clear();

            intersecting = false;
            foreach (var grid in gridsToTest)
            {
                MatrixD mat = grid.PositionComp.WorldMatrixNormalizedInv;

                Vector3D.Transform(ref a, ref mat, out aLocal);
                Vector3D.Transform(ref b, ref mat, out bLocal);
                Vector3D.Transform(ref c, ref mat, out cLocal);
                Vector3D.TransformNormal(ref g, ref mat, out gLocal);

                triBB = new BoundingBoxD(Vector3D.MaxValue, Vector3D.MinValue);
                triBB.Include(ref aLocal, ref bLocal, ref cLocal);
                
                Vector3I min = grid.LocalToGridInteger(triBB.Min);
                Vector3I max = grid.LocalToGridInteger(triBB.Max);
                Vector3I pos = min - Vector3I.One;
                Vector3I max2 = max + Vector3I.One;
                for (var it = new Vector3I_RangeIterator(ref pos, ref max2); it.IsValid(); it.GetNext(out pos))
                {
                    if (grid.GetCubeBlock(pos) != null)
                    {
                        Vector3 largeMin = (pos - Vector3.One) * grid.GridSize;
                        Vector3 largeMax = (pos + Vector3.One) * grid.GridSize;
                        Vector3 smallMin = (pos - Vector3.Half) * grid.GridSize;
                        Vector3 smallMax = (pos + Vector3.Half) * grid.GridSize;
                        BoundingBoxD largeBb = new BoundingBoxD(largeMin, largeMax);
                        BoundingBoxD bb = new BoundingBoxD(smallMin, smallMax);

                        largeBb.Include(largeMin + gLocal);
                        largeBb.Include(largeMax + gLocal);
                        bb.Include(smallMin + gLocal);
                        bb.Include(smallMax + gLocal);

                        ProfilerShort.Begin("Triangle intersection tests");
                        if (largeBb.IntersectsTriangle(ref aLocal, ref bLocal, ref cLocal))
                        {
                            if (bb.IntersectsTriangle(ref aLocal, ref bLocal, ref cLocal))
                            {
                                intersecting = true;
                                ProfilerShort.End();
                                break;
                            }
                            else
                            {
                                int dx = Math.Min(Math.Abs(min.X - pos.X), Math.Abs(max.X - pos.X));
                                int dy = Math.Min(Math.Abs(min.Y - pos.Y), Math.Abs(max.Y - pos.Y));
                                int dz = Math.Min(Math.Abs(min.Z - pos.Z), Math.Abs(max.Z - pos.Z));
                                if ((dx + dy + dz) < 3)
                                    m_tmpLinkCandidates.Add(new MyGridPathfinding.CubeId() { Grid = grid, Coords = pos });
                            }
                        }
                        ProfilerShort.End();
                    }
                }

                if (intersecting) break;
            }

            if (!intersecting)
            {
                for (int i = 0; i < m_tmpLinkCandidates.Count; ++i)
                {
                    linkCandidatesOutput.Add(m_tmpLinkCandidates[i]);
                }
            }
            m_tmpLinkCandidates.Clear();

            ProfilerShort.End();
        }
        protected override MyProceduralCell GenerateProceduralCell(ref VRageMath.Vector3I cellId)
        {
            MyProceduralCell cell = new MyProceduralCell(cellId, this.CELL_SIZE);
            ProfilerShort.Begin("GenerateObjectSeedsCell");

            IMyModule densityFunctionFilled = GetCellDensityFunctionFilled(cell.BoundingVolume);
            if (densityFunctionFilled == null)
            {
                ProfilerShort.End();
                return null;
            }
            IMyModule densityFunctionRemoved = GetCellDensityFunctionRemoved(cell.BoundingVolume);

            int cellSeed = GetCellSeed(ref cellId);
            var random = MyRandom.Instance;
            using (random.PushSeed(cellSeed))
            {
                int index = 0;
                Vector3I subCellId = Vector3I.Zero;
                Vector3I max = new Vector3I(SUBCELLS - 1);
                for (var iter = new Vector3I_RangeIterator(ref Vector3I.Zero, ref max); iter.IsValid(); iter.GetNext(out subCellId))
                {
                    // there is a bug in the position calculation which can very rarely cause overlaping objects but backwards compatibility so meh
                    Vector3D position = new Vector3D(random.NextDouble(), random.NextDouble(), random.NextDouble());
                    position += (Vector3D)subCellId / SUBCELL_SIZE;
                    position += cellId;
                    position *= CELL_SIZE;

                    if (!MyEntities.IsInsideWorld(position))
                    {
                        continue;
                    }

                    ProfilerShort.Begin("Density functions");
                    double valueRemoved = -1;
                    if (densityFunctionRemoved != null)
                    {
                        valueRemoved = densityFunctionRemoved.GetValue(position.X, position.Y, position.Z);

                        if (valueRemoved <= -1)
                        {
                            ProfilerShort.End();
                            continue;
                        }
                    }

                    var valueFilled = densityFunctionFilled.GetValue(position.X, position.Y, position.Z);

                    if (densityFunctionRemoved != null)
                    {
                        if (valueRemoved < valueFilled)
                        {
                            ProfilerShort.End();
                            continue;
                        }
                    }
                    ProfilerShort.End();

                    if (valueFilled < m_objectDensity) // -1..+1
                    {
                        var objectSeed = new MyObjectSeed(cell, position, GetObjectSize(random.NextDouble()));
                        objectSeed.Params.Type = GetSeedType(random.NextDouble());
                        objectSeed.Params.Seed = random.Next();
                        objectSeed.Params.Index = index++;

                        GenerateObject(cell, objectSeed, ref index, random, densityFunctionFilled, densityFunctionRemoved);
                    }
                }
            }

            ProfilerShort.End();
            return cell;
        }
        //[Conditional("DEBUG")]
        private void FixCacheMaterial(Vector3I voxelStart, Vector3I voxelEnd)
        {
            var mcount = Sandbox.Definitions.MyDefinitionManager.Static.VoxelMaterialCount;
            voxelEnd = Vector3I.Min(voxelEnd - voxelStart, m_cache.Size3D);
            voxelStart = Vector3I.Zero;
            var it = new Vector3I_RangeIterator(ref voxelStart, ref voxelEnd);
            var pos = it.Current;
            for (; it.IsValid(); it.GetNext(out pos))
            {
                var lin = m_cache.ComputeLinear(ref pos);
                var mat = m_cache.Material(lin);

                if (mat >= mcount && mat != MyVoxelConstants.NULL_MATERIAL)
                {
                    //Debug.Fail(String.Format("VoxelData contains invalid materials (id: {0}).", m_cache.Material(lin)));
                    m_cache.Material(lin, MyVoxelConstants.NULL_MATERIAL);
                }
            }
        }
        public void ProcessChangedCellComponents()
        {
            ProfilerShort.Begin("ProcessChangedCellComponents");

            m_currentHelper = this;

            Vector3I min, max, pos;
            List<int> triangles = null;
            foreach (var cell in m_changedCells)
            {
                min = CellToLowestCube(cell);
                max = min + m_cellSize - Vector3I.One;

                // Save a hashset of all the triangles in the current cell
                pos = min;
                for (var it = new Vector3I_RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos))
                {
                    if (!m_triangleRegistry.TryGetValue(pos, out triangles)) continue;

                    foreach (var triIndex in triangles)
                    {
                        m_tmpCellTriangles.Add(triIndex);
                    }
                }

                if (m_tmpCellTriangles.Count == 0) continue;

                MyCellCoord cellCoord = new MyCellCoord(0, cell);
                ulong packedCell = cellCoord.PackId64();
                m_components.OpenCell(packedCell);

                long timeBegin = m_mesh.GetCurrentTimestamp() + 1;
                long timeEnd = timeBegin;
                m_currentComponentRel = 0;

                m_tmpComponentTriangles.Clear();
                foreach (var triIndex in m_tmpCellTriangles)
                {
                    // Skip already visited triangles
                    var triangle = m_mesh.GetTriangle(triIndex);
                    if (m_currentComponentRel != 0 && m_mesh.VisitedBetween(triangle, timeBegin, timeEnd)) continue;

                    m_components.OpenComponent();

                    // Make sure we have place in m_currentCellConnections
                    if (m_currentComponentRel >= m_currentCellConnections.Count)
                    {
                        m_currentCellConnections.Add(new List<int>());
                    }

                    // Find connected component from an unvisited triangle and mark its connections
                    m_components.AddComponentTriangle(triangle, triangle.Center);
                    triangle.ComponentIndex = m_currentComponentRel;
                    m_tmpComponentTriangles.Add(triangle);
                    m_mesh.PrepareTraversal(triangle, null, m_processTrianglePredicate);
                    m_mesh.PerformTraversal();
                    m_tmpComponentTriangles.Add(null);

                    m_components.CloseComponent();

                    timeEnd = m_mesh.GetCurrentTimestamp();
                    if (m_currentComponentRel == 0)
                    {
                        timeBegin = timeEnd;
                    }
                    m_currentComponentRel++;
                }

                m_tmpCellTriangles.Clear();

                MyNavmeshComponents.ClosedCellInfo cellInfo = new MyNavmeshComponents.ClosedCellInfo();
                m_components.CloseAndCacheCell(ref cellInfo);

                // Renumber triangles from the old indices to the newly assigned index from m_components
                int componentIndex = cellInfo.StartingIndex;
                foreach (var triangle in m_tmpComponentTriangles)
                {
                    if (triangle == null)
                    {
                        componentIndex++;
                        continue;
                    }
                    triangle.ComponentIndex = componentIndex;
                }
                m_tmpComponentTriangles.Clear();

                // Remove old component primitives
                if (!cellInfo.NewCell && cellInfo.ComponentNum != cellInfo.OldComponentNum)
                {
                    for (int i = 0; i < cellInfo.OldComponentNum; ++i)
                    {
                        m_mesh.HighLevelGroup.RemovePrimitive(cellInfo.OldStartingIndex + i);
                    }
                }

                // Add new component primitives
                if (cellInfo.NewCell || cellInfo.ComponentNum != cellInfo.OldComponentNum)
                {
                    for (int i = 0; i < cellInfo.ComponentNum; ++i)
                    {
                        m_mesh.HighLevelGroup.AddPrimitive(cellInfo.StartingIndex + i, m_components.GetComponentCenter(i));
                    }
                }

                // Update existing component primitives
                if (!cellInfo.NewCell && cellInfo.ComponentNum == cellInfo.OldComponentNum)
                {
                    for (int i = 0; i < cellInfo.ComponentNum; ++i)
                    {
                        var primitive = m_mesh.HighLevelGroup.GetPrimitive(cellInfo.StartingIndex + i);
                        primitive.UpdatePosition(m_components.GetComponentCenter(i));
                    }
                }

                // Connect new components with the others in the neighboring cells
                for (int i = 0; i < cellInfo.ComponentNum; ++i)
                {
                    int compIndex = cellInfo.StartingIndex + i;

                    var primitive = m_mesh.HighLevelGroup.GetPrimitive(compIndex);
                    primitive.GetNeighbours(m_tmpNeighbors);

                    // Connect to disconnected components
                    foreach (var connection in m_currentCellConnections[i])
                    {
                        if (!m_tmpNeighbors.Remove(connection))
                        {
                            m_mesh.HighLevelGroup.ConnectPrimitives(compIndex, connection);
                        }
                    }

                    // Disconnect neighbors that should be no longer connected
                    foreach (var neighbor in m_tmpNeighbors)
                    {
                        // Only disconnect from the other cell if it is expanded and there was no connection found
                        var neighborPrimitive = m_mesh.HighLevelGroup.TryGetPrimitive(neighbor);
                        if (neighborPrimitive != null && neighborPrimitive.IsExpanded)
                        {
                            m_mesh.HighLevelGroup.DisconnectPrimitives(compIndex, neighbor);
                        }
                    }

                    m_tmpNeighbors.Clear();
                    m_currentCellConnections[i].Clear();
                }

                // Set all the components as expanded
                for (int i = 0; i < cellInfo.ComponentNum; ++i)
                {
                    componentIndex = cellInfo.StartingIndex + i;
                    var component = m_mesh.HighLevelGroup.GetPrimitive(componentIndex);
                    if (component != null)
                    {
                        component.IsExpanded = true;
                    }
                }
            }

            m_changedCells.Clear();

            m_currentHelper = null;

            ProfilerShort.End();
        }
        public static ulong FillInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx)
        {
            Vector3I minCorner, maxCorner, numCells;
            ulong retValue = 0;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);

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

            for (var itCells = new Vector3I_RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

                Vector3I originalMinCorner = cellMinCorner;
                Vector3I originalMaxCorner = cellMaxCorner;

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

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

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

                ulong filledSum = 0;

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

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

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

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


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

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

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

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

                retValue += filledSum;
            }

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

            return retValue;
        }
        public void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged)
        {
            minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate + 1;
            maxVoxelChanged += MyPrecalcComponent.InvalidatedRangeInflate + 1;
            m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged);
            m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged);

            Vector3I minCellLod0, maxCellLod0;
            minVoxelChanged -= m_voxelMap.StorageMin;
            maxVoxelChanged -= m_voxelMap.StorageMin;

            MyVoxelCoordSystems.VoxelCoordToRenderCellCoord(0, ref minVoxelChanged, out minCellLod0);
            MyVoxelCoordSystems.VoxelCoordToRenderCellCoord(0, ref maxVoxelChanged, out maxCellLod0);

            MyRenderProxy.InvalidateClipmapRange(m_renderObjectIDs[0], minCellLod0, maxCellLod0);

            if (minCellLod0 == Vector3I.Zero &&
                maxCellLod0 == ((m_voxelMap.Storage.Size - 1) >> MyVoxelCoordSystems.RenderCellSizeInLodVoxelsShift(0)))
            {
                m_renderWorkTracker.InvalidateAll();
                m_mergeWorkTracker.InvalidateAll();
            }
            else
            {
                for (int i = 0; i < MyCellCoord.MAX_LOD_COUNT; ++i)
                {
                    var minCell = minCellLod0 >> i;
                    var maxCell = maxCellLod0 >> i;
                    var cellCoord = new MyCellCoord(i, ref minCell);
                    for (var it = new Vector3I_RangeIterator(ref minCell, ref maxCell);
                        it.IsValid(); it.GetNext(out cellCoord.CoordInLod))
                    {
                        m_renderWorkTracker.Invalidate(cellCoord.PackId64());
                        m_mergeWorkTracker.Invalidate(cellCoord.PackId64());
                    }
                }
            }
        }
        public static ulong CutOutShape(MyVoxelBase voxelMap, MyShape shape)
        {
            if(MySession.Static.EnableVoxelDestruction == false)
            {
                return 0;
            }

            Vector3I minCorner, maxCorner, numCells;
            GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells);
            ulong changedVolumeAmount = 0;

            for (var itCells = new Vector3I_RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext())
            {
                Vector3I cellMinCorner, cellMaxCorner;
                GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner);

                var cacheMin = cellMinCorner - 1;
                var cacheMax = cellMaxCorner + 1;
                voxelMap.Storage.ClampVoxelCoord(ref cacheMin);
                voxelMap.Storage.ClampVoxelCoord(ref cacheMax);

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

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

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

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

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

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

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

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

                changedVolumeAmount += removedSum;
            }

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

            return changedVolumeAmount;
        }
Exemple #52
0
        private void GeneratePhysicalShapeForBox(ref Vector3I increment, ref BoundingBoxD shapeBox)
        {
            if (!shapeBox.Intersects(PositionComp.WorldAABB))
                return;

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

            minCorner /= PHYSICS_SECTOR_SIZE_METERS;
            maxCorner /= PHYSICS_SECTOR_SIZE_METERS;

            for (var it = new Vector3I_RangeIterator(ref minCorner, ref maxCorner);
                it.IsValid(); it.MoveNext())
            {
                ProfilerShort.Begin("Myplanet::create physics shape");
                CreateVoxelPhysics(ref increment, ref it);
                ProfilerShort.End();
            }
        }
        private void LoadBlocks(GridSimulationData simData)
        {
            simData.BlockCount = m_grid.GetBlocks().Count;

            simData.All.Clear();
            simData.DynamicBlocks.Clear();
            simData.StaticBlocks.Clear();

            using (Stats.Timing.Measure("SI - Collect", VRage.Stats.MyStatTypeEnum.Sum | VRage.Stats.MyStatTypeEnum.DontDisappearFlag))
            {
                // Store blocks
                foreach (var block in m_grid.GetBlocks())
                {
                    if (simData.All.ContainsKey(block.Position))
                    {
                        Debug.Fail("Same blocks in grid!");
                        continue;
                    }

                    bool isStatic = m_grid.Physics.Shape.BlocksConnectedToWorld.Contains(block.Position);

                    if (isStatic)
                    {
                        var n = new Node(block.Position, true);
                        n.PhysicalMaterial = block.BlockDefinition.PhysicalMaterial;
                        simData.StaticBlocks.Add(n);
                        simData.All.Add(block.Position, n);
                    }
                    else 
                    {
                        

                        float mass = m_grid.Physics.Shape.GetBlockMass(block.Position);
                        var cubeMass = MassToSI(mass);

                        var physicalMaterial = block.BlockDefinition.PhysicalMaterial;
                        if (block.FatBlock is MyCompoundCubeBlock)
                        {
                            var compBlock = block.FatBlock as MyCompoundCubeBlock;

                            physicalMaterial = compBlock.GetBlocks().First().BlockDefinition.PhysicalMaterial;

                            //Simulate blocks where or pieces are generated
                            bool allAreGenerated = true;
                            foreach (var b in compBlock.GetBlocks())
                            {
                                if (!b.BlockDefinition.IsGeneratedBlock)
                                {
                                    allAreGenerated = false;
                                    break;
                                }
                            }

                            bool isGenerated = true;
                            foreach (var b in compBlock.GetBlocks())
                            {
                                if (!b.BlockDefinition.IsGeneratedBlock)
                                {
                                    isGenerated = false;
                                    break;
                                }
                                else
                                    if (b.BlockDefinition.IsGeneratedBlock && b.BlockDefinition.PhysicalMaterial.Id.SubtypeName == "Stone")
                                    {
                                        isGenerated = false;
                                        break;
                                    }
                                    else
                                        if (b.BlockDefinition.IsGeneratedBlock && b.BlockDefinition.PhysicalMaterial.Id.SubtypeName == "RoofTile" && allAreGenerated)
                                        {
                                            isGenerated = false;
                                            cubeMass *= 6f;
                                            break;
                                        }
                                        else
                                            if (b.BlockDefinition.IsGeneratedBlock && b.BlockDefinition.PhysicalMaterial.Id.SubtypeName == "RoofWood" && allAreGenerated)
                                            {
                                                isGenerated = false;
                                                cubeMass *= 3f;
                                                break;
                                            }
                                            else
                                                if (b.BlockDefinition.IsGeneratedBlock && b.BlockDefinition.PhysicalMaterial.Id.SubtypeName == "RoofHay" && allAreGenerated)
                                                {
                                                    isGenerated = false;
                                                    cubeMass *= 1.2f;
                                                    break;
                                                }
                                                else
                                                {
                                                }
                            }

                            //we dont want to simulate these pieces..
                            if (isGenerated)
                                continue;
                        }

                        Vector3I pos = block.Min;
                        float volumeRecip = 1.0f / block.BlockDefinition.Size.Size;
                        for (var it = new Vector3I_RangeIterator(ref block.Min, ref block.Max); it.IsValid(); it.GetNext(out pos))
                        {
                            var node = new Node(pos, false);

                            node.Mass = cubeMass * volumeRecip;

                            node.PhysicalMaterial = physicalMaterial;

                            simData.DynamicBlocks.Add(node);
                            simData.All.Add(pos, node);
                        }
                    }
                }

                foreach (var block in simData.DynamicWeights)
                {
                    if (simData.All.ContainsKey(block.Key))
                    {
                        simData.All[block.Key].Mass += block.Value;
                    }
                    else
                    {
                        var node = new Node(block.Key, false);
                        node.Mass = simData.DynamicWeights[block.Key];
                        node.IsDynamicWeight = true;
                        simData.DynamicBlocks.Add(node);
                        simData.All.Add(block.Key, node);
                    }
                }
            }

            m_grid.Physics.ContactPointCallback -= Physics_ContactPointCallback;
            m_grid.Physics.ContactPointCallback += Physics_ContactPointCallback;

            AddNeighbours(simData);
        }
        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();
        }
 void IMyOctreeLeafNode.WriteRange(MyStorageData source, ref Vector3I readOffset, ref Vector3I min, ref Vector3I max)
 {
     m_octree.WriteRange(source, m_dataType, ref readOffset, ref min, ref max);
     if (DEBUG_WRITES)
     {
         var tmp = new MyStorageData();
         tmp.Resize(min, max);
         m_octree.ReadRange(tmp, m_dataType, ref Vector3I.Zero, 0, ref min, ref max);
         Vector3I p = Vector3I.Zero;
         var cacheEnd = max - min;
         int errorCounter = 0;
         for (var it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref cacheEnd);
             it.IsValid(); it.GetNext(out p))
         {
             var read = readOffset + p;
             if (source.Get(m_dataType, ref read) != tmp.Get(m_dataType, ref p))
                 ++errorCounter;
         }
         Debug.Assert(errorCounter == 0, string.Format("{0} errors writing to leaf octree.", errorCounter));
     }
 }
        internal void GenerateAllShapes()
        {
            if (!m_bodiesInitialized) CreateRigidBodies();

            var min = Vector3I.Zero;

            Vector3I storageSize = m_voxelMap.Size;
            Vector3I max = new Vector3I(0, 0, 0);
            max.X = storageSize.X >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            max.Y = storageSize.Y >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
            max.Z = storageSize.Z >> MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;

            max += min;

            var args = new MyPrecalcJobPhysicsPrefetch.Args
            {
                GeometryCell = new MyCellCoord(1, min),
                Storage = m_voxelMap.Storage,
                TargetPhysics = this,
                Tracker = m_workTracker
            };
            for (var it = new Vector3I_RangeIterator(ref min, ref max);
                it.IsValid();
                it.GetNext(out args.GeometryCell.CoordInLod))
            {
                MyPrecalcJobPhysicsPrefetch.Start(args);
            }
        }
        private MyShipMergeBlock GetOtherMergeBlock()
        {
            Vector3I minI, maxI;
            CalculateMergeArea(out minI, out maxI);

            Vector3I pos = minI;
            for (Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref minI, ref maxI); it.IsValid(); it.GetNext(out pos))
            {
                var block = this.CubeGrid.GetCubeBlock(pos);
                if (block != null && block.FatBlock != null)
                {
                    var mergeBlock = block.FatBlock as MyShipMergeBlock;
                    if (mergeBlock == null) continue;

                    Vector3I otherMinI, otherMaxI;
                    mergeBlock.CalculateMergeArea(out otherMinI, out otherMaxI);
                    Vector3I faceNormal = Base6Directions.GetIntVector(this.Orientation.TransformDirection(m_forward));

                    // Bounding box test of minI <-> maxI and otherMinI(shifted by faceNormal) <-> otherMaxI(shifted by faceNormal)
                    otherMinI = maxI - (otherMinI + faceNormal);
                    otherMaxI = otherMaxI + faceNormal - minI;
                    if (otherMinI.X < 0) continue;
                    if (otherMinI.Y < 0) continue;
                    if (otherMinI.Z < 0) continue;
                    if (otherMaxI.X < 0) continue;
                    if (otherMaxI.Y < 0) continue;
                    if (otherMaxI.Z < 0) continue;

                    return mergeBlock;
                }
            }

            return null;
        }
        public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck, bool adviceCache = false)
        {

            m_resultVerticesCounter = 0;
            m_resultTrianglesCounter = 0;
            m_edgeVertexCalcCounter++;
            m_temporaryVoxelsCounter++;            

            CalcPolygCubeSize(lod, storage.Size);

            m_voxelStart = voxelStart;
            //voxelStart = voxelStart;
            //voxelEnd = voxelEnd;
            var ssize = storage.Size;
            m_cache.Resize(voxelStart, voxelEnd);

            // Load content first, check it if it contains isosurface, early exit if it doesn't.
            storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd);

            if (!m_cache.ContainsIsoSurface())
                return null;

            storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, lod, ref voxelStart, ref voxelEnd);

            ProfilerShort.Begin("Marching cubes");
            {
                //  Size of voxel or cell (in meters) and size of voxel map / voxel cells
                ComputeSizeAndOrigin(lod, storage.Size);


                var start = Vector3I.Zero;
                var end = voxelEnd - voxelStart - 3;
                Vector3I coord0 = start;


                for (var it = new Vector3I_RangeIterator(ref start, ref end); it.IsValid(); it.GetNext(out coord0))
                {
                    int cubeIndex = 0;
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 1;
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 2;
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 4;
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 0, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 8;
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 16;
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 0) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 32;
                    if (m_cache.Content(coord0.X + 1, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 64;
                    if (m_cache.Content(coord0.X + 0, coord0.Y + 1, coord0.Z + 1) < MyVoxelConstants.VOXEL_ISO_LEVEL) cubeIndex |= 128;

                    //  Cube is entirely in/out of the surface
                    if (MyMarchingCubesConstants.EdgeTable[cubeIndex] == 0)
                    {
                        continue;
                    }

                    //  We can get this voxel content right from cache (not using GetVoxelContent method), because after CopyVoxelContents these array must be filled. But only content, not material, normal, etc.
                    Vector3I tempVoxelCoord0 = ComputeTemporaryVoxelData(m_cache, ref coord0, cubeIndex, lod);

                    //  Create the triangles
                    CreateTriangles(ref coord0, cubeIndex, ref tempVoxelCoord0);
                }
            }
            ProfilerShort.End();


            double numCellsHalf = 0.5f * (m_cache.Size3D.X);
            var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod);
            var vertexCellOffset = voxelStart - AffectedRangeOffset;

            IMyIsoMesherOutputBuffer isomesh = new MyIsoMesh();


            for (int i = 0; i < m_resultVerticesCounter; i++)
            {
                var pos = (m_resultVertices[i].Position - (Vector3)storage.Size / 2) / storage.Size;                
                m_resultVertices[i].Position = pos;
                m_resultVertices[i].PositionMorph = pos;
                m_resultVertices[i].NormalMorph = m_resultVertices[i].Normal;
                m_resultVertices[i].MaterialMorph = m_resultVertices[i].Material;
                m_resultVertices[i].AmbientMorph = m_resultVertices[i].Ambient;
            }

            for (int i = 0; i < m_resultVerticesCounter; i++)
            {
                isomesh.WriteVertex(ref m_resultVertices[i].Cell, ref m_resultVertices[i].Position, ref m_resultVertices[i].Normal, (byte)m_resultVertices[i].Material, m_resultVertices[i].Ambient);
            }

            for (int i = 0; i < m_resultTrianglesCounter; i++)
            {
                isomesh.WriteTriangle(m_resultTriangles[i].VertexIndex0, m_resultTriangles[i].VertexIndex1, m_resultTriangles[i].VertexIndex2);
            }

            var mIsoMesh = (MyIsoMesh)isomesh;
            mIsoMesh.PositionOffset = storage.Size / 2;
            mIsoMesh.PositionScale = storage.Size;
            mIsoMesh.CellStart = voxelStart;
            mIsoMesh.CellEnd = voxelEnd;

            var vertexCells = mIsoMesh.Cells.GetInternalArray();
            for (int i = 0; i < mIsoMesh.VerticesCount; i++)
            {
                vertexCells[i] += vertexCellOffset;
            }

            return (MyIsoMesh)isomesh;
        }
            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();
                }
            }
Exemple #60
0
        private MyVoxelPhysics CreateVoxelPhysics(ref Vector3I increment, ref Vector3I_RangeIterator it)
        {
            if (m_physicsShapes == null)
            {
                m_physicsShapes = new Dictionary<Vector3I, MyVoxelPhysics>();
            }

            MyVoxelPhysics voxelMap = null;
            if (!m_physicsShapes.TryGetValue(it.Current, out voxelMap))
            {
                Vector3I storageMin = it.Current * increment;
                Vector3I storageMax = storageMin + increment;

                BoundingBox check = new BoundingBox(storageMin, storageMax);

                if (Storage.Intersect(ref check, false) == ContainmentType.Intersects)
                {
                    voxelMap = new MyVoxelPhysics();

                    voxelMap.Init(m_storage,
                        this.PositionLeftBottomCorner + storageMin * MyVoxelConstants.VOXEL_SIZE_IN_METRES, storageMin,
                        storageMax, this);
                    voxelMap.Save = false;
                    MyEntities.Add(voxelMap);
                }

                m_physicsShapes.Add(it.Current, voxelMap);
            }
            return voxelMap;
        }