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; } }
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); }
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)); }
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]; } } } }
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)); } } }
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; } } } }
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); }
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())); } }