Exemplo n.º 1
0
        public static void PrepareTexture(Vector3[] verts, Vector4[] data, Direction direction, TextureCollection[] textureCollections, bool rotated)
        {
            Vector2Int texture  = textureCollections[(int)direction].GetTexture();
            bool       backface = DirectionUtils.IsBackface(direction);

            PrepareTexture(data, verts, direction, texture, rotated, backface);
        }
Exemplo n.º 2
0
        public override void BuildFace(Chunk chunk, Vector3[] vertices, Color32[] palette, ref BlockFace face, bool rotated)
        {
            bool backFace = DirectionUtils.IsBackface(face.side);

            LocalPools pools = Globals.WorkPool.GetPool(chunk.ThreadID);

            Vector3[] verts = pools.vector3ArrayPool.PopExact(4);
            Color32[] 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);
        }
Exemplo n.º 3
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 = Globals.WorkPool.GetPool(chunk.ThreadID);

            Vector3[] verts = pools.vector3ArrayPool.PopExact(4);
            Vector4[] uvs   = pools.vector4ArrayPool.PopExact(4);
            Color32[] 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];
                }

                cols[0] = Colors[d];
                cols[1] = Colors[d];
                cols[2] = Colors[d];
                cols[3] = Colors[d];

                BlockUtils.PrepareTexture(verts, uvs, face.side, Textures, rotated);
                BlockUtils.AdjustColors(chunk, cols, face.light);

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

            pools.color32ArrayPool.Push(cols);
            pools.vector4ArrayPool.Push(uvs);
            pools.vector3ArrayPool.Push(verts);
        }
Exemplo n.º 4
0
        protected override void BuildBox(Chunk chunk, Block block, int minX, int minY, int minZ, int maxX, int maxY,
                                         int maxZ)
        {
            // Order of vertices when building faces:
            //     1--2
            //     |  |
            //     |  |
            //     0--3

            int sizeWithPadding     = sideSize + Env.CHUNK_PADDING_2;
            int sizeWithPaddingPow2 = sizeWithPadding * sizeWithPadding;

            LocalPools  pools  = Globals.WorkPool.GetPool(chunk.ThreadID);
            ChunkBlocks blocks = chunk.Blocks;

            Chunk[] listeners = chunk.Neighbors;

            // Custom blocks have their own rules
            // TODO: Implement custom block colliders

            /*if (block.Custom)
             * {
             *  for (int yy = minY; yy < maxY; yy++)
             *  {
             *      for (int zz = minZ; zz < maxZ; zz++)
             *      {
             *          for (int xx = minX; xx < maxX; xx++)
             *          {
             *              ... // build collider here
             *          }
             *      }
             *  }
             *
             *  return;
             * }*/

            Vector3[] vertexData = pools.vector3ArrayPool.PopExact(4);
            bool[]    mask       = pools.boolArrayPool.PopExact(sideSize * sideSize);

            int n, w, h, l, k, maskIndex;

            #region Top face

            if (listeners[(int)Direction.up] != null ||
                // Don't render faces on world's edges for chunks with no neighbor
                maxY != sideSize)
            {
                Array.Clear(mask, 0, mask.Length);

                // x axis - width
                // z axis - height

                int neighborIndex = Helpers.GetChunkIndex1DFrom3D(minX, maxY, minZ, pow);
                int zOffset       = sizeWithPadding - maxX + minX;

                // Build the mask
                for (int zz = minZ; zz < maxZ; ++zz, neighborIndex += zOffset)
                {
                    n = minX + zz * sideSize;
                    for (int xx = minX; xx < maxX; ++xx, ++n, ++neighborIndex)
                    {
                        // Let's see whether we can merge the faces
                        if (!blocks.GetBlock(neighborIndex).CanCollide)
                        {
                            mask[n] = true;
                        }
                    }
                }

                // Build faces from the mask if it's possible
                for (int zz = minZ; zz < maxZ; ++zz)
                {
                    n = minX + zz * sideSize;
                    for (int xx = minX; xx < maxX;)
                    {
                        if (mask[n] == false)
                        {
                            ++xx;
                            ++n;
                            continue;
                        }

                        bool m = mask[n];

                        // Compute width
                        for (w = 1; xx + w < sideSize && mask[n + w] == m; w++)
                        {
                        }

                        // Compute height
                        for (h = 1; zz + h < sideSize; h++)
                        {
                            for (k = 0; k < w; k++)
                            {
                                maskIndex = n + k + h * sideSize;
                                if (mask[maskIndex] == false || mask[maskIndex] != m)
                                {
                                    goto cont;
                                }
                            }
                        }
cont:

                        // Build the face
                        {
                            vertexData[0] = new Vector3(xx, maxY, zz) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.up][0];
                            vertexData[1] = new Vector3(xx, maxY, zz + h) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.up][1];
                            vertexData[2] = new Vector3(xx + w, maxY, zz + h) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.up][2];
                            vertexData[3] = new Vector3(xx + w, maxY, zz) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.up][3];

                            chunk.ColliderGeometryHandler.Batcher.AddFace(block.physicMaterialID, vertexData, DirectionUtils.IsBackface(Direction.up));
                        }

                        // Zero out the mask. We don't need to process the same fields again
                        for (l = 0; l < h; ++l)
                        {
                            maskIndex = n + l * sideSize;
                            for (k = 0; k < w; ++k, ++maskIndex)
                            {
                                mask[maskIndex] = false;
                            }
                        }

                        xx += w;
                        n  += w;
                    }
                }
            }

            #endregion

            #region Bottom face

            if (listeners[(int)Direction.down] != null ||
                // Don't render faces on world's edges for chunks with no neighbor
                minY != 0)
            {
                Array.Clear(mask, 0, mask.Length);

                // x axis - width
                // z axis - height

                int neighborIndex = Helpers.GetChunkIndex1DFrom3D(minX, minY - 1, minZ, pow);
                int zOffset       = sizeWithPadding - maxX + minX;

                // Build the mask
                for (int zz = minZ; zz < maxZ; ++zz, neighborIndex += zOffset)
                {
                    n = minX + zz * sideSize;
                    for (int xx = minX; xx < maxX; ++xx, ++n, ++neighborIndex)
                    {
                        // Let's see whether we can merge the faces
                        if (!blocks.GetBlock(neighborIndex).CanCollide)
                        {
                            mask[n] = true;
                        }
                    }
                }

                // Build faces from the mask if it's possible
                for (int zz = minZ; zz < maxZ; ++zz)
                {
                    n = minX + zz * sideSize;
                    for (int xx = minX; xx < maxX;)
                    {
                        if (mask[n] == false)
                        {
                            ++xx;
                            ++n;
                            continue;
                        }

                        bool m = mask[n];

                        // Compute width
                        for (w = 1; xx + w < sideSize && mask[n + w] == m; w++)
                        {
                        }

                        // Compute height
                        for (h = 1; zz + h < sideSize; h++)
                        {
                            for (k = 0; k < w; k++)
                            {
                                maskIndex = n + k + h * sideSize;
                                if (mask[maskIndex] == false || mask[maskIndex] != m)
                                {
                                    goto cont;
                                }
                            }
                        }
cont:

                        // Build the face
                        {
                            vertexData[0] = new Vector3(xx, minY, zz) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.down][0];
                            vertexData[1] = new Vector3(xx, minY, zz + h) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.down][1];
                            vertexData[2] = new Vector3(xx + w, minY, zz + h) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.down][2];
                            vertexData[3] = new Vector3(xx + w, minY, zz) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.down][3];

                            chunk.ColliderGeometryHandler.Batcher.AddFace(block.physicMaterialID, vertexData, DirectionUtils.IsBackface(Direction.down));
                        }

                        // Zero out the mask. We don't need to process the same fields again
                        for (l = 0; l < h; ++l)
                        {
                            maskIndex = n + l * sideSize;
                            for (k = 0; k < w; ++k, ++maskIndex)
                            {
                                mask[maskIndex] = false;
                            }
                        }

                        xx += w;
                        n  += w;
                    }
                }
            }

            #endregion

            #region Right face

            if (listeners[(int)Direction.east] != null ||
                // Don't render faces on world's edges for chunks with no neighbor
                maxX != sideSize)
            {
                Array.Clear(mask, 0, mask.Length);

                // y axis - height
                // z axis - width

                int neighborIndex = Helpers.GetChunkIndex1DFrom3D(maxX, minY, minZ, pow);
                int yOffset       = sizeWithPaddingPow2 - (maxZ - minZ) * sizeWithPadding;

                // Build the mask
                for (int yy = minY; yy < maxY; ++yy, neighborIndex += yOffset)
                {
                    n = minZ + yy * sideSize;
                    for (int zz = minZ; zz < maxZ; ++zz, ++n, neighborIndex += sizeWithPadding)
                    {
                        // Let's see whether we can merge the faces
                        if (!blocks.GetBlock(neighborIndex).CanCollide)
                        {
                            mask[n] = true;
                        }
                    }
                }

                // Build faces from the mask if it's possible
                for (int yy = minY; yy < maxY; ++yy)
                {
                    n = minZ + yy * sideSize;
                    for (int zz = minZ; zz < maxZ;)
                    {
                        if (mask[n] == false)
                        {
                            ++zz;
                            ++n;
                            continue;
                        }

                        bool m = mask[n];

                        // Compute width
                        for (w = 1; zz + w < sideSize && mask[n + w] == m; w++)
                        {
                        }

                        // Compute height
                        for (h = 1; yy + h < sideSize; h++)
                        {
                            for (k = 0; k < w; k++)
                            {
                                maskIndex = n + k + h * sideSize;
                                if (mask[maskIndex] == false || mask[maskIndex] != m)
                                {
                                    goto cont;
                                }
                            }
                        }
cont:

                        // Build the face
                        {
                            vertexData[0] = new Vector3(maxX, yy, zz) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.east][0];
                            vertexData[1] = new Vector3(maxX, yy + h, zz) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.east][1];
                            vertexData[2] = new Vector3(maxX, yy + h, zz + w) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.east][2];
                            vertexData[3] = new Vector3(maxX, yy, zz + w) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.east][3];

                            chunk.ColliderGeometryHandler.Batcher.AddFace(block.physicMaterialID, vertexData, DirectionUtils.IsBackface(Direction.east));
                        }

                        // Zero out the mask. We don't need to process the same fields again
                        for (l = 0; l < h; ++l)
                        {
                            maskIndex = n + l * sideSize;
                            for (k = 0; k < w; ++k, ++maskIndex)
                            {
                                mask[maskIndex] = false;
                            }
                        }

                        zz += w;
                        n  += w;
                    }
                }
            }

            #endregion

            #region Left face

            if (listeners[(int)Direction.west] != null ||
                // Don't render faces on world's edges for chunks with no neighbor
                minX != 0)
            {
                Array.Clear(mask, 0, mask.Length);

                // y axis - height
                // z axis - width

                int neighborIndex = Helpers.GetChunkIndex1DFrom3D(minX - 1, minY, minZ, pow);
                int yOffset       = sizeWithPaddingPow2 - (maxZ - minZ) * sizeWithPadding;

                // Build the mask
                for (int yy = minY; yy < maxY; ++yy, neighborIndex += yOffset)
                {
                    n = minZ + yy * sideSize;
                    for (int zz = minZ; zz < maxZ; ++zz, ++n, neighborIndex += sizeWithPadding)
                    {
                        // Let's see whether we can merge the faces
                        if (!blocks.GetBlock(neighborIndex).CanCollide)
                        {
                            mask[n] = true;
                        }
                    }
                }

                // Build faces from the mask if it's possible
                for (int yy = minY; yy < maxY; ++yy)
                {
                    n = minZ + yy * sideSize;
                    for (int zz = minZ; zz < maxZ;)
                    {
                        if (mask[n] == false)
                        {
                            ++zz;
                            ++n;
                            continue;
                        }

                        bool m = mask[n];

                        // Compute width
                        for (w = 1; zz + w < sideSize && mask[n + w] == m; w++)
                        {
                        }

                        // Compute height
                        for (h = 1; yy + h < sideSize; h++)
                        {
                            for (k = 0; k < w; k++)
                            {
                                maskIndex = n + k + h * sideSize;
                                if (mask[maskIndex] == false || mask[maskIndex] != m)
                                {
                                    goto cont;
                                }
                            }
                        }
cont:

                        // Build the face
                        {
                            vertexData[0] = new Vector3(minX, yy, zz) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.west][0];
                            vertexData[1] = new Vector3(minX, yy + h, zz) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.west][1];
                            vertexData[2] = new Vector3(minX, yy + h, zz + w) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.west][2];
                            vertexData[3] = new Vector3(minX, yy, zz + w) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.west][3];

                            chunk.ColliderGeometryHandler.Batcher.AddFace(block.physicMaterialID, vertexData, DirectionUtils.IsBackface(Direction.west));
                        }

                        // Zero out the mask. We don't need to process the same fields again
                        for (l = 0; l < h; ++l)
                        {
                            maskIndex = n + l * sideSize;
                            for (k = 0; k < w; ++k, ++maskIndex)
                            {
                                mask[maskIndex] = false;
                            }
                        }

                        zz += w;
                        n  += w;
                    }
                }
            }

            #endregion

            #region Front face

            if (listeners[(int)Direction.north] != null ||
                // Don't render faces on world's edges for chunks with no neighbor
                maxZ != sideSize)
            {
                Array.Clear(mask, 0, mask.Length);

                // x axis - width
                // y axis - height

                int neighborIndex = Helpers.GetChunkIndex1DFrom3D(minX, minY, maxZ, pow);
                int yOffset       = sizeWithPaddingPow2 - maxX + minX;

                // Build the mask
                for (int yy = minY; yy < maxY; ++yy, neighborIndex += yOffset)
                {
                    n = minX + yy * sideSize;
                    for (int xx = minX; xx < maxX; ++xx, ++n, ++neighborIndex)
                    {
                        // Let's see whether we can merge the faces
                        if (!blocks.GetBlock(neighborIndex).CanCollide)
                        {
                            mask[n] = true;
                        }
                    }
                }

                // Build faces from the mask if it's possible
                for (int yy = minY; yy < maxY; ++yy)
                {
                    n = minX + yy * sideSize;
                    for (int xx = minX; xx < maxX;)
                    {
                        if (mask[n] == false)
                        {
                            ++xx;
                            ++n;
                            continue;
                        }

                        bool m = mask[n];

                        // Compute width
                        for (w = 1; xx + w < sideSize && mask[n + w] == m; w++)
                        {
                        }

                        // Compute height
                        for (h = 1; yy + h < sideSize; h++)
                        {
                            for (k = 0; k < w; k++)
                            {
                                maskIndex = n + k + h * sideSize;
                                if (mask[maskIndex] == false || mask[maskIndex] != m)
                                {
                                    goto cont;
                                }
                            }
                        }
cont:

                        // Build the face
                        {
                            vertexData[0] = new Vector3(xx, yy, maxZ) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.north][0];
                            vertexData[1] = new Vector3(xx, yy + h, maxZ) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.north][1];
                            vertexData[2] = new Vector3(xx + w, yy + h, maxZ) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.north][2];
                            vertexData[3] = new Vector3(xx + w, yy, maxZ) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.north][3];

                            chunk.ColliderGeometryHandler.Batcher.AddFace(block.physicMaterialID, vertexData, DirectionUtils.IsBackface(Direction.north));
                        }

                        // Zero out the mask. We don't need to process the same fields again
                        for (l = 0; l < h; ++l)
                        {
                            maskIndex = n + l * sideSize;
                            for (k = 0; k < w; ++k, ++maskIndex)
                            {
                                mask[maskIndex] = false;
                            }
                        }

                        xx += w;
                        n  += w;
                    }
                }
            }

            #endregion

            #region Back face

            if (listeners[(int)Direction.south] != null ||
                // Don't render faces on world's edges for chunks with no neighbor
                minZ != 0)
            {
                Array.Clear(mask, 0, mask.Length);

                // x axis - width
                // y axis - height

                int neighborIndex = Helpers.GetChunkIndex1DFrom3D(minX, minY, minZ - 1, pow);
                int yOffset       = sizeWithPaddingPow2 - maxX + minX;

                // Build the mask
                for (int yy = minY; yy < maxY; ++yy, neighborIndex += yOffset)
                {
                    n = minX + yy * sideSize;
                    for (int xx = minX; xx < maxX; ++xx, ++n, ++neighborIndex)
                    {
                        // Let's see whether we can merge the faces
                        if (!blocks.GetBlock(neighborIndex).CanCollide)
                        {
                            mask[n] = true;
                        }
                    }
                }

                // Build faces from the mask if it's possible
                for (int yy = minY; yy < maxY; ++yy)
                {
                    n = minX + yy * sideSize;
                    for (int xx = minX; xx < maxX;)
                    {
                        if (mask[n] == false)
                        {
                            ++xx;
                            ++n;
                            continue;
                        }

                        bool m = mask[n];

                        // Compute width
                        for (w = 1; xx + w < sideSize && mask[n + w] == m; w++)
                        {
                        }

                        // Compute height
                        for (h = 1; yy + h < sideSize; h++)
                        {
                            for (k = 0; k < w; k++)
                            {
                                maskIndex = n + k + h * sideSize;
                                if (mask[maskIndex] == false || mask[maskIndex] != m)
                                {
                                    goto cont;
                                }
                            }
                        }
cont:

                        // Build the face
                        {
                            vertexData[0] = new Vector3(xx, yy, minZ) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.south][0];
                            vertexData[1] = new Vector3(xx, yy + h, minZ) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.south][1];
                            vertexData[2] = new Vector3(xx + w, yy + h, minZ) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.south][2];
                            vertexData[3] = new Vector3(xx + w, yy, minZ) * scale +
                                            BlockUtils.paddingOffsets[(int)Direction.south][3];

                            chunk.ColliderGeometryHandler.Batcher.AddFace(block.physicMaterialID, vertexData, DirectionUtils.IsBackface(Direction.south));
                        }

                        // Zero out the mask. We don't need to process the same fields again
                        for (l = 0; l < h; ++l)
                        {
                            maskIndex = n + l * sideSize;
                            for (k = 0; k < w; ++k, ++maskIndex)
                            {
                                mask[maskIndex] = false;
                            }
                        }

                        xx += w;
                        n  += w;
                    }
                }
            }

            #endregion

            pools.boolArrayPool.Push(mask);
            pools.vector3ArrayPool.Push(vertexData);
        }