Ejemplo n.º 1
0
    public override void BuildFace(Chunk chunk, Vector3[] vertices, Color32[] palette, ref BlockFace face, bool rotated)
    {
        bool backFace = DirectionUtils.IsBackface(face.side);

        var pools = Globals.WorkPool.GetPool(chunk.ThreadID);
        var verts = pools.Vector3ArrayPool.PopExact(4);
        var cols  = pools.Color32ArrayPool.PopExact(4);

        {
            verts[0] = vertices[0];
            verts[1] = vertices[1];
            verts[2] = vertices[2];
            verts[3] = vertices[3];

            cols[0] = palette[face.block.Type];
            cols[1] = palette[face.block.Type];
            cols[2] = palette[face.block.Type];
            cols[3] = palette[face.block.Type];

            BlockUtils.AdjustColors(chunk, cols, face.light);

            RenderGeometryBatcher batcher = chunk.RenderGeometryHandler.Batcher;
            batcher.AddFace(face.materialID, verts, cols, backFace);
        }

        pools.Color32ArrayPool.Push(cols);
        pools.Vector3ArrayPool.Push(verts);
    }
Ejemplo n.º 2
0
        public void Reset()
        {
            // Reset chunk events
            m_removalRequested  = false;
            m_firstFinalization = true;

            m_lod = 0;

            m_setBlockQueue.Clear();

            // Reset blocks
            Blocks.Reset();

            PossiblyVisible = false;

            MinRenderX         = EngineSettings.ChunkConfig.Mask;
            MaxRenderX         = 0;
            MinRenderY         = EngineSettings.ChunkConfig.Mask;
            MaxRenderY         = 0;
            MinRenderZ         = EngineSettings.ChunkConfig.Mask;
            MaxRenderZ         = 0;
            m_lowestEmptyBlock = EngineSettings.ChunkConfig.Mask;

            // Reset sections
            NonEmptyBlocks = 0;

            RenderGeometryBatcher.Clear();

            ResetGeometryBoundingMesh();

            StateManager.Reset();
        }
Ejemplo n.º 3
0
    public override void BuildBlock(Chunk chunk, ref Vector3Int localPos, int materialID)
    {
        for (int d = 0; d < 6; d++)
        {
            Direction dir = DirectionUtils.Get(d);

            BlockFace face = new BlockFace
            {
                block      = null,
                pos        = localPos,
                side       = dir,
                light      = new BlockLightData(0),
                materialID = materialID
            };

            BuildFace(chunk, null, null, ref face, false);
        }

        RenderGeometryBatcher batcher = chunk.GeometryHandler.Batcher;

        var  d2      = customMeshConfig.data;
        Rect texture = d2.textures.GetTexture(chunk, ref localPos, Direction.down);

        batcher.AddMeshData(materialID, d2.tris, d2.verts, d2.colors, d2.uvs, ref texture, localPos);
    }
Ejemplo n.º 4
0
 public virtual void BuildMesh(
     Map map, RenderGeometryBatcher batcher, int offsetX, int offsetY, int offsetZ,
     int minX, int maxX, int minY, int maxY, int minZ, int maxZ, int lod,
     LocalPools pools
     )
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 5
0
    public override void BuildBlock(Chunk chunk, Vector3Int localPos)
    {
        Rect texture = customMeshConfig.texture != null
                           ? customMeshConfig.texture.GetTexture(chunk, localPos, Direction.down)
                           : new Rect();

        RenderGeometryBatcher batcher = chunk.GeometryHandler.Batcher;

        batcher.AddMeshData(customMeshConfig.tris, customMeshConfig.verts, texture, localPos);
    }
Ejemplo n.º 6
0
        public Chunk()
        {
            Blocks = new BlockStorage();

            // Associate Chunk with a certain thread and make use of its memory pool
            // This is necessary in order to have lock-free caches
            ThreadID = Globals.WorkPool.GetThreadIDFromIndex(s_id++);
            Pools    = Globals.WorkPool.GetPool(ThreadID);

            RenderGeometryBatcher   = new RenderGeometryBatcher(Globals.CubeMeshGeometryBuilder, this);
            BBoxVertices            = new List <Vector3>();
            BBoxVerticesTransformed = new List <Vector3>();

            StateManager = new ChunkStateManagerClient(this);
        }
Ejemplo n.º 7
0
        public void Build(RenderGeometryBatcher batcher, ref BlockData block, BlockFace face, bool backFace, ref Vector3[] vecs, LocalPools pools)
        {
            int iface = (int)face;

            // Randomize the color a bit
            Color32 color = BlockDatabase.GetBlockInfo(block.BlockType).Color;

            if (block.BlockType != BlockType.None)
            {
                float value = m_noise.GetValue(vecs[0] + vecs[1] + vecs[2] + vecs[3]); // -1.0f..1.0f
                float noise = (255.0f * value) * 0.02f;                                // Deviation of 0.02f points from the original
                int   n     = (int)noise;
                byte  r     = (byte)Math.Max(0, Math.Min(color.r + n, 255));
                byte  g     = (byte)Math.Max(0, Math.Min(color.g + n, 255));
                byte  b     = (byte)Math.Max(0, Math.Min(color.b + n, 255));
                color = new Color32(r, g, b, color.a);
            }

            VertexData[]      vertexData      = pools.PopVertexDataArray(4);
            VertexDataFixed[] vertexDataFixed = pools.PopVertexDataFixedArray(4);
            {
                for (int i = 0; i < 4; i++)
                {
                    vertexData[i] = pools.PopVertexData();
                }

                for (int i = 0; i < 4; i++)
                {
                    vertexData[i].Vertex = vecs[i];
                    vertexData[i].Color  = color;
                    vertexData[i].UV     = AddFaceUV(i, GetTexture(iface), backFace);
                    vertexData[i].Normal = SNormals[iface][i];
                }

                for (int i = 0; i < 4; i++)
                {
                    vertexDataFixed[i] = VertexDataUtils.ClassToStruct(vertexData[i]);
                }
                batcher.AddFace(vertexDataFixed, backFace);

                for (int i = 0; i < 4; i++)
                {
                    pools.PushVertexData(vertexData[i]);
                }
            }
            pools.PushVertexDataFixedArray(vertexDataFixed);
            pools.PushVertexDataArray(vertexData);
        }
Ejemplo n.º 8
0
    public override void BuildFace(Chunk chunk, Vector3[] vertices, Color32[] palette, ref BlockFace face, bool rotated)
    {
        var d = connectedMeshConfig.dataDir[(int)face.side];

        var tris = d.tris;

        if (tris == null)
        {
            return;
        }

        var verts    = d.verts;
        var uvs      = d.uvs;
        var textures = d.textures;
        var colors   = d.colors;

        Rect        rect;
        ChunkBlocks blocks = chunk.blocks;

        RenderGeometryBatcher batcher = chunk.GeometryHandler.Batcher;

        Vector3Int sidePos = face.pos.Add(face.side);

        if (connectedMeshConfig.connectsToSolid && blocks.Get(ref sidePos).Solid)
        {
            rect = textures.GetTexture(chunk, ref face.pos, face.side);
            batcher.AddMeshData(face.materialID, tris, verts, colors, uvs, ref rect, face.pos);
        }
        else if (connectedMeshConfig.connectsToTypes.Length != 0)
        {
            int neighborType = blocks.Get(ref sidePos).Type;
            for (int i = 0; i < connectedMeshConfig.connectsToTypes.Length; i++)
            {
                if (neighborType == connectedMeshConfig.connectsToTypes[i])
                {
                    rect = textures.GetTexture(chunk, ref face.pos, face.side);
                    batcher.AddMeshData(face.materialID, tris, verts, colors, uvs, ref rect, face.pos);
                    break;
                }
            }
        }

        var d2 = customMeshConfig.data;

        rect = d2.textures.GetTexture(chunk, ref face.pos, Direction.down);
        batcher.AddMeshData(face.materialID, d2.tris, d2.verts, d2.colors, d2.uvs, ref rect, face.pos);
    }
Ejemplo n.º 9
0
    public override void BuildFace(Chunk chunk, Vector3[] vertices, Color32[] palette, ref BlockFace face, bool rotated)
    {
        bool backFace = DirectionUtils.IsBackface(face.side);
        int  d        = DirectionUtils.Get(face.side);

        LocalPools pools = chunk.pools;
        var        verts = pools.Vector3ArrayPool.PopExact(4);
        var        cols  = pools.Color32ArrayPool.PopExact(4);

        {
            if (vertices == null)
            {
                Vector3 pos = face.pos;

                verts[0] = pos + BlockUtils.PaddingOffsets[d][0];
                verts[1] = pos + BlockUtils.PaddingOffsets[d][1];
                verts[2] = pos + BlockUtils.PaddingOffsets[d][2];
                verts[3] = pos + BlockUtils.PaddingOffsets[d][3];

                cols[0] = colors[d];
                cols[1] = colors[d];
                cols[2] = colors[d];
                cols[3] = colors[d];
            }
            else
            {
                verts[0] = vertices[0];
                verts[1] = vertices[1];
                verts[2] = vertices[2];
                verts[3] = vertices[3];

                cols[0] = colors[d];
                cols[1] = colors[d];
                cols[2] = colors[d];
                cols[3] = colors[d];
            }

            BlockUtils.AdjustColors(chunk, cols, face.light);

            RenderGeometryBatcher batcher = chunk.GeometryHandler.Batcher;
            batcher.AddFace(face.materialID, verts, cols, backFace);
        }

        pools.Color32ArrayPool.Push(cols);
        pools.Vector3ArrayPool.Push(verts);
    }
Ejemplo n.º 10
0
    public override void BuildBlock(Chunk chunk, ref Vector3Int localPos, int materialID)
    {
        var  data    = customMeshConfig.data;
        Rect texture = data.textures != null
                           ? data.textures.GetTexture(chunk, ref localPos, Direction.down)
                           : new Rect();

        RenderGeometryBatcher batcher = chunk.GeometryHandler.Batcher;

        if (data.uvs == null)
        {
            batcher.AddMeshData(materialID, data.tris, data.verts, data.colors, localPos);
        }
        else if (data.colors == null)
        {
            batcher.AddMeshData(materialID, data.tris, data.verts, data.uvs, ref texture, localPos);
        }
        else
        {
            batcher.AddMeshData(materialID, data.tris, data.verts, data.colors, data.uvs, ref texture, localPos);
        }
    }
Ejemplo n.º 11
0
    public override void BuildFace(Chunk chunk, Vector3[] vertices, Color32[] palette, ref BlockFace face, bool rotated)
    {
        bool backface = DirectionUtils.IsBackface(face.side);
        int  d        = DirectionUtils.Get(face.side);

        var pools = Globals.WorkPool.GetPool(chunk.ThreadID);
        var verts = pools.Vector3ArrayPool.PopExact(4);
        var uvs   = pools.Vector2ArrayPool.PopExact(4);
        var cols  = pools.Color32ArrayPool.PopExact(4);

        {
            if (vertices == null)
            {
                Vector3 pos = face.pos;

                verts[0] = pos + BlockUtils.PaddingOffsets[d][0];
                verts[1] = pos + BlockUtils.PaddingOffsets[d][1];
                verts[2] = pos + BlockUtils.PaddingOffsets[d][2];
                verts[3] = pos + BlockUtils.PaddingOffsets[d][3];
            }
            else
            {
                verts[0] = vertices[0];
                verts[1] = vertices[1];
                verts[2] = vertices[2];
                verts[3] = vertices[3];
            }

            BlockUtils.PrepareTexture(chunk, ref face.pos, uvs, face.side, textures, rotated);
            BlockUtils.PrepareColors(chunk, cols, face.light);

            RenderGeometryBatcher batcher = chunk.RenderGeometryHandler.Batcher;
            batcher.AddFace(face.materialID, verts, cols, uvs, backface);
        }

        pools.Color32ArrayPool.Push(cols);
        pools.Vector2ArrayPool.Push(uvs);
        pools.Vector3ArrayPool.Push(verts);
    }
Ejemplo n.º 12
0
    public override void BuildBlock(Chunk chunk, Vector3Int localPos, Vector3Int globalPos)
    {
        Rect texture;
        RenderGeometryBatcher batcher = chunk.GeometryHandler.Batcher;
        WorldBlocks           blocks  = chunk.world.blocks;

        for (int d = 0; d < 6; d++)
        {
            Direction dir = DirectionUtils.Get(d);
            if (!connectedMeshConfig.directionalTris.ContainsKey(dir))
            {
                continue;
            }

            if (connectedMeshConfig.connectsToSolid && blocks.GetBlock(globalPos + dir).IsSolid(DirectionUtils.Opposite(dir)))
            {
                texture = connectedMeshConfig.texture.GetTexture(chunk, localPos, globalPos, dir);
                batcher.AddMeshData(connectedMeshConfig.directionalTris[dir], connectedMeshConfig.directionalVerts[dir], texture, localPos);
            }
            else if (connectedMeshConfig.connectsToTypes.Length != 0)
            {
                int neighborType = blocks.Get(globalPos.Add(dir)).Type;
                for (int i = 0; i < connectedMeshConfig.connectsToTypes.Length; i++)
                {
                    if (neighborType == connectedMeshConfig.connectsToTypes[i])
                    {
                        texture = connectedMeshConfig.texture.GetTexture(chunk, localPos, globalPos, dir);
                        batcher.AddMeshData(connectedMeshConfig.directionalTris[dir], connectedMeshConfig.directionalVerts[dir], texture, localPos);
                        break;
                    }
                }
            }
        }

        texture = customMeshConfig.texture.GetTexture(chunk, localPos, globalPos, Direction.down);
        batcher.AddMeshData(customMeshConfig.tris, customMeshConfig.verts, texture, localPos);
    }
Ejemplo n.º 13
0
 public ARenderGeometryHandler(string prefabName)
 {
     Batcher = new RenderGeometryBatcher(prefabName);
 }
Ejemplo n.º 14
0
    public override void BuildBlock(Chunk chunk, ref Vector3Int localPos, int materialID)
    {
        var pools = Globals.WorkPool.GetPool(chunk.ThreadID);
        RenderGeometryBatcher batcher = chunk.RenderGeometryHandler.Batcher;

        // Using the block positions hash is much better for random numbers than saving the offset and height in the block data
        int hash = localPos.GetHashCode();

        float blockHeight = (hash & 63) * coef * Env.BlockSize;

        hash *= 39;
        float offsetX = (hash & 63) * coef * Env.BlockSizeHalf - Env.BlockSizeHalf * 0.5f;

        hash *= 39;
        float offsetZ = (hash & 63) * coef * Env.BlockSizeHalf - Env.BlockSizeHalf * 0.5f;

        // Converting the position to a vector adjusts it based on block size and gives us real world coordinates for x, y and z
        Vector3 vPos = localPos;

        vPos += new Vector3(offsetX, 0, offsetZ);

        float x1 = vPos.x - BlockUtils.blockPadding;
        float x2 = vPos.x + BlockUtils.blockPadding + Env.BlockSize;
        float y1 = vPos.y - BlockUtils.blockPadding;
        float y2 = vPos.y + BlockUtils.blockPadding + blockHeight;
        float z1 = vPos.z - BlockUtils.blockPadding;
        float z2 = vPos.z + BlockUtils.blockPadding + Env.BlockSize;

        var verts  = pools.Vector3ArrayPool.PopExact(4);
        var uvs    = pools.Vector2ArrayPool.PopExact(4);
        var colors = pools.Color32ArrayPool.PopExact(4);

        BlockUtils.PrepareTexture(chunk, ref localPos, uvs, Direction.north, texture, false);

        // TODO: How do I make sure that if I supply no color value, white is used?
        // TODO: These colors could be removed and memory would be saved
        {
            colors[0] = new Color32(255, 255, 255, 255);
            colors[1] = new Color32(255, 255, 255, 255);
            colors[2] = new Color32(255, 255, 255, 255);
            colors[3] = new Color32(255, 255, 255, 255);
        }

        {
            verts[0] = new Vector3(x1, y1, z2);
            verts[1] = new Vector3(x1, y2, z2);
            verts[2] = new Vector3(x2, y2, z1);
            verts[3] = new Vector3(x2, y1, z1);
            batcher.AddFace(materialID, verts, colors, uvs, false);
        }
        {
            verts[0] = new Vector3(x2, y1, z1);
            verts[1] = new Vector3(x2, y2, z1);
            verts[2] = new Vector3(x1, y2, z2);
            verts[3] = new Vector3(x1, y1, z2);
            batcher.AddFace(materialID, verts, colors, uvs, false);
        }
        {
            verts[0] = new Vector3(x2, y1, z2);
            verts[1] = new Vector3(x2, y2, z2);
            verts[2] = new Vector3(x1, y2, z1);
            verts[3] = new Vector3(x1, y1, z1);
            batcher.AddFace(materialID, verts, colors, uvs, false);
        }
        {
            verts[0] = new Vector3(x1, y1, z1);
            verts[1] = new Vector3(x1, y2, z1);
            verts[2] = new Vector3(x2, y2, z2);
            verts[3] = new Vector3(x2, y1, z2);
            batcher.AddFace(materialID, verts, colors, uvs, false);
        }

        pools.Color32ArrayPool.Push(colors);
        pools.Vector2ArrayPool.Push(uvs);
        pools.Vector3ArrayPool.Push(verts);
    }
 protected ARenderGeometryHandler(string prefabName, Material[] materials)
 {
     Batcher = new RenderGeometryBatcher(prefabName, materials);
 }
Ejemplo n.º 16
0
 public void Build()
 {
     // Prepare chunk for rendering
     RenderGeometryBatcher.Commit();
 }
Ejemplo n.º 17
0
        public override void BuildMesh(
            Map map, RenderGeometryBatcher batcher, int offsetX, int offsetY, int offsetZ,
            int minX, int maxX, int minY, int maxY, int minZ, int maxZ, int lod,
            LocalPools pools
            )
        {
            BlockFace face = 0;

            int stepSize = 1 << lod;

            Assert.IsTrue(lod <= EngineSettings.ChunkConfig.LogSize); // LOD can't be bigger than chunk size
            int width = EngineSettings.ChunkConfig.Size >> lod;

            int[] mins  = { minX >> lod, minY >> lod, minZ >> lod };
            int[] maxes = { maxX >> lod, maxY >> lod, maxZ >> lod };

            int[] x  = { 0, 0, 0 };                                                    // Relative position of a block
            int[] xx = { 0, 0, 0 };                                                    // Relative position of a block after applying lod
            int[] q  = { 0, 0, 0 };                                                    // Direction in which we compare neighbors when building mask (q[d] is our current direction)
            int[] du = { 0, 0, 0 };                                                    // Width in a given dimension (du[u] is our current dimension)
            int[] dv = { 0, 0, 0 };                                                    // Height in a given dimension (dv[v] is our current dimension)
            int[] s  = { map.VoxelLogScaleX, map.VoxelLogScaleY, map.VoxelLogScaleZ }; // Scale in each dimension

            BlockData[] mask = pools.PopBlockDataArray(width * width);
            Vector3[]   vecs = pools.PopVector3Array(4);

            // Iterate over 3 dimensions. Once for front faces, once for back faces
            for (int dd = 0; dd < 2 * 3; dd++)
            {
                int d = dd % 3;
                int u = (d + 1) % 3;
                int v = (d + 2) % 3;

                x[0] = 0;
                x[1] = 0;
                x[2] = 0;

                q[0] = 0;
                q[1] = 0;
                q[2] = 0;
                q[d] = stepSize << s[d];

                // Determine which side we're meshing
                bool backFace = dd < 3;
                switch (dd)
                {
                case 0: face = BlockFace.Left; break;

                case 3: face = BlockFace.Right; break;

                case 1: face = BlockFace.Bottom; break;

                case 4: face = BlockFace.Top; break;

                case 2: face = BlockFace.Back; break;

                case 5: face = BlockFace.Front; break;
                }

                // Move through the dimension from front to back
                for (x[d] = mins[d] - 1; x[d] <= maxes[d];)
                {
                    // Compute the mask
                    int n = 0;

                    for (x[v] = 0; x[v] < mins[v]; x[v]++)
                    {
                        for (x[u] = 0; x[u] < width; x[u]++)
                        {
                            mask[n++] = BlockData.Air;
                        }
                    }

                    for (x[v] = mins[v]; x[v] <= maxes[v]; x[v]++)
                    {
                        for (x[u] = 0; x[u] < mins[u]; x[u]++)
                        {
                            mask[n++] = BlockData.Air;
                        }

                        for (x[u] = mins[u]; x[u] <= maxes[u]; x[u]++)
                        {
                            int realX = (x[0] << lod << s[0]) + offsetX;
                            int realY = (x[1] << lod << s[1]) + offsetY;
                            int realZ = (x[2] << lod << s[2]) + offsetZ;

                            BlockData voxelFace0 = map.GetBlock(realX, realY, realZ);
                            BlockData voxelFace1 = map.GetBlock(realX + q[0], realY + q[1], realZ + q[2]);

                            mask[n++] = (voxelFace0.IsSolid() && voxelFace1.IsSolid())
                                            ? BlockData.Air
                                            : (backFace ? voxelFace1 : voxelFace0);
                        }

                        for (x[u] = maxes[u] + 1; x[u] < width; x[u]++)
                        {
                            mask[n++] = BlockData.Air;
                        }
                    }

                    for (x[v] = maxes[v] + 1; x[v] < width; x[v]++)
                    {
                        for (x[u] = 0; x[u] < width; x[u]++)
                        {
                            mask[n++] = BlockData.Air;
                        }
                    }

                    x[d]++;
                    n = 0;

                    // Build faces from the mask if it's possible
                    int j;
                    for (j = 0; j < width; j++)
                    {
                        int i;
                        for (i = 0; i < width;)
                        {
                            if (mask[n].IsEmpty())
                            {
                                i++;
                                n++;
                                continue;
                            }

                            BlockType type = mask[n].BlockType;

                            // Compute width & height
                            const int w = 1;
                            const int h = 1;

                            // Determine whether we really want to build this face
                            // TODO: Skip bottom faces at the bottom of the world
                            bool buildFace = true;
                            if (buildFace)
                            {
                                // Prepare face coordinates and dimensions
                                x[u] = i;
                                x[v] = j;

                                xx[0] = ((x[0] << lod) << s[0]) + offsetX;
                                xx[1] = ((x[1] << lod) << s[1]) + offsetY;
                                xx[2] = ((x[2] << lod) << s[2]) + offsetZ;

                                du[0] = du[1] = du[2] = 0;
                                dv[0] = dv[1] = dv[2] = 0;
                                du[u] = (w << lod) << s[u];
                                dv[v] = (h << lod) << s[v];

                                // Face vertices
                                Vector3Int v1 = new Vector3Int(
                                    xx[0], xx[1], xx[2]
                                    );
                                Vector3Int v2 = new Vector3Int(
                                    xx[0] + du[0], xx[1] + du[1], xx[2] + du[2]
                                    );
                                Vector3Int v3 = new Vector3Int(
                                    xx[0] + du[0] + dv[0], xx[1] + du[1] + dv[1], xx[2] + du[2] + dv[2]
                                    );
                                Vector3Int v4 = new Vector3Int(
                                    xx[0] + dv[0], xx[1] + dv[1], xx[2] + dv[2]
                                    );

                                // Face vertices transformed to world coordinates
                                // 0--1
                                // |  |
                                // |  |
                                // 3--2
                                vecs[0] = new Vector3(v4.X, v4.Y, v4.Z);
                                vecs[1] = new Vector3(v3.X, v3.Y, v3.Z);
                                vecs[2] = new Vector3(v2.X, v2.Y, v2.Z);
                                vecs[3] = new Vector3(v1.X, v1.Y, v1.Z);

                                // Build the face
                                IFaceBuilder builder = BlockDatabase.GetFaceBuilder(type);
                                builder.Build(batcher, ref mask[n], face, backFace, ref vecs, pools);
                            }

                            // Zero out the mask
                            int l;
                            for (l = 0; l < h; ++l)
                            {
                                int k;
                                for (k = 0; k < w; ++k)
                                {
                                    mask[n + k + l * width] = BlockData.Air;
                                }
                            }

                            i += w;
                            n += w;
                        }
                    }
                }
            }

            pools.PushBlockDataArray(mask);
            pools.PushVector3Array(vecs);
        }