/* * void Update () { * * foreach (Chunk chunk in ChunksMap) { * if (chunk == null) { * continue; * } * foreach (ChunkSlice slice in chunk.Slices) { * if (slice.IsEmpty) { * continue; * } * slice.FrustrumCulling(); * } * } * } */ void FixedUpdate() { ++accumulator; if (accumulator == 2) // Each 100ms (1 FixedStep is 50ms) { lock (ChunkQueueLock) { Queue <ChunkSliceBuildEntry> temp = ChunkSlicesWorkingQueue; ChunkSlicesWorkingQueue = ChunkSlicesToBuild; ChunkSlicesToBuild = temp; } for (int i = 0; ChunkSlicesWorkingQueue.Count != 0 && i < 40; ++i) { ChunkSliceBuildEntry chunkEntry = ChunkSlicesWorkingQueue.Dequeue(); BuildChunkSliceMesh(chunkEntry); if (ChunkSlicesWorkingQueue.Count == 0 && Player.Instance == null) { Server.Instance.spawnPlayer(new Vector3(0, 160, 0), Quaternion.identity); Menu.Instance.showPanel("PlayerPanel"); } } lock (SliceLock) { Queue <ChunkSlicesDeleteEntry> temp = SlicesToDeleteWorking; SlicesToDeleteWorking = SlicesToDelete; SlicesToDelete = temp; } for (int i = 0; SlicesToDeleteWorking.Count != 0; ++i) { ChunkSlicesDeleteEntry sliceToDelete = SlicesToDeleteWorking.Dequeue(); /*for(int s = 0; s < sliceToDelete.indexesToDelete.Length; ++s) * { * int index = sliceToDelete.indexesToDelete[s]; * ChunkSlice slice = sliceToDelete.parentChunk.Slices[index]; * if(slice.IsEmpty) * sliceToDelete.parentChunk.Slices[index] = null; * * UnityEngine.Object.Destroy(sliceToDelete.parentChunk.ChunkSliceObjects[index]); * sliceToDelete.parentChunk.ChunkSliceObjects[index] = null; * }*/ } accumulator = 0; } }
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"); }