public void BuildMesh() { if (Mesh != null) { frontMeshBuilder.Clear(); } // We use a temporary empty var here in the case of this being ran on a seperate thread. // If this chunk was previously renderable, and is being updated, we don't want it to "flicker" // on the main thread while it is being updated. The main thread should just render the old mesh // until this is completed. bool isEmpty = true; for (int x = 0; x < HSIZE; x++) { for (int y = 0; y < VSIZE; y++) { for (int z = 0; z < HSIZE; z++) { // Grab data about the current block ChunkBlock data = blockData[z, y, x]; Block block = Blocks[z, y, x]; // If it's not air, lets draw! if (block != Block.AIR) { // Calculate the color of the block Color4 voxelColor = block.GetColor4(); // Determine which builder we'll be using VoxelMeshBuilder useBuilder = frontMeshBuilder; // Calculate the position of the block for local and global space. IndexPosition blockPos = new IndexPosition(x, y, z); Vector3 off = (blockPos * Block.CUBE_SIZE); // Get information about this block's neighbors. bool blockAbove, blockBelow, blockLeft, blockForward, blockBackward, blockRight; if (Mesh != null && !dirtyMask[z, y, x]) { // If this block was already calculated and isn't dirty, // we can simply pull the neighbor data from the chunkblock data. blockAbove = data.Up; blockBelow = data.Down; blockLeft = data.Left; blockForward = data.Front; blockBackward = data.Back; blockRight = data.Right; } else { // Search for each block in all 6 directions blockAbove = GetBlockSafe(x, y + 1, z).IsOpaqueTo(block); blockBelow = GetBlockSafe(x, y - 1, z).IsOpaqueTo(block); blockLeft = GetBlockSafe(x - 1, y, z).IsOpaqueTo(block); blockForward = GetBlockSafe(x, y, z + 1).IsOpaqueTo(block); blockBackward = GetBlockSafe(x, y, z - 1).IsOpaqueTo(block); blockRight = GetBlockSafe(x + 1, y, z).IsOpaqueTo(block); // Update the chunkblock data data.SetNeighbors(blockAbove, blockBelow, blockLeft, blockRight, blockForward, blockBackward); } // Only set this chunk to being non-empty if we are actually rendering something if (data.NeighborCount != 6) { isEmpty = false; } // Add each cube face if (!blockLeft) { useBuilder.AddLeft(block, blockPos, off, voxelColor); } if (!blockRight) { useBuilder.AddRight(block, blockPos, off, voxelColor); } if (!blockBackward) { useBuilder.AddBack(block, blockPos, off, voxelColor); } if (!blockForward) { useBuilder.AddFront(block, blockPos, off, voxelColor); } if (!blockAbove) { useBuilder.AddTop(block, blockPos, off, voxelColor); } if (!blockBelow) { useBuilder.AddBottom(block, blockPos, off, voxelColor); } } else { // Default air-blocks to zero so that they are // correctly updated when a block is place there later. data.NeighborCount = 0; } // Update the block data dirtyMask[z, y, x] = false; blockData[z, y, x] = data; } } } IsEmpty = isEmpty; // Swap Buffers VoxelMeshBuilder temp = frontMeshBuilder; frontMeshBuilder = backMeshBuilder; backMeshBuilder = temp; }