Beispiel #1
0
    private World()
    {
        // Get the extents of the world.
        var  blocks = Component.FindObjectsOfType <Block>();
        Int3 minPos = new Int3(500, 500, 500);
        Int3 maxPos = new Int3(-500, -500, -500);

        foreach (Block block in blocks)
        {
            Debug.Log("Block at: " + block.transform.position);
            minPos = Int3.Min(minPos, new Int3(block.transform.position));
            maxPos = Int3.Max(maxPos, new Int3(block.transform.position));
        }

        Origin = minPos;
        Size   = maxPos - minPos + Int3.One;
        Debug.Log("Origin: " + minPos);
        Debug.Log("Size: " + Size);
        Debug.Log("Max Pos: " + maxPos);
        // Fill the array.
        Blocks = new Block[Size.x, Size.y, Size.z];
        //Debug.Log("Blocks dimension: " + Blocks.GetLength(0) + ", ")
        foreach (Block block in blocks)
        {
            Int3 pos = new Int3(block.transform.position) - Origin;
            Blocks[pos.x, pos.y, pos.z] = block;
        }
    }
Beispiel #2
0
        protected override Int3 GetElementSpanValues(UIElement element)
        {
            var position = GetElementGridPositions(element);
            var span     = base.GetElementSpanValues(element);

            return(Int3.Min(position + span, new Int3(stripDefinitions[0].Count, stripDefinitions[1].Count, stripDefinitions[2].Count)) - position);
        }
Beispiel #3
0
        public override Vec3 ClampDestination(string task, Vec3 newPosition, EntityID currentEntityPosition, float maxDistance)
        {
            newPosition = Ranges.World.Clamp(newPosition);              //make sure we do not leave the simulation space


            if (!Simulation.Owns(newPosition))
            {
                Int3 targetShard = Int3.Min(newPosition.FloorInt3, Simulation.Extent.XYZ - 1);
                bool any = false, anyResponive = false;
                foreach (var n in Simulation.Neighbors)
                {
                    if (n.ID.XYZ == targetShard)
                    {
                        any = true;
                        if (n.IsResponsive)
                        {
                            anyResponive = true;
                        }
                        break;
                    }
                }
                if (!any)
                {
                    Debug.Fail("This should not happen");
                    throw new ExecutionException(currentEntityPosition, task + " targets space beyond known neighbors. Rejecting motion");
                }
                if (!anyResponive && !AllowMotionToUnresponsiveNeighbor)
                {
                    throw new ExecutionException(currentEntityPosition, task + " targets space of inactive neighbor shard. Rejecting");
                }
            }


            return(base.ClampDestination(task, newPosition, currentEntityPosition, maxDistance));
        }
Beispiel #4
0
        public void Include(BitCube other, Int3 offset)
        {
            if ((offset >= size).Any)
            {
                return;
            }

            Int3 sourceStart = Int3.Max(-offset, 0);
            Int3 sourceCount = other.Size - sourceStart;

            Int3 destStart = Int3.Max(offset, 0);

            sourceCount = Int3.Min(destStart + sourceCount, size) - destStart;

            Int3 at = new Int3();

            for (at.X = 0; at.X < sourceCount.X; at.X++)
            {
                for (at.Y = 0; at.Y < sourceCount.Y; at.Y++)
                {
                    for (at.Z = 0; at.Z < sourceCount.Z; at.Z++)
                    {
                        this[at + destStart] |= other[at + sourceStart];
                    }
                }
            }
        }
Beispiel #5
0
 public static Int3 ToPixelR(Vec3 relative)
 {
     if ((relative < Vec3.Zero).Any)
     {
         throw new ArgumentOutOfRangeException(relative + " partially less than zero");
     }
     if ((relative > Vec3.One).Any)
     {
         throw new ArgumentOutOfRangeException(relative + " partially greater or equal to one");
     }
     return(Int3.Min((relative * CommonResolution).FloorInt3, CommonResolution - 1));
 }
    public IEnumerable <Util.Tuple <Cell, CellValue> > GetFilledCells(Cell cellA, Cell cellB)
    {
        Int3 cellIntA = cellA.ToInt3();
        Int3 cellIntB = cellB.ToInt3();

        Int3 min = Int3.Min(cellIntA, cellIntB);
        Int3 max = Int3.Max(cellIntA, cellIntB) + Int3.one();

        // Int3 mins3 = mins.ToInt3();
        // Int3 maxs = inclusiveMaxs.ToInt3() + Int3.one();
        foreach (Int3 u in Int3.Enumerate(min, max))
        {
            CellValue val = GetCellValue(new Cell(u));
            if (val.blockType != BlockShape.Empty)
            {
                yield return(new Util.Tuple <Cell, CellValue>(new Cell(u), val));
            }
        }
    }
Beispiel #7
0
        public void SetOne(Int3 offset, Int3 count)
        {
            Int3 sourceStart = Int3.Max(-offset, 0);
            Int3 sourceCount = count - sourceStart;
            Int3 destStart   = Int3.Max(offset, 0);

            sourceCount = Int3.Min(destStart + sourceCount, size) - destStart;

            Int3 at = new Int3();

            for (at.X = 0; at.X < sourceCount.X; at.X++)
            {
                for (at.Y = 0; at.Y < sourceCount.Y; at.Y++)
                {
                    for (at.Z = 0; at.Z < sourceCount.Z; at.Z++)
                    {
                        this[at + destStart] = true;
                    }
                }
            }
        }
Beispiel #8
0
        public int OneCountIn(Int3 offset, Int3 count)
        {
            Int3 count3 = count - Int3.Max(-offset, 0);

            offset = Int3.Max(offset, 0);
            count3 = Int3.Min(offset + count3, size) - offset;

            Int3 at = new Int3();
            int  rs = 0;

            for (at.X = 0; at.X < count3.X; at.X++)
            {
                for (at.Y = 0; at.Y < count3.Y; at.Y++)
                {
                    for (at.Z = 0; at.Z < count3.Z; at.Z++)
                    {
                        rs += this[at + offset] ? 1 : 0;
                    }
                }
            }
            return(rs);
        }
Beispiel #9
0
        protected override Int3 GetElementGridPositions(UIElement element)
        {
            var position = base.GetElementGridPositions(element);

            return(Int3.Min(position, new Int3(stripDefinitions[0].Count - 1, stripDefinitions[1].Count - 1, stripDefinitions[2].Count - 1)));
        }
        public void PostProcess(RenderDrawContext drawContext, ShaderSource[] mipmapShaders)
        {
            if (mipmapShaders.Length != LayoutSize)
            {
                return;
            }

            if (VoxelMipmapSimple == null)
            {
                VoxelMipmapSimple = new Stride.Rendering.ComputeEffect.ComputeEffectShader(drawContext.RenderContext)
                {
                    ShaderSourceName = "Voxel2x2x2MipmapEffect"
                };
            }

            if (VoxelMipmapSimpleGroups == null || VoxelMipmapSimpleGroups.Length != LayoutSize || VoxelMipmapSimpleGroups[0].Length != TempMipMaps.Length)
            {
                if (VoxelMipmapSimpleGroups != null)
                {
                    for (int axis = 0; axis < LayoutSize; axis++)
                    {
                        if (VoxelMipmapSimpleGroups[axis] != null)
                        {
                            foreach (var shader in VoxelMipmapSimpleGroups[axis])
                            {
                                shader.Dispose();
                            }
                        }
                    }
                }
                VoxelMipmapSimpleGroups = new Stride.Rendering.ComputeEffect.ComputeEffectShader[LayoutSize][];
                for (int axis = 0; axis < LayoutSize; axis++)
                {
                    VoxelMipmapSimpleGroups[axis] = new Stride.Rendering.ComputeEffect.ComputeEffectShader[TempMipMaps.Length];
                    for (int i = 0; i < VoxelMipmapSimpleGroups[axis].Length; i++)
                    {
                        VoxelMipmapSimpleGroups[axis][i] = new Stride.Rendering.ComputeEffect.ComputeEffectShader(drawContext.RenderContext)
                        {
                            ShaderSourceName = "Voxel2x2x2MipmapEffect"
                        };
                    }
                }
            }

            int offsetIndex = 0;
            //Mipmap detailed clipmaps into less detailed ones
            Vector3 totalResolution   = ClipMapResolution * new Vector3(1, LayoutSize, 1);
            Int3    threadGroupCounts = new Int3(32, 32, 32);

            if (DownsampleFinerClipMaps)
            {
                for (int i = 0; i < ClipMapCount - 1; i++)
                {
                    Vector3 Offset = MippingOffset[offsetIndex];

                    VoxelMipmapSimple.ThreadNumbers     = new Int3(8);
                    VoxelMipmapSimple.ThreadGroupCounts = (Int3)((ClipMapResolution / 2f) / (Vector3)VoxelMipmapSimple.ThreadNumbers);

                    for (int axis = 0; axis < LayoutSize; axis++)
                    {
                        VoxelMipmapSimple.Parameters.Set(Voxel2x2x2MipmapKeys.ReadTex, ClipMaps);
                        VoxelMipmapSimple.Parameters.Set(Voxel2x2x2MipmapKeys.WriteTex, TempMipMaps[0]);
                        VoxelMipmapSimple.Parameters.Set(Voxel2x2x2MipmapKeys.ReadOffset, -(Vector3.Mod(Offset, new Vector3(2))) + new Vector3(0, (int)totalResolution.Y * i + (int)ClipMapResolution.Y * axis, 0));
                        VoxelMipmapSimple.Parameters.Set(Voxel2x2x2MipmapKeys.WriteOffset, new Vector3(0, ClipMapResolution.Y / 2 * axis, 0));
                        VoxelMipmapSimple.Parameters.Set(Voxel2x2x2MipmapKeys.mipmapper, mipmapShaders[axis]);
                        ((RendererBase)VoxelMipmapSimple).Draw(drawContext);
                    }

                    Offset -= Vector3.Mod(Offset, new Vector3(2));
                    //Copy each axis, ignoring the top and bottom plane
                    for (int axis = 0; axis < LayoutSize; axis++)
                    {
                        int axisOffset = axis * (int)ClipMapResolution.Y;

                        Int3 CopySize = new Int3((int)ClipMapResolution.X / 2 - 2, (int)ClipMapResolution.Y / 2 - 2, (int)ClipMapResolution.Z / 2 - 2);


                        Int3 DstMinBound = new Int3((int)ClipMapResolution.X / 4 + (int)Offset.X / 2 + 1, (int)totalResolution.Y * (i + 1) + axisOffset + (int)ClipMapResolution.Y / 4 + 1 + (int)Offset.Y / 2, (int)ClipMapResolution.Z / 4 + (int)Offset.Z / 2 + 1);
                        Int3 DstMaxBound = DstMinBound + CopySize;

                        DstMaxBound = Int3.Min(DstMaxBound, new Int3((int)totalResolution.X, (int)totalResolution.Y * (i + 2), (int)totalResolution.Z));
                        DstMinBound = Int3.Min(DstMinBound, new Int3((int)totalResolution.X, (int)totalResolution.Y * (i + 2), (int)totalResolution.Z));
                        DstMaxBound = Int3.Max(DstMaxBound, new Int3(0, (int)totalResolution.Y * (i + 1), 0));
                        DstMinBound = Int3.Max(DstMinBound, new Int3(0, (int)totalResolution.Y * (i + 1), 0));

                        Int3 SizeBound = DstMaxBound - DstMinBound;

                        Int3 SrcMinBound = new Int3(1, axisOffset / 2 + 1, 1);
                        Int3 SrcMaxBound = SrcMinBound + SizeBound;

                        if (SizeBound.X > 0 && SizeBound.Y > 0 && SizeBound.Z > 0)
                        {
                            drawContext.CommandList.CopyRegion(TempMipMaps[0], 0,
                                                               new ResourceRegion(
                                                                   SrcMinBound.X, SrcMinBound.Y, SrcMinBound.Z,
                                                                   SrcMaxBound.X, SrcMaxBound.Y, SrcMaxBound.Z
                                                                   ),
                                                               ClipMaps, 0,
                                                               DstMinBound.X, DstMinBound.Y, DstMinBound.Z);
                        }
                    }
                    offsetIndex++;
                }
            }
            Vector3 resolution = ClipMapResolution;

            offsetIndex = ClipMapCount - 1;
            //Mipmaps for the largest clipmap
            for (int i = 0; i < TempMipMaps.Length - 1; i++)
            {
                Vector3 Offset = MippingOffset[offsetIndex];
                resolution /= 2;

                Vector3 threadNums = Vector3.Min(resolution, new Vector3(8));

                for (int axis = 0; axis < LayoutSize; axis++)
                {
                    var mipmapShader = VoxelMipmapSimpleGroups[axis][i];
                    mipmapShader.ThreadNumbers     = (Int3)(threadNums);
                    mipmapShader.ThreadGroupCounts = (Int3)(resolution / threadNums);
                    if (i == 0)
                    {
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.ReadTex, ClipMaps);
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.ReadOffset, -Offset + new Vector3(0, (int)ClipMapResolution.Y * LayoutSize * (ClipMapCount - 1) + (int)ClipMapResolution.Y * axis, 0));
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.WriteOffset, new Vector3(0, resolution.Y * axis, 0));
                    }
                    else
                    {
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.ReadTex, TempMipMaps[i - 1]);
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.ReadOffset, -Offset + new Vector3(0, resolution.Y * axis * 2, 0));
                        mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.WriteOffset, new Vector3(0, resolution.Y * axis, 0));
                    }
                    mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.WriteTex, TempMipMaps[i]);
                    mipmapShader.Parameters.Set(Voxel2x2x2MipmapKeys.mipmapper, mipmapShaders[axis]);
                    ((RendererBase)mipmapShader).Draw(drawContext);
                }
                //Don't seem to be able to read and write to the same texture, even if the views
                //point to different mipmaps.
                drawContext.CommandList.CopyRegion(TempMipMaps[i], 0, null, MipMaps, i);
                offsetIndex++;
            }
            Array.Copy(PerMapOffsetScale, PerMapOffsetScaleCurrent, PerMapOffsetScale.Length);
        }
    public void Reset(
        Vector2 worldSize, byte[] terrainV2Data,
        bool loadingDataFromBeforeDigging,
        byte[] legacyData,
        ulong[] customStyleWorkshopIds = null,
        string simpleData = null)
    {
        Debug.Assert(worldSize.magnitude > 0f);
        Util.Log($"Resetting terrain!");

        float groundSizeX = worldSize.x;
        float groundSizeZ = worldSize.y;

        var newDims = new Int3(
            Mathf.CeilToInt(groundSizeX / BLOCK_SIZE.x),
            BlocksYCount,
            Mathf.CeilToInt(groundSizeZ / BLOCK_SIZE.z));

        Debug.Assert(newDims >= new Int3(10, 10, 10));

        Int3 newBotCenter = new Int3(newDims.x / 2, 0, newDims.z / 2);

        // If old data exists, make sure we restore it. This is the resize use case.
        byte[] restoreData = null;
        Int3   restoreDims = Int3.zero();

        if (terrainV2 != null)
        {
            var oldDims = terrainV2.GetWorldDimensions();
            restoreDims = Int3.Min(oldDims, newDims);
            Int3 start = oldDims / 2 - restoreDims / 2;
            Int3 end   = start + restoreDims;
            Debug.Assert(start >= Int3.zero());
            Debug.Assert(end <= oldDims);
            restoreData = terrainV2.Serialize(start, end);

            Destroy(terrainV2.gameObject);
            terrainV2 = null;
        }

        using (Util.Profile("terrainV2 instantiate"))
            terrainV2 = Instantiate(terrainV2Prefab, Vector3.zero, Quaternion.identity, this.transform);

        using (Util.Profile("terrainV2 SetWorldDimensions"))
            terrainV2.SetWorldDimensions(newDims);

        terrainV2.SetRootOffset(new Vector3(
                                    -newDims.x / 2 * 2.5f,
                                    BlocksYStart * BlockHeight + BlockHeight / 2f,
                                    -newDims.z / 2 * 2.5f));

        using (Util.Profile("Create color terrain textures"))
        {
            int texSize = terrainV2.GetStyleTextureResolution();
            // Color32 way faster in general than Color.
            for (int i = 0; i < NumSolidColorStyles; i++)
            {
                Color32[] pixels  = new Color32[texSize * texSize];
                Color32   color32 = rendering.blockColors[i];
                for (int j = 0; j < pixels.Length; j++)
                {
                    pixels[j] = color32;
                }
                terrainV2.SetStyleTextures(i, pixels); // color

                // 10 is orange
                if (i == (int)BlockStyle.SolidColor10)
                {
                    fallbackTexture = pixels;
                }
            }
        }

        Debug.Assert(fallbackTexture != null, "Could not find fallbackTexture?");

        // TODO why do we do these specifically? Are they not read in via the loop below?
        terrainV2.SetStyleTextures((int)BlockStyle.Stone, terrainV2Textures[4].GetPixels32());                                                                              // stone
        terrainV2.SetStyleTextures((int)BlockStyle.Space, terrainV2Textures[1].GetPixels32());                                                                              // metal
        terrainV2.SetStyleTextures((int)BlockStyle.Grass, terrainV2Textures[8].GetPixels32(), terrainV2Textures[7].GetPixels32(), terrainV2Textures[6].GetPixels32());      // grass
        terrainV2.SetStyleTextures((int)BlockStyle.SnowRock, terrainV2Textures[11].GetPixels32(), terrainV2Textures[10].GetPixels32(), terrainV2Textures[9].GetPixels32()); // snow

        foreach (object obj in Enum.GetValues(typeof(BlockStyle)))
        {
            BlockStyle style = (BlockStyle)obj;
            if ((int)style <= (int)BlockStyle.SnowRock)
            {
                // We hard code this above for now.
                continue;
            }
            Color32[] topOrAtlas = null;
            Color32[] side       = null;
            Color32[] overflow   = null;
            foreach (var tex in terrainV2Textures)
            {
                if (tex == null)
                {
                    continue;
                }
                if (!tex.name.StartsWith(style.ToString().ToLowerInvariant()))
                {
                    continue;
                }

                if (tex.name.EndsWith("-top") || tex.name == style.ToString().ToLowerInvariant())
                {
                    topOrAtlas = tex.GetPixels32();
                }
                else if (tex.name.EndsWith("-side-ceiling"))
                {
                    side = tex.GetPixels32();
                }
                else if (tex.name.EndsWith("-overflow"))
                {
                    overflow = tex.GetPixels32();
                }
            }

            if (topOrAtlas == null)
            {
                Util.LogWarning($"Had to use fallback texture for terrain style {style}. side={side}, overflow={overflow}");
                topOrAtlas = fallbackTexture;
            }

            if (side != null)
            {
#if UNITY_EDITOR
                Debug.Assert(overflow != null, $"{style.ToString()} style has a side texture but not an overflow?");
#endif
            }
            else
            {
                if (overflow != null)
                {
                    Util.LogWarning($"Style {style} had an overflow texture but not a side? IGNORING overflow.");
                    overflow = null;
                }
            }

            terrainV2.SetStyleTextures((int)style, topOrAtlas, side, overflow);
        }

        // Custom styles
        this.customStyleWorkshopIds.Clear();
        if (customStyleWorkshopIds != null)
        {
            this.customStyleWorkshopIds.AddRange(customStyleWorkshopIds);
        }
        UpdateCustomStyleWorkshopIds();

        if (restoreData != null)
        {
            terrainV2.Deserialize(restoreData, (newDims / 2 - restoreDims / 2));
        }

        if (legacyData != null)
        {
            LoadLegacyTerrainData(legacyData);

            // But move all the blocks to our new system.
            using (Util.Profile("legacySync"))
            {
                foreach (var args in database.EnumerateBlocks())
                {
                    terrainV2.SetCell(args.cell.ToInt3() + GetV2Offset(), (int)args.value.style, (int)args.value.blockType - 1, (int)args.value.direction);
                }
            }
        }

        if (terrainV2Data != null)
        {
            Util.Log($"loading v2 data of {terrainV2Data.Length} bytes");
            using (Util.Profile("terrainV2 Deserialize"))
                terrainV2.Deserialize(terrainV2Data);

            // Legacy upgrade
            if (loadingDataFromBeforeDigging)
            {
                // The serialized data was before digging. We need to move it up, effectively.
                Debug.Assert(BlocksYStart < 0);
                // Copy...
                byte[] temp = terrainV2.Serialize(
                    Int3.zero(),
                    newDims.WithY(newDims.y + BlocksYStart));
                // Move up..
                terrainV2.Deserialize(
                    temp,
                    Int3.zero().WithY(-BlocksYStart));

                // At this point, we actually have 2 copies of the terrain, offset by
                // some Y! heh. But the SetSlices call below will deal with that.
            }
        }

        if (loadingDataFromBeforeDigging)
        {
            // Fill in the ground.
            BlockStyle style = BlockStyle.Grass;
            switch (stage.GetGroundType())
            {
            case GameBuilderStage.GroundType.Snow:
                style = BlockStyle.SnowRock;
                break;

            case GameBuilderStage.GroundType.SolidColor:
            case GameBuilderStage.GroundType.Space:
            case GameBuilderStage.GroundType.Grass:
            default:
                style = BlockStyle.Grass;
                break;
            }
            terrainV2.SetSlices(0, (0 - BlocksYStart), (int)style, 0, 0);
        }

        if (!simpleData.IsNullOrEmpty())
        {
            byte[] zippedBytes = System.Convert.FromBase64String(simpleData);
            using (var zippedStream = new System.IO.MemoryStream(zippedBytes, 0, zippedBytes.Length))
                using (var unzipped = new System.IO.Compression.GZipStream(zippedStream, System.IO.Compression.CompressionMode.Decompress))
                    using (System.IO.BinaryReader reader = new System.IO.BinaryReader(unzipped))
                    {
                        int version = reader.ReadUInt16(); // Unused.
                        Debug.Assert(version == 0, $"Unknown simpleData version: {version}");
                        uint numBlocks = reader.ReadUInt32();
                        Util.Log($"reading in {numBlocks} from simpleData");
                        for (int i = 0; i < numBlocks; i++)
                        {
                            short  x         = reader.ReadInt16();
                            short  y         = reader.ReadInt16();
                            short  z         = reader.ReadInt16();
                            byte   shape     = reader.ReadByte();
                            byte   direction = reader.ReadByte();
                            ushort style     = reader.ReadUInt16();
                            this.SetCellValue(
                                new Cell(x, y, z),
                                new CellValue
                            {
                                blockType = (BlockShape)shape,
                                direction = (BlockDirection)direction,
                                style     = (BlockStyle)style
                            });
                        }
                    }
        }

        // Now mark chunks with actors in them as important
        foreach (var actor in engine.EnumerateActors())
        {
            // Non-dynamic-physics actors don't need terrain to exist...well, less so.
            if (!actor.GetEnablePhysics())
            {
                continue;
            }
            var  pos  = actor.GetSpawnPosition();
            Int3 cell = GetContainingCell(pos).ToInt3();
            terrainV2.ReportRigidbodyAt((cell + GetV2Offset()));
        }
    }