/// <summary> /// Rebuilds this chunk's geometry. /// </summary> public void Rebuild(Graphics.SceneRenderer renderer) { ReconstructBlockFaceVisibility(); ReconstructVertices(renderer); // Reset dirty flag. isDirty = false; }
public void Draw(Graphics.SceneRenderer renderer) { effect.View = renderer.Camera.LookAtMatrix; effect.Projection = GameSettings.PfovMatrix; Chunk chunk; // Draw geometry for (int x = 0; x < width; ++x) { for (int z = 0; z < length; ++z) { chunk = chunks[x, z]; // If necessary, rebuild the chunk's geometry. if (chunk.IsDirty) { chunk.Rebuild(renderer); } else { // Else just rebuild transparent vertices to ensure correct draw order. // TODO: Perform this only when the player moves, not every frame. chunk.ReconstructVertices(renderer, true); } // If there are opaque vertices to draw, do so. if (chunk.OpaqueVertexBuffer != null) { renderer.DrawVertices(chunk.OpaqueVertexBuffer, effect); } // Draw any alpha-blended vertices. if (chunk.TransparentVertexBuffer != null) { renderer.DrawAlphaBlendedVertices(chunk.TransparentVertexBuffer, effect, new Vector3(x * Chunk.WIDTH, 0, z * Chunk.LENGTH)); } } } }
/// <summary> /// Reconstructs voxel vertices for the world, based on visible block face data. /// </summary> /// <param name="renderer">The SceneRenderer which will be used to render the vertices.</param> /// <param name="alphaBlendedOnly">If true, only alpha-blended vertices will be reconstructed.</param> public void ReconstructVertices(Graphics.SceneRenderer renderer, bool alphaBlendedOnly = false) { Block block; List <VertexRebuildQueueItem> alphaBlendedBlocksToRebuild = new List <VertexRebuildQueueItem>(); // Using a List so this can be depth-sorted. Queue <VertexRebuildQueueItem> opaqueBlocksToRebuild = new Queue <VertexRebuildQueueItem>(); List <VertexPositionColorTexture> alphaBlendedVertices = new List <VertexPositionColorTexture>(); List <VertexPositionColorTexture> opaqueVertices = new List <VertexPositionColorTexture>(); // TODO: Use an array instead of a list // Queue up blocks to be processed. for (int x = 0; x < WIDTH; ++x) { for (int y = 0; y < HEIGHT; ++y) { for (int z = 0; z < LENGTH; ++z) { block = BlockAt(x, y, z); if (block.BlockType.IsInvisible) { // Skip invisible blocks as they have no vertices. continue; } else if (block.BlockType.IsAlphaBlended) { // Add alpha blended blocks to alpha blended queue. VertexRebuildQueueItem queueItem = new VertexRebuildQueueItem(); queueItem.Block = block; queueItem.Position = new Vector3Int(x, y, z); alphaBlendedBlocksToRebuild.Add(queueItem); } else if (!alphaBlendedOnly) { // Add opaque blocks to opaque queue. VertexRebuildQueueItem queueItem = new VertexRebuildQueueItem(); queueItem.Block = block; queueItem.Position = new Vector3Int(x, y, z); opaqueBlocksToRebuild.Enqueue(queueItem); } } } } // Depth-sort alpha blended block list. alphaBlendedBlocksToRebuild = alphaBlendedBlocksToRebuild.OrderBy(q => ((q.Position.ToVector3() - renderer.Camera.Position).LengthSquared())).ToList(); // Reset primitive counts. transparentPrimitiveCount = 0; if (!alphaBlendedOnly) { opaquePrimitiveCount = 0; } // Process alpha-blended blocks. foreach (VertexRebuildQueueItem currentQueueItem in alphaBlendedBlocksToRebuild) { Vector3Int worldPosition = new Vector3Int(chunkX * WIDTH + currentQueueItem.Position.X, currentQueueItem.Position.Y, chunkZ * LENGTH + currentQueueItem.Position.Z); alphaBlendedVertices.AddRange(currentQueueItem.Block.GetVertices(worldPosition)); } transparentPrimitiveCount = alphaBlendedVertices.Count / 3; // Process opaque blocks. if (!alphaBlendedOnly) { VertexRebuildQueueItem currentQueueItem; while (opaqueBlocksToRebuild.Count > 0) { currentQueueItem = opaqueBlocksToRebuild.Dequeue(); Vector3Int worldPosition = new Vector3Int(chunkX * WIDTH + currentQueueItem.Position.X, currentQueueItem.Position.Y, chunkZ * LENGTH + currentQueueItem.Position.Z); opaqueVertices.AddRange(currentQueueItem.Block.GetVertices(worldPosition)); } opaquePrimitiveCount = opaqueVertices.Count / 3; } // For some reason list converts to an array in the wrong order, so reverse the lists. // TODO: Fix this. alphaBlendedVertices.Reverse(); if (transparentPrimitiveCount == 0) { transparentVertexBuffer = null; } else { transparentVertexBuffer = new VertexBuffer(renderer.GraphicsDevice, typeof(VertexPositionColorTexture), alphaBlendedVertices.Count, BufferUsage.WriteOnly); transparentVertexBuffer.SetData <VertexPositionColorTexture>(alphaBlendedVertices.ToArray()); } if (!alphaBlendedOnly) { opaqueVertices.Reverse(); if (opaquePrimitiveCount == 0) { opaqueVertexBuffer = null; } else { opaqueVertexBuffer = new VertexBuffer(renderer.GraphicsDevice, typeof(VertexPositionColorTexture), opaqueVertices.Count, BufferUsage.WriteOnly); opaqueVertexBuffer.SetData <VertexPositionColorTexture>(opaqueVertices.ToArray()); } } }