Beispiel #1
0
 public float DistanceSquared(ref Vector3Int otherVector)
 {
     var dX = otherVector.X - X;
     var dY = otherVector.X - X;
     var dZ = otherVector.X - X;
     return dX * dX + dY * dY + dZ * dZ;
 }
 public FluidContainer(MappingFunction mappingFunction, Block[] blocks, FluidCell solidCellReference)
 {
     m_mappingFunction = mappingFunction;
     m_blocks = blocks;
     m_solidCellReference = solidCellReference;
     Update = true;
     Alive = true;
     m_min = new Vector3Int(int.MaxValue, int.MaxValue, int.MaxValue);
     m_max = new Vector3Int(-int.MaxValue, -int.MaxValue, -int.MaxValue);
     Cells = new List<FluidCell>();
     CellDictionary = new Dictionary<long, FluidCell>();
     Updated = new List<FluidCell>();
 }
Beispiel #3
0
        public CloudTarget(Vector3Int position, int sizeX, int sizeY, int sizeZ, int renderScale)
        {
            // calculate the real world position.
            Position = position;

            // calculate bounding-box.
            BoundingBox = new BoundingBox(new Vector3(Position.X, Position.Y, Position.Z),
                new Vector3(Position.X + sizeX, Position.Y + sizeY,
                    Position.Z + sizeZ));

            RenderingBoundingBox = new BoundingBox(new Vector3(Position.X, Position.Y, Position.Z),
               new Vector3(Position.X + sizeX * renderScale, Position.Y + sizeY * renderScale,
                   Position.Z + sizeZ * renderScale));
        }
 public abstract void RemoveBlock(Vector3Int position);
 //TODO : break this out into sub functions
 public void Step()
 {
     foreach (var cell in Cells)
     {
         if (cell.Awake && cell.Type == FluidCell.CellType.Water) //In theory this check is redundant...
         {
             cell.Propagate();
         }
     }
     var hasChanged = false;
     var potentialPruningNeeded = false;
     foreach (var cell in Updated)
     {
         if (cell.Type == FluidCell.CellType.Solid)
         {
             hasChanged = true;
             potentialPruningNeeded = true;
         }
         if (Math.Abs(cell.Level - cell.LevelNextStep) >= FluidCell.MinFlow / 2.0f)
         {
             hasChanged = true;
             cell.Awake = true;
         }
         cell.Level = cell.LevelNextStep;
         if (cell.Type == FluidCell.CellType.Water && cell.Level < FluidCell.MinLevel)
         {
             potentialPruningNeeded = true;
             cell.Type = FluidCell.CellType.Air;
         }
         if (!(cell.Type == FluidCell.CellType.Air && cell.Level > FluidCell.MinLevel))
         {
             continue;
         }
         cell.Type = FluidCell.CellType.Water;
         RecalculateBounds(cell);
         BuildNeighborhood(cell);
         Cells.Add(cell);
     }
     Updated.Clear();
     if (potentialPruningNeeded)
     {
         m_min = new Vector3Int(int.MaxValue, int.MaxValue, int.MaxValue);
         m_max = new Vector3Int(-int.MaxValue, -int.MaxValue, -int.MaxValue);
         var removeList = new List<FluidCell>();
         foreach (var cell in Cells)
         {
             if (cell.Type == FluidCell.CellType.Solid ||
                 cell.Type == FluidCell.CellType.Air)
             {
                 removeList.Add(cell);
             }
             else
             {
                 RecalculateBounds(cell);
             }
         }
         foreach (var cell in removeList)
         {
             Cells.Remove(cell);
             if ((cell.Up != null && cell.Up.Type == FluidCell.CellType.Water) ||
                 (cell.North != null && cell.North.Type == FluidCell.CellType.Water) ||
                 (cell.East != null && cell.East.Type == FluidCell.CellType.Water) ||
                 (cell.South != null && cell.South.Type == FluidCell.CellType.Water) ||
                 (cell.West != null && cell.West.Type == FluidCell.CellType.Water) ||
                 (cell.Down != null && cell.Down.Type == FluidCell.CellType.Water))
             {
                 continue;
             }
             var cellHash = m_mappingFunction(cell.X, cell.Y, cell.Z);
             CellDictionary.Remove(cellHash);
         }
     }
     Alive = Cells.Count != 0;
     Update = hasChanged;
 }
Beispiel #6
0
 public VisibilityTraceNode(Vector3Int position, int index)
 {
     Position = position;
     Index = index;
 }
Beispiel #7
0
 private int IterateOnFace(FaceDirection direction, ref Vector3Int index)
 {
     int i1;
     switch(direction)
     {
         case FaceDirection.XIncreasing:
         case FaceDirection.XDecreasing:
             i1 = index.Y;
             index.Y = (i1 + 1) % SizeInBlocks;
             if(index.Y < i1)
             {
                 index.Z = (index.Z + 1) % SizeInBlocks;
             }
             break;
         case FaceDirection.YIncreasing:
         case FaceDirection.YDecreasing:
             i1 = index.X;
             index.X = (i1 + 1) % SizeInBlocks;
             if(index.X < i1)
             {
                 index.Z = (index.Z + 1) % SizeInBlocks;
             }
             break;
         case FaceDirection.ZIncreasing:
         case FaceDirection.ZDecreasing:
             i1 = index.Y;
             index.Y = (i1 + 1) % SizeInBlocks;
             if(index.Y < i1)
             {
                 index.X = (index.X + 1) % SizeInBlocks;
             }
             break;
     }
     return m_mappingFunction(index.X, index.Y, index.Z);
 }
Beispiel #8
0
 private void RecacheChunks()
 {
     foreach (var chunk in m_chunkStorage.Values.Where(chunk => !IsInCacheRange(chunk)))
     {
         m_chunkStorage.Remove(chunk.ChunkCachePosition.X, chunk.ChunkCachePosition.Y, chunk.ChunkCachePosition.Z);
         chunk.PrepForRemoval();
     }
     m_processingQueue.Clear();
     var toAdd = new List<Chunk>();
     var chunkPosition = new Vector3Int((int)(m_cacheCenterPosition.X / Chunk.SizeInBlocks), (int)(m_cacheCenterPosition.Y / Chunk.SizeInBlocks), ((int)m_cacheCenterPosition.Z / Chunk.SizeInBlocks));
     for (var z = -CacheRange; z <= CacheRange; z++)
     {
         for (var y = -CacheRange; y <= CacheRange; y++)
         {
             for (var x = -CacheRange; x <= CacheRange; x++)
             {
                 Chunk chunk;
                 if (!m_chunkStorage.ContainsKey(chunkPosition.X + x,
                     chunkPosition.Y + y, chunkPosition.Z + z))
                 {
                     chunk =
                         new Chunk(
                             new Vector3Int(chunkPosition.X + x, chunkPosition.Y + y, chunkPosition.Z + z),
                             Blocks, BlockIndexByWorldPosition, GetNeighborChunk);
                     m_chunkStorage[
                         chunk.ChunkCachePosition.X, chunk.ChunkCachePosition.Y, chunk.ChunkCachePosition.Z] =
                         chunk;
                 }
                 else
                 {
                     chunk = m_chunkStorage[chunkPosition.X + x,
                         chunkPosition.Y + y, chunkPosition.Z + z];
                 }
                 if ((IsInViewRange(chunk) && chunk.ChunkState == ChunkState.Ready)
                     || (!IsInViewRange(chunk) && chunk.ChunkState == ChunkState.AwaitingLighting))
                 {
                     continue;
                 }
                 toAdd.Add(chunk);
             }
         }
     }
     var center = new Vector3(m_cacheCenterPosition.X - Chunk.SizeInBlocks / 2, m_cacheCenterPosition.Y - Chunk.SizeInBlocks / 2, m_cacheCenterPosition.Z - Chunk.SizeInBlocks / 2);
     toAdd.Sort((chunk1, chunk2) =>
     {
         var ret = (int) (chunk1.Position.DistanceSquared(ref center) - chunk2.Position.DistanceSquared(ref center));
         if (ret == 0)
         {
             return (chunk2.ChunkState - chunk1.ChunkState);
         }
         return ret;
     });
     foreach (var chunk in toAdd)
     {
         m_processingQueue.Enqueue(chunk);
     }
 }
Beispiel #9
0
        private static void CopyCunkToPage(Page page, Vector3Int position, Block[] blocks, MappingFunction mappingFunction)
        {
            var originX = MathUtilities.Modulo(position.X, Page.PageSizeInBlocks);
            var originY = MathUtilities.Modulo(position.Y, Page.PageSizeInBlocks);
            var originZ = MathUtilities.Modulo(position.Z, Page.PageSizeInBlocks);
            for (var x = originX; x < originX + Chunk.SizeInBlocks; x++)
            {
                for (var y = originY; y < originY + Chunk.SizeInBlocks; y++)
                {
                    for (var z = originZ; z < originZ + Chunk.SizeInBlocks; z++)
                    {
                        page.Data[Page.BlockIndexFromRelativePosition(x, y, z)] =
                            blocks[mappingFunction(position.X + x, position.Y + y, position.Z + z)];
                    }
                }
            }
	    }
Beispiel #10
0
 public bool Equals(Vector3Int other)
 {
     return (((X == other.X) && (Y == other.Y)) && (Z == other.Z));
 }
Beispiel #11
0
 public float Distance(ref Vector3Int otherVector)
 {
     return (float)Math.Sqrt(DistanceSquared(ref otherVector));
 }
 private void EvaluateLinearTree(Block[] blocks, out float compressionRatio, out ScanDirection optimalDirection)
 {
     var count = m_chunkSize * m_chunkSize * m_chunkSize;
     compressionRatio = 0;
     optimalDirection = ScanDirection.Xyz;
     foreach (ScanDirection scanDirection in Enum.GetValues(typeof(ScanDirection)))
     {
         var nodesRemoved = count;
         Block current = Block.Empty;
         Vector3Int workCoords = new Vector3Int();
         for (var i = 0; i < count; ++i)
         {
             var block = blocks[GetNextIndex(scanDirection, m_chunkSize, ref workCoords)];
             if (block == current)
             {
                 continue;
             }
             current = block;
             --nodesRemoved;
         }
         var currentRatio = nodesRemoved / (float)count;
         if (currentRatio <= compressionRatio)
         {
             continue;
         }
         compressionRatio = currentRatio;
         optimalDirection = scanDirection;
         //this means we are mostly air and can just exit out now!
         if (currentRatio > 0.97f)
         {
             break;
         }
     }
 }
 private SortedList<Interval, Block> ConvertArrayToIntervalTreeLinear(Block[] blocks, ScanDirection optimalDirection, out float compressionRatio)
 {
     var count = m_chunkSize * m_chunkSize * m_chunkSize;
     var nodesRemoved = count;
     var intervals = new SortedList<Interval, Block>();
     var min = 0;
     var max = 0;
     var current = Block.Empty;
     var started = false;
     var workCoords = new Vector3Int();
     for (var i = 0; i < count; ++i)
     {
         var block = blocks[GetNextIndex(optimalDirection, m_chunkSize, ref workCoords)];
         if (!(started && block == current))
         {
             if (started)
             {
                 intervals.Add(new Interval((ushort)min, (ushort)max), current);
             }
             current = block;
             min = i;
             started = true;
             --nodesRemoved;
         }
         max = i;
     }
     intervals.Add(new Interval((ushort)min, (ushort)max), current);
     compressionRatio = nodesRemoved / (float)count;
     return intervals;
 }
 private static int GetNextIndex(ScanDirection direction, int chunkSize, ref Vector3Int workCoords)
 {
     var x = workCoords.X;
     var y = workCoords.Y;
     var z = workCoords.Z;
     switch (direction)
     {
         case ScanDirection.Xyz:
             workCoords.X = (x + 1)%chunkSize;
             if (workCoords.X < x)
             {
                 workCoords.Y = (y + 1)%chunkSize;
                 if (workCoords.Y < y)
                 {
                     workCoords.Z = (z + 1)%chunkSize;
                 }
             }
             break;
         case ScanDirection.Xzy:
             workCoords.X = (x + 1)%chunkSize;
             if (workCoords.X < x)
             {
                 workCoords.Z = (z + 1)%chunkSize;
                 if (workCoords.Z < z)
                 {
                     workCoords.Y = (y + 1)%chunkSize;
                 }
             }
             break;
         case ScanDirection.Yxz:
             workCoords.Y = (y + 1)%chunkSize;
             if (workCoords.Y < y)
             {
                 workCoords.X = (x + 1)%chunkSize;
                 if (workCoords.X < x)
                 {
                     workCoords.Z = (z + 1)%chunkSize;
                 }
             }
             break;
         case ScanDirection.Yzx:
             workCoords.Y = (y + 1)%chunkSize;
             if (workCoords.Y < y)
             {
                 workCoords.Z = (z + 1) % chunkSize;
                 if (workCoords.Z < z)
                 {
                     workCoords.X = (x + 1) % chunkSize;
                 }
             }
             break;
         case ScanDirection.Zxy:
             workCoords.Z = (z + 1) % chunkSize;
             if (workCoords.Z < z)
             {
                 workCoords.X = (x + 1) % chunkSize;
                 if (workCoords.X < x)
                 {
                     workCoords.Y = (y + 1) % chunkSize;
                 }
             }
             break;
         case ScanDirection.Zyx:
             workCoords.Z = (z + 1) % chunkSize;
             if (workCoords.Z < z)
             {
                 workCoords.Y = (y + 1) % chunkSize;
                 if (workCoords.Y < y)
                 {
                     workCoords.X = (x + 1) % chunkSize;
                 }
             }
             break;
         default:
             throw new ArgumentOutOfRangeException("direction");
     }
     return workCoords.X*chunkSize*chunkSize + workCoords.Z*chunkSize + workCoords.Y;
 }
Beispiel #15
0
 public WorldEdit(Vector3Int position, WorldEditType editType)
 {
     Position = position;
     EditType = editType;
 }
Beispiel #16
0
        public Chunk(Vector3Int chunkCachePosition, Block[] blocks, MappingFunction mappingFunction, GetNeighborChunk getNeighborChunk)
        {
            ChunkState = ChunkState.AwaitingGenerate; // set initial state to awaiting generation.
            ChunkCachePosition = chunkCachePosition; // set the relative position.
            m_blocks = blocks;
            m_mappingFunction = mappingFunction;
            m_getNeighborChunk = getNeighborChunk;

            // calculate the real world position.
            Position = new Vector3Int(ChunkCachePosition.X * SizeInBlocks,
                                           ChunkCachePosition.Y * SizeInBlocks,
                                           ChunkCachePosition.Z * SizeInBlocks);

            // calculate bounding-box.
            BoundingBox = new BoundingBox(new Vector3(Position.X, Position.Y, Position.Z),
                                          new Vector3(Position.X + SizeInBlocks, Position.Y + SizeInBlocks,
                                                      Position.Z + SizeInBlocks));
            #if DEBUG
            MainEngine.GetEngineInstance().DebugOnlyDebugManager.RegisterInGameDebuggable(this);
            #endif
        }
Beispiel #17
0
	    public void SaveChunk(Vector3Int position, Block[] blocks, MappingFunction mappingFunction, Action<bool> callback)
        {
            var pagePositionX = position.X >> 6;
            var pagePositionY = position.Y >> 6;
            var pagePositionZ = position.Z >> 6;
	        var pageId = CreatePageId(pagePositionX, pagePositionY, pagePositionZ);
	        if (m_pagesPendingWrite.Contains(pageId))
	        {
                if (callback != null)
                {
                    callback(false);
                }
	        }
	        else
	        {
	            Page page;
	            if (m_pageCache.ContainsPage(pageId))
	            {
                    page = m_pageCache.GetPage(pageId);
                    CopyCunkToPage(page, position, blocks, mappingFunction);
	            }
                else if (m_directory.Pages.Contains(pageId))
                {
                    page = DecompressPage(pageId);
                    CopyCunkToPage(page, position, blocks, mappingFunction);
                    m_pageCache.InsertPage(page);
                }
	            else
	            {
                    page = new Page(position.X, position.Y, position.Z, pageId);
                    for (var x = 0; x < Page.PageSizeInBlocks; x++)
                    {
                        for (var y = 0; y < Page.PageSizeInBlocks; y++)
                        {
                            for (var z = 0; z < Page.PageSizeInBlocks; z++)
                            {
                                page.Data[Page.BlockIndexFromRelativePosition(x, y, z)] =
                                    blocks[mappingFunction(position.X + x, position.Y + y, position.Z + z)];
                            }
                        }
                    }
                    m_pageCache.InsertPage(page);
                    m_directory.Pages.Add(pageId);
                   // m_jsonWriter.Write("SaveDirectory", m_directory);
	            }
	            m_pagesPendingWrite.Add(pageId);
	            Task.Run(() =>
	            {
	                CompressPage(page);
	                if (callback != null)
	                {
	                    callback(true);
	                }
	                m_pagesPendingWrite.Remove(page.PageId);
	            });
	        }
	    }
Beispiel #18
0
        public void RecalculateVisivility()
        {
            m_visibilityTraceQueue = new Queue<VisibilityTraceNode>();
            //We need to iterate over all blocks on each face of the chunk
            foreach (FaceDirection direction in Enum.GetValues(typeof(FaceDirection)))
            {
                var workVector = new Vector3Int();
                for (var index = 0; index < SizeInBlocks * SizeInBlocks; ++index)
                {
                    int faceIndex = IterateOnFace(direction, ref workVector);
                    m_visibilityTraceQueue.Enqueue(new VisibilityTraceNode(workVector, faceIndex));
                }
                while(m_visibilityTraceQueue.Count > 0)
                {
                    var node = m_visibilityTraceQueue.Dequeue();

                }
            }
        }
Beispiel #19
0
	    public void LoadOrCreateChunk(Vector3Int position, Block[] blocks, MappingFunction mappingFunction)
        {
            var pagePositionX = position.X / Page.PageSizeInBlocks;
            var pagePositionY = position.Y / Page.PageSizeInBlocks;
            var pagePositionZ = position.Z / Page.PageSizeInBlocks;
            var pageId = CreatePageId(pagePositionX, pagePositionY, pagePositionZ);
            if (m_pageCache.ContainsPage(pageId))
            {
                var page = m_pageCache.GetPage(pageId);
                CopyPageToChunk(page, position, blocks, mappingFunction);
            }
            else if (m_directory.Pages.Contains(pageId))
            {
                var page = DecompressPage(pageId);
                CopyPageToChunk(page, position, blocks, mappingFunction);
                m_pageCache.InsertPage(page);
            }
            else if (!m_pagesPendingWrite.Contains(pageId))
            {
                m_pagesPendingWrite.Add(pageId);
                var page = new Page(position.X, position.Y, position.Z, pageId);
                var worldPosX = pagePositionX * Page.PageSizeInBlocks;
                var worldPosY = pagePositionY * Page.PageSizeInBlocks;
                var worldPosZ = pagePositionZ * Page.PageSizeInBlocks;
                TerrainGenerator.Instance.GenerateDataForChunk(worldPosX, worldPosY, worldPosZ,
                                                               Page.PageSizeInBlocks, page.Data, (x, y, z) => Page.BlockIndexFromRelativePosition(
                                                                   x - worldPosX, y - worldPosY, z - worldPosZ));

                //BlockDataUtilities.SetupScanDirectedHilbertCurve(Page.PageSizeInBlocks);
               // ChunkCompressor.GetHilbertCurve(32);
                var timer = Stopwatch.StartNew();
                float compressionRatio;
                //ChunkCompressor.ScanDirection scanDir;
                var tree = ChunkCompressor.GetCompressor(Page.PageSizeInBlocks).ConvertArrayToIntervalTree(page.Data,
                    out compressionRatio);
                Console.WriteLine("tree creation time: " + timer.ElapsedMilliseconds);
              //  Console.WriteLine("h: " + scanDir);
              //  Console.WriteLine("tree compresion ratio: " + compressionRatio);
              //  timer.Restart();
            //    var tree2 = ChunkCompressor.ConvertArrayToIntervalTreeLinear(page.Data, Page.PageSizeInBlocks,
            //       out compressionRatio, out scanDir);
                //Console.WriteLine("linear tree creation time: " + timer.ElapsedMilliseconds);
               // Console.WriteLine("l: " + scanDir);
              //  Console.WriteLine("l: " + compressionRatio);

               // tree.

                timer.Restart();
                var res = tree[new Interval(17490)];
                Console.WriteLine("tree query time: " + timer.ElapsedMilliseconds);
                using (var fileStream = new FileStream(Path.Combine(m_dataDirectory, page.PageId + "_tree.page"), FileMode.Create))
                {
                    using (var compressor = new GZipStream(fileStream, CompressionLevel.Optimal))
                    {
                        //Serializer.Serialize(compressor, tree);
                    }
                }
                Console.WriteLine("tree compressionTime time: " + timer.ElapsedMilliseconds);

                timer.Restart();
                CompressPage(page);
                Console.WriteLine("normal compressionTime time: " + timer.ElapsedMilliseconds);

                m_pageCache.InsertPage(page);
                m_directory.Pages.Add(pageId);
                CopyPageToChunk(page, position, blocks, mappingFunction);
                //m_jsonWriter.Write("SaveDirectory", m_directory);
              /*  Task.Run(() =>
                {
                    CompressPage(page);
                    m_pagesPendingWrite.Remove(page.PageId);
                });*/
            }
	    }
Beispiel #20
0
 public Chunk GetChunkByWorldPosition(Vector3Int position)
 {
     return GetChunkByWorldPosition(position.X, position.Y, position.Z);
 }