Example #1
0
    public byte GetBitMask(Vector3 voxel)
    {
        Vector3[] neighbours = Util.HorizontalBlockNeighbours(voxel);
        int       value      = 1;
        int       total      = 0;

        for (int i = 0; i < neighbours.Length; i++)
        {
            Chunk   owner;
            Vector3 pos;
            //	TODO: Use out keyword in Blockowner and have it return bool instead of running InChunk for the if statement.
            if (!Util.InChunk(neighbours[i]))
            {
                owner = BlockOwner(neighbours[i]);
                pos   = owner != this ? Util.WrapBlockIndex(neighbours[i]) : neighbours[i];
            }
            else
            {
                owner = this;
                pos   = neighbours[i];
            }

            int x = (int)pos.x, y = (int)pos.y, z = (int)pos.z;

            Blocks.Types type = owner.blockTypes[x, y, z];

            if (Blocks.seeThrough[(int)type])
            {
                total += value;
            }
            value *= 2;
        }
        return((byte)total);
    }
Example #2
0
    //	Player can see through adjacent block
    bool FaceExposed(Vector3 offset, Vector3 blockPosition)
    {
        //	Neighbour position
        Vector3 neighbour = blockPosition + offset;

        Chunk neighbourOwner = BlockOwner(neighbour);

        //	Neighbour is outside this chunk
        if (!neighbourOwner.Equals(this))
        {
            //	Convert local index to neighbouring chunk
            neighbour = Util.WrapBlockIndex(neighbour);
        }
        //	Neighbour is in chunk being drawn
        else
        {
            //	Block not at edge and chunk is solid
            if (composition == Composition.SOLID)
            {
                return(false);
            }
        }

        //	Neighbour has no blocks generated so this area is not exposed
        if (neighbourOwner.status == Chunk.Status.CREATED)
        {
            return(false);
        }
        else
        {
            //	Check if block type is see through
            int x = (int)neighbour.x, y = (int)neighbour.y, z = (int)neighbour.z;

            Blocks.Types type = neighbourOwner.blockTypes[x, y, z];


            return(Blocks.seeThrough[(int)type] || (int)neighbourOwner.blockShapes[x, y, z] != 0);
        }
    }
Example #3
0
    public void SmoothBlocks()
    {
        //	*This is not completely deterministic - the order in which chunks are processed could impact the final terrain in some cases
        if (this.composition != Composition.MIX)
        {
            return;
        }
        //	Remove unwanted blocks from surface
        for (int x = 0; x < World.chunkSize; x++)
        {
            for (int z = 0; z < World.chunkSize; z++)
            {
                int y = column.heightMap[x, z] - (int)this.position.y;

                if (y > World.chunkSize - 1 || y < 0)
                {
                    continue;
                }

                Blocks.Types type = blockTypes[x, y, z];

                if (Blocks.smoothSurface[(int)type])
                {
                    blockBytes[x, y, z] = GetBitMask(new Vector3(x, y, z));                //, true, type);
                    Shapes.RemoveBlocks(this, x, y, z);
                }
            }
        }

        //	Assign shapes to smooth terrain
        for (int x = 0; x < World.chunkSize; x++)
        {
            for (int z = 0; z < World.chunkSize; z++)
            {
                int          height        = column.heightMap[x, z] - (int)this.position.y;
                Shapes.Types previousShape = 0;
                int          previousY     = 0;

                for (int y = height; y > height - 2; y--)
                {
                    if (y > World.chunkSize - 1 || y < 0)
                    {
                        continue;
                    }

                    Blocks.Types type          = blockTypes[x, y, z];
                    Vector3      blockPosition = new Vector3(x, y, z);
                    if (Blocks.smoothSurface[(int)type])
                    {
                        blockBytes[x, y, z] = GetBitMask(blockPosition);
                        Shapes.SetSlopes(this, x, y, z);
                    }

                    //	Avoid overhangs on steep slopes - does not handle iterating between two chunks
                    if (previousShape == Shapes.Types.CORNEROUT && (blockShapes[x, y, z] == Shapes.Types.CORNEROUT || blockShapes[x, y, z] == Shapes.Types.WEDGE))
                    {
                        blockShapes[x, y + 1, z] = Shapes.Types.CORNEROUT2;
                        blockShapes[x, y, z]     = Shapes.Types.CUBE;
                    }
                    else if (previousShape == Shapes.Types.WEDGE)
                    {
                        blockShapes[x, y, z] = Shapes.Types.CUBE;
                    }

                    previousShape = blockShapes[x, y, z];
                    previousY     = y;
                }
            }
        }
    }
Example #4
0
    public void Draw(bool redraw = false)
    {
        //bool debugging = false;

        if (status == Status.DRAWN && !redraw ||
            composition == Composition.EMPTY)
        {
            return;
        }

        Vector3[] offsets = Util.CubeFaceDirections();
        int       solidAdjacentChunkCount = 0;

        for (int i = 0; i < 6; i++)
        {
            Vector3 adjacentPosition = this.position + (offsets[i] * World.chunkSize);

            //World.debug.OutlineChunk(adjacentPosition, Color.green, sizeDivision: 3.5f);

            Chunk adjacentChunk = World.chunks[adjacentPosition];
            if (adjacentChunk.composition == Chunk.Composition.SOLID)
            {
                solidAdjacentChunkCount++;
            }
            if (solidAdjacentChunkCount == 6)
            {
                return;
            }
        }

        world.chunksDrawn++;
        World.debug.Output("Chunks drawn", world.chunksDrawn.ToString());

        List <Vector3> verts = new List <Vector3>();
        List <Vector3> norms = new List <Vector3>();
        List <int>     tris  = new List <int>();
        List <Vector2> UVs   = new List <Vector2>();
        List <Color>   cols  = new List <Color>();

        //	Vertex count for offsetting triangle indices
        int vertexCount       = 0;
        int exposedBlockCount = 0;

        //	Generate mesh data
        for (int x = 0; x < World.chunkSize; x++)
        {
            for (int z = 0; z < World.chunkSize; z++)
            {
                for (int y = 0; y < World.chunkSize; y++)
                {
                    //	Check block type, skip drawing if air
                    Blocks.Types type = blockTypes[x, y, z];
                    if (type == Blocks.Types.AIR)
                    {
                        continue;
                    }
                    if (composition == Composition.SOLID && (Util.InChunk(x, 1) && Util.InChunk(y, 1) && Util.InChunk(z, 1)))
                    {
                        continue;
                    }

                    Vector3 blockPosition = new Vector3(x, y, z);

                    Shapes.Types shape = blockShapes[x, y, z];

                    //	Check if adjacent blocks are exposed
                    bool[] exposedFaces = new bool[6];
                    bool   blockExposed = false;
                    for (int e = 0; e < 6; e++)
                    {
                        exposedFaces[e] = FaceExposed(offsets[e], blockPosition);

                        if (exposedFaces[e] && !blockExposed)
                        {
                            blockExposed = true;
                        }
                    }

                    if (blockExposed)
                    {
                        exposedBlockCount++;
                    }

                    //	Block is not visible so nothing to draw
                    if (!blockExposed && blockBytes[x, y, z] == 0)
                    {
                        continue;
                    }

                    //	Check block shapes and generate mesh data
                    int localVertCount = 0;


                    localVertCount = shapes[(int)blockShapes[x, y, z]].Draw(verts, norms, tris, UVs,
                                                                            blockPosition,
                                                                            blockYRotation[x, y, z],
                                                                            exposedFaces,
                                                                            vertexCount,
                                                                            (int)type);

                    //	Keep count of vertices to offset triangles
                    vertexCount += localVertCount;

                    Color color = (Color)Blocks.colors[(int)blockTypes[x, y, z]];

                    /*if(column.POIWalls != null && column.POIWalls[x,z] == 1) color = Color.black;
                     * else if(column.POIWalls != null && column.POIWalls[x,z] == 2) color = Color.red;
                     * else if(column.POIWalls != null && column.POIWalls[x,z] == 3) color = Color.green;
                     * /*else if(column.POIHeightGradient != null)
                     * {
                     *      float colVal = ((float)column.POIHeightGradient[x,z])/10;
                     *      if(colVal == 0) colVal = 0.05f;
                     *      color = new Color(colVal,colVal,colVal);
                     * }*/


                    cols.AddRange(Enumerable.Repeat(color,
                                                    localVertCount));
                }
            }
        }

        CreateMesh(verts, norms, tris, UVs, cols);
        status = Status.DRAWN;
    }
Example #5
0
    //	Change type of block at voxel and reload chunk(s)
    public bool ChangeBlock(Vector3 voxel, Blocks.Types type, Shapes.Types shape = Shapes.Types.CUBE)
    {
        //	Find owner chunk
        Chunk chunk;

        if (!chunks.TryGetValue(VoxelOwner(voxel), out chunk))
        {
            Debug.Log("can't find chunk at " + VoxelOwner(voxel));
            return(false);
        }

        Column columnTopology = columns[new Vector3(chunk.position.x, 0, chunk.position.z)];

        //	Check highest/lowest blocks in column
        if (type == Blocks.Types.AIR)
        {
            if (voxel.y < columnTopology.lowestPoint)
            {
                columnTopology.lowestPoint = (int)voxel.y;
            }
            if (chunk.composition == Chunk.Composition.SOLID)
            {
                chunk.composition = Chunk.Composition.MIX;
            }
        }
        else
        {
            if (voxel.y > columnTopology.highestPoint)
            {
                columnTopology.highestPoint = (int)voxel.y;
            }
            if (chunk.composition == Chunk.Composition.EMPTY)
            {
                chunk.composition = Chunk.Composition.MIX;
            }
        }

        //	Change block type
        Vector3 local = voxel - chunk.position;

        chunk.blockTypes[(int)local.x, (int)local.y, (int)local.z]  = type;
        chunk.blockShapes[(int)local.x, (int)local.y, (int)local.z] = shape;

        List <Vector3> adjacent = new List <Vector3>();

        //	If the block is at edge(s) get it's adjacent chunk(s)
        if (local.x == 0)
        {
            adjacent.Add((new Vector3(chunk.position.x - chunkSize, chunk.position.y, chunk.position.z)));
        }
        if (local.x == chunkSize - 1)
        {
            adjacent.Add((new Vector3(chunk.position.x + chunkSize, chunk.position.y, chunk.position.z)));
        }
        if (local.y == 0)
        {
            adjacent.Add((new Vector3(chunk.position.x, chunk.position.y - chunkSize, chunk.position.z)));
        }
        if (local.y == chunkSize - 1)
        {
            adjacent.Add((new Vector3(chunk.position.x, chunk.position.y + chunkSize, chunk.position.z)));
        }
        if (local.z == 0)
        {
            adjacent.Add((new Vector3(chunk.position.x, chunk.position.y, chunk.position.z - chunkSize)));
        }
        if (local.z == chunkSize - 1)
        {
            adjacent.Add((new Vector3(chunk.position.x, chunk.position.y, chunk.position.z + chunkSize)));
        }

        if (local.x == 0 && local.z == 0)
        {
            adjacent.Add((new Vector3(chunk.position.x - chunkSize, chunk.position.y, chunk.position.z - chunkSize)));
        }
        if (local.x == chunkSize - 1 && local.z == chunkSize - 1)
        {
            adjacent.Add((new Vector3(chunk.position.x + chunkSize, chunk.position.y, chunk.position.z + chunkSize)));
        }

        if (local.x == 0 && local.z == chunkSize - 1)
        {
            adjacent.Add((new Vector3(chunk.position.x - chunkSize, chunk.position.y, chunk.position.z + chunkSize)));
        }
        if (local.x == chunkSize - 1 && local.z == 0)
        {
            adjacent.Add((new Vector3(chunk.position.x + chunkSize, chunk.position.y, chunk.position.z - chunkSize)));
        }

        //	Update adjacent
        foreach (Vector3 chunkPosition in adjacent)
        {
            Chunk updateChunk = World.chunks[chunkPosition];
            UpdateChunk(chunkPosition);
        }
        //	Update target
        UpdateChunk(chunk.position);

        return(true);
    }