Example #1
0
        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;
        }