public void InitRenderableSlices() { for (int i = 0; i < NumSlices; ++i) { ChunkSlice slice = Slices[i]; if (!slice.IsEmpty) { slice.ClearDirtyLight(); GameObject newObject = new GameObject("ChunkSlice#" + i); ChunkSliceObjects[i] = newObject; MeshRenderer meshRenderer = newObject.AddComponent(typeof(MeshRenderer)) as MeshRenderer; meshRenderer.material = WorldBehaviour.BlockMaterial; meshRenderer.material.mainTexture = WorldBehaviour.AtlasTexture; meshRenderer.sharedMaterial = WorldBehaviour.BlockMaterial; newObject.AddComponent(typeof(MeshFilter)); newObject.AddComponent <MeshCollider>(); Vector3 pos = new Vector3(ChunkObject.transform.position.x, ChunkObject.transform.position.y + (i * Chunk.SliceHeight), ChunkObject.transform.position.z); if (WorldBehaviour.mode == 3) { pos.x = pos.x * Server.brickWidth; pos.y = pos.y * Server.brickHeight; pos.z = pos.z * Server.brickWidth; } newObject.transform.position = pos; newObject.transform.parent = ChunkObject.transform; slice.renderer = meshRenderer; slice.CreateBoundsBox(newObject.transform); } } }
public BlockType GetBlockType(int x, int y, int z) { ChunkSlice slice = Slices[y / Chunk.SliceHeight]; if (slice == null) { return(0); } return((BlockType)slice[x, y & Chunk.SliceHeightLimit, z]); }
public void ClearDirtySlices() { for (int i = 0; i < NumSlices; ++i) { ChunkSlice slice = Slices[i]; if (slice != null && !slice.IsEmpty) { slice.ClearDirtyLight(); } } }
public void SetSkylight(int x, int y, int z, byte newLight) { ChunkSlice slice = Slices[y / Chunk.SliceHeight]; if (slice == null) { return; } slice.SetSkylight(x, y & SliceHeightLimit, z, newLight); }
public byte GetSkylight(int x, int y, int z) { ChunkSlice slice = Slices[y / Chunk.SliceHeight]; if (slice == null) { return(0); } return(slice.GetSkylight(x, y & SliceHeightLimit, z)); }
public Chunk(int chunkX, int chunkZ, WorldBehaviour world, Color color) { ChunkColor = color; X = chunkX; Z = chunkZ; World = world; for (int i = 0; i < NumSlices; ++i) { Slices[i] = new ChunkSlice(i, this); } }
public void SetType(int x, int y, int z, BlockType type, bool unused) { ChunkSlice slice = Slices[y / Chunk.SliceHeight]; slice[x & 0xF, y & Chunk.SliceHeightLimit, z & 0xF] = (byte)type; }
public void RenderChunk(Chunk chunk) { WorldBehaviour world = chunk.World; /* Stopwatch watch = new Stopwatch(); * watch.Start(); */ int minSliceIndex = chunk.MinSliceIndex; int lowestY = chunk.LowestY; Chunk frontChunk = world.GetChunk(chunk.X, chunk.Z - 1); Chunk backChunk = world.GetChunk(chunk.X, chunk.Z + 1); Chunk leftChunk = world.GetChunk(chunk.X - 1, chunk.Z); Chunk rightChunk = world.GetChunk(chunk.X + 1, chunk.Z); if (frontChunk != null && frontChunk.MinSliceIndex < minSliceIndex) { minSliceIndex = frontChunk.MinSliceIndex; lowestY = frontChunk.LowestY; } if (backChunk != null && backChunk.MinSliceIndex < minSliceIndex) { minSliceIndex = backChunk.MinSliceIndex; lowestY = backChunk.LowestY; } if (leftChunk != null && leftChunk.MinSliceIndex < minSliceIndex) { minSliceIndex = leftChunk.MinSliceIndex; lowestY = leftChunk.MinSliceIndex; } if (rightChunk != null && rightChunk.MinSliceIndex < minSliceIndex) { minSliceIndex = rightChunk.MinSliceIndex; lowestY = rightChunk.MinSliceIndex; } for (int i = Chunk.NumSlices - 1; i >= 0; --i) { ChunkSlice chunkSlice = chunk.Slices[i]; if (i < minSliceIndex) { for (int index = i; index >= 0; --index) { indexesToDelete.Add(index); } break; } if (chunkSlice.IsEmpty) { indexesToDelete.Add(i); continue; } float epsilon = 0.00f; /*watch.Reset(); * watch.Start();*/ int minHeight = chunk.MinSliceIndex == chunkSlice.Index ? (chunk.LowestY & Chunk.SliceHeightLimit) : 0; for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { for (int y = Chunk.SliceHeight - 1; y >= 0 && y >= minHeight; --y) { byte block = chunkSlice[x, y, z]; int light = 0; byte top; if (block == 0) { continue; } if (y + 1 > Chunk.SliceHeightLimit) { if (i + 1 > Chunk.MaxSliceIndex) { top = 0; } else { ChunkSlice topSlice = chunk.Slices[i + 1]; top = topSlice[x, (y + 1) & Chunk.SliceHeightLimit, z]; light = topSlice.GetSkylight(x, (y + 1) & Chunk.SliceHeightLimit, z); } } else { top = chunkSlice[x, y + 1, z]; light = chunkSlice.GetSkylight(x, y + 1, z); } // we are checking the top face of the block, so see if the top is exposed if (top == 0) { if (WorldBehaviour.mode == 2) { spawnBrick(block, new Vector3(x, y, z)); } else if (WorldBehaviour.mode == 3) { addBrickFace("top", block, x, y, z); } else { int vertexIndex = vertices.Count; vertices.Add(new Vector3(x, y + 1, z)); vertices.Add(new Vector3(x, y + 1, z + 1)); vertices.Add(new Vector3(x + 1, y + 1, z + 1)); vertices.Add(new Vector3(x + 1, y + 1, z)); triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 3); triangles.Add(vertexIndex); float attenuation = (light / 15.0f); Color withLight = new Color(topColor.r * attenuation, topColor.g * attenuation, topColor.b * attenuation, 1); colors.Add(withLight); colors.Add(withLight); colors.Add(withLight); colors.Add(withLight); Rect coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Top); float yMax = coords.y + coords.height - epsilon; float xMax = coords.x + coords.width - epsilon; float xMin = coords.x + epsilon; float yMin = coords.y + epsilon; uvs.Add(new Vector2(xMin, yMax)); uvs.Add(new Vector2(xMin, yMin)); uvs.Add(new Vector2(xMax, yMin)); uvs.Add(new Vector2(xMax, yMax)); } } int front; if (z - 1 < 0) { int worldX = (chunk.X << 4) + x; int worldZ = (chunk.Z << 4) - 1; int worldY = (chunkSlice.Index * ChunkSlice.SizeY) + y; front = (byte)world.GetBlockType(worldX, worldY, worldZ); } else { front = chunkSlice[x, y, z - 1]; } if (front == 0) { if (WorldBehaviour.mode == 2) { spawnBrick(block, new Vector3(x, y, z)); } else if (WorldBehaviour.mode == 3) { addBrickFace("front", block, x, y, z); } else { int vertexIndex = vertices.Count; vertices.Add(new Vector3(x, y, z)); vertices.Add(new Vector3(x, y + 1, z)); vertices.Add(new Vector3(x + 1, y + 1, z)); vertices.Add(new Vector3(x + 1, y, z)); triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 3); triangles.Add(vertexIndex); colors.Add(firstSideColor); colors.Add(firstSideColor); colors.Add(firstSideColor); colors.Add(firstSideColor); Rect coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Side); float yMax = coords.y + coords.height - epsilon; float xMax = coords.x + coords.width - epsilon; float xMin = coords.x + epsilon; float yMin = coords.y + epsilon; uvs.Add(new Vector2(xMin, yMin)); uvs.Add(new Vector2(xMin, yMax)); uvs.Add(new Vector2(xMax, yMax)); uvs.Add(new Vector2(xMax, yMin)); } } int right; if (x + 1 > 15) { int worldX = (chunk.X << 4) + 16; int worldZ = (chunk.Z << 4) + z; int worldY = (chunkSlice.Index * ChunkSlice.SizeY) + y; right = (byte)world.GetBlockType(worldX, worldY, worldZ); } else { right = chunkSlice[x + 1, y, z]; } if (right == 0) { if (WorldBehaviour.mode == 2) { spawnBrick(block, new Vector3(x, y, z)); } else if (WorldBehaviour.mode == 3) { addBrickFace("right", block, x, y, z); } else { int vertexIndex = vertices.Count; vertices.Add(new Vector3(x + 1, y, z)); vertices.Add(new Vector3(x + 1, y + 1, z)); vertices.Add(new Vector3(x + 1, y + 1, z + 1)); vertices.Add(new Vector3(x + 1, y, z + 1)); triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 3); triangles.Add(vertexIndex); colors.Add(secondSideColor); colors.Add(secondSideColor); colors.Add(secondSideColor); colors.Add(secondSideColor); Rect coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Side); float yMax = coords.y + coords.height - epsilon; float xMax = coords.x + coords.width - epsilon; float xMin = coords.x + epsilon; float yMin = coords.y + epsilon; uvs.Add(new Vector2(xMin, yMin)); uvs.Add(new Vector2(xMin, yMax)); uvs.Add(new Vector2(xMax, yMax)); uvs.Add(new Vector2(xMax, yMin)); } } int back; if (z + 1 > 15) { int worldX = (chunk.X << 4) + x; int worldZ = (chunk.Z << 4) + 16; int worldY = (chunkSlice.Index * ChunkSlice.SizeY) + y; back = (byte)world.GetBlockType(worldX, worldY, worldZ); } else { back = chunkSlice[x, y, z + 1]; } if (back == 0) { if (WorldBehaviour.mode == 2) { spawnBrick(block, new Vector3(x, y, z)); } else if (WorldBehaviour.mode == 3) { addBrickFace("back", block, x, y, z); } else { int vertexIndex = vertices.Count; vertices.Add(new Vector3(x + 1, y, z + 1)); vertices.Add(new Vector3(x + 1, y + 1, z + 1)); vertices.Add(new Vector3(x, y + 1, z + 1)); vertices.Add(new Vector3(x, y, z + 1)); triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 3); triangles.Add(vertexIndex); colors.Add(firstSideColor); colors.Add(firstSideColor); colors.Add(firstSideColor); colors.Add(firstSideColor); Rect coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Side); float yMax = coords.y + coords.height - epsilon; float xMax = coords.x + coords.width - epsilon; float xMin = coords.x + epsilon; float yMin = coords.y + epsilon; uvs.Add(new Vector2(xMin, yMin)); uvs.Add(new Vector2(xMin, yMax)); uvs.Add(new Vector2(xMax, yMax)); uvs.Add(new Vector2(xMax, yMin)); } } int left; if (x - 1 < 0) { int worldX = (chunk.X << 4) - 1; int worldZ = (chunk.Z << 4) + z; int worldY = (chunkSlice.Index * ChunkSlice.SizeY) + y; left = (byte)world.GetBlockType(worldX, worldY, worldZ); } else { left = chunkSlice[x - 1, y, z]; } if (left == 0) { if (WorldBehaviour.mode == 2) { spawnBrick(block, new Vector3(x, y, z)); } else if (WorldBehaviour.mode == 3) { addBrickFace("left", block, x, y, z); } else { int vertexIndex = vertices.Count; vertices.Add(new Vector3(x, y, z + 1)); vertices.Add(new Vector3(x, y + 1, z + 1)); vertices.Add(new Vector3(x, y + 1, z)); vertices.Add(new Vector3(x, y, z)); triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 3); triangles.Add(vertexIndex); colors.Add(secondSideColor); colors.Add(secondSideColor); colors.Add(secondSideColor); colors.Add(secondSideColor); Rect coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Side); float yMax = coords.y + coords.height - epsilon; float xMax = coords.x + coords.width - epsilon; float xMin = coords.x + epsilon; float yMin = coords.y + epsilon; uvs.Add(new Vector2(xMin, yMin)); uvs.Add(new Vector2(xMin, yMax)); uvs.Add(new Vector2(xMax, yMax)); uvs.Add(new Vector2(xMax, yMin)); } } byte bottom; if (y - 1 < 0) { bottom = 1; } else { bottom = chunkSlice[x, y - 1, z]; } if (bottom == 0) { if (WorldBehaviour.mode == 2) { spawnBrick(block, new Vector3(x, y, z)); } else if (WorldBehaviour.mode == 3) { addBrickFace("bottom", block, x, y, z); } else { int vertexIndex = vertices.Count; vertices.Add(new Vector3(x, y, z + 1)); vertices.Add(new Vector3(x, y, z)); vertices.Add(new Vector3(x + 1, y, z)); vertices.Add(new Vector3(x + 1, y, z + 1)); triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 3); triangles.Add(vertexIndex); colors.Add(bottomColor); colors.Add(bottomColor); colors.Add(bottomColor); colors.Add(bottomColor); Rect coords = BlockUVs.GetUVFromTypeAndFace((BlockType)block, BlockFace.Bottom); float yMax = coords.y + coords.height - epsilon; float xMax = coords.x + coords.width - epsilon; float xMin = coords.x + epsilon; float yMin = coords.y + epsilon; uvs.Add(new Vector2(xMin, yMin)); uvs.Add(new Vector2(xMin, yMax)); uvs.Add(new Vector2(xMax, yMax)); uvs.Add(new Vector2(xMax, yMin)); } } } } } /*watch.Stop(); * long elapsedPreMesh = watch.ElapsedMilliseconds; * watch.Start();*/ ChunkSliceBuildEntry chunkEntry = new ChunkSliceBuildEntry(); chunkEntry.Vertices = vertices.ToArray(); chunkEntry.Triangles = triangles.ToArray(); chunkEntry.Colors = colors.ToArray(); chunkEntry.Uvs = uvs.ToArray(); chunkEntry.ParentChunk = chunk; chunkEntry.SliceIndex = i; chunkEntry.ColliderVertices = colliderVertices.ToArray(); chunkEntry.ColliderTriangles = colliderTriangles.ToArray(); if (WorldBehaviour.mode == 2) { Dictionary <byte, Vector3[]> meshList = new Dictionary <byte, Vector3[]>(); foreach (byte block in meshes.Keys) { meshList.Add(block, meshes[block].ToArray()); } chunkEntry.meshes = meshList; } vertices.Clear(); triangles.Clear(); colors.Clear(); uvs.Clear(); meshes.Clear(); added.Clear(); colliderVertices.Clear(); colliderTriangles.Clear(); lock (WorldBehaviour.ChunkQueueLock) WorldBehaviour.ChunkSlicesToBuild.Enqueue(chunkEntry); //watch.Stop(); //elapsedPostSet = watch.ElapsedMilliseconds; /*UnityEngine.Debug.Log("Elapsed Mesh Prepare " + elapsedPreMesh + "ms"); * UnityEngine.Debug.Log("Elapsed Mesh Build " + (elapsedPostMesh - elapsedPreMesh) + "ms"); * UnityEngine.Debug.Log("Elapsed Mesh Set " + (elapsedPostSet - elapsedPostMesh) + "ms"); * UnityEngine.Debug.Log("Total Elapsed " + (elapsedPostSet));*/ } if (indexesToDelete.Count > 0) { lock (WorldBehaviour.SliceLock) { ChunkSlicesDeleteEntry chunkSliceEntry = new ChunkSlicesDeleteEntry(); chunkSliceEntry.indexesToDelete = indexesToDelete.ToArray(); chunkSliceEntry.parentChunk = chunk; WorldBehaviour.SlicesToDelete.Enqueue(chunkSliceEntry); } } //watch.Stop(); //UnityEngine.Debug.Log ("Total Elapsed " + ((double)watch.ElapsedTicks / (double)Stopwatch.Frequency) + "ms"); }