예제 #1
0
        public static MeshData CreateGreedyMesh(Chunk chunk)
        {
            var meshData = new MeshData();

            int size = Chunk.Size;

            var world  = chunk.World;
            var offset = chunk.Position * Chunk.Size;

            Block block1;
            Block block2;

            for (bool backFace = true, b = false; b != backFace; backFace = backFace && b, b = !b)
            {
                for (int d = 0; d < 3; d++)
                {
                    int   i, j, k, l, w, h, u = (d + 1) % 3, v = (d + 2) % 3;
                    int[] x    = new int[3];
                    int[] q    = new int[3];
                    int[] mask = new int[size * size];

                    Direction side = Direction.Left;

                    if (d == 0)
                    {
                        side = backFace ? Direction.Left : Direction.Right;
                    }
                    else if (d == 1)
                    {
                        side = backFace ? Direction.Down : Direction.Up;
                    }
                    else if (d == 2)
                    {
                        side = backFace ? Direction.Back : Direction.Forward;
                    }

                    q[d] = 1;
                    for (x[d] = -1; x[d] < size;)
                    {
                        // Compute the mask
                        int n = 0;
                        for (x[v] = 0; x[v] < size; ++x[v])
                        {
                            for (x[u] = 0; x[u] < size; ++x[u])
                            {
                                var block1Pos = new Vector3Int(x[0], x[1], x[2]) + offset;
                                var block2Pos = new Vector3Int(x[0] + q[0], x[1] + q[1], x[2] + q[2]) + offset;

                                block1 = world.GetBlock(block1Pos); // 0 <= x[d] ? WorldManager.Active.GetBlock(new Vecx[0], x[1], x[2]]) : Block.Null;
                                block2 = world.GetBlock(block2Pos); //x[d] < size - 1 ? chunk[x[0] + q[0], x[1] + q[1], x[2] + q[2]] : Block.Null;

                                var one = BlockManager.GetNumericalId(block1.Definition.Identifier);
                                var two = BlockManager.GetNumericalId(block2.Definition.Identifier);


                                if ((one != 0) == (two != 0))
                                {
                                    mask[n] = 0;
                                }
                                else if (one != 0)
                                {
                                    mask[n] = one;
                                }
                                else
                                {
                                    mask[n] = -two;
                                }

                                n++;
                            }
                        }

                        // Increment x[d]
                        ++x[d];

                        // Generate mesh for mask using lexicographic ordering
                        n = 0;
                        for (j = 0; j < size; ++j)
                        {
                            for (i = 0; i < size;)
                            {
                                var c = mask[n];
                                if (c != 0)
                                {
                                    // Compute width
                                    for (w = 1; i + w < size && mask[n + w] == c; ++w)
                                    {
                                        ;
                                    }

                                    // Compute height (this is slightly awkward
                                    var done = false;
                                    for (h = 1; j + h < size; ++h)
                                    {
                                        for (k = 0; k < w; ++k)
                                        {
                                            if (c != mask[n + k + h * size])
                                            {
                                                done = true;
                                                break;
                                            }
                                        }

                                        if (done)
                                        {
                                            break;
                                        }
                                    }

                                    // Add quad
                                    x[u] = i;
                                    x[v] = j;
                                    int[] du = new int[3];
                                    int[] dv = new int[3];

                                    dv[v] = h;
                                    du[u] = w;

                                    c = c <= 0 ? -c : c;

                                    AddFace(new Vector3(x[0], x[1], x[2]),
                                            new Vector3(x[0] + du[0], x[1] + du[1], x[2] + du[2]),
                                            new Vector3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], x[2] + du[2] + dv[2]),
                                            new Vector3(x[0] + dv[0], x[1] + dv[1], x[2] + dv[2]), BlockManager.GetBlock(c), side, w, h, backFace, meshData);

                                    // Zero-out mask
                                    for (l = 0; l < h; ++l)
                                    {
                                        for (k = 0; k < w; ++k)
                                        {
                                            mask[n + k + l * size] = 0;
                                        }
                                    }

                                    // Increment counters and continue
                                    i += w;
                                    n += w;
                                }
                                else
                                {
                                    ++i;
                                    ++n;
                                }
                            }
                        }
                    }
                }
            }


            chunk.Dirty    = false;
            chunk.Rendered = true;

            return(meshData);
        }
예제 #2
0
        private static void AddFace(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, BlockDefinition blockDefinition, Direction side, int width, int height, bool back, MeshData meshData)
        {
            int index = meshData.Vertices.Count;
            int layer = blockDefinition.GetTexture(side).Layer;

            meshData.AddVertex(v1);
            meshData.AddVertex(v2);
            meshData.AddVertex(v3);
            meshData.AddVertex(v4);

            if (side == Direction.Forward || side == Direction.Back)
            {
                meshData.AddUV(new Vector3(0, 0, layer));
                meshData.AddUV(new Vector3(width, 0, layer));
                meshData.AddUV(new Vector3(width, height, layer));
                meshData.AddUV(new Vector3(0, height, layer));
            }
            else
            {
                meshData.AddUV(new Vector3(0, 0, layer));
                meshData.AddUV(new Vector3(0, width, layer));
                meshData.AddUV(new Vector3(height, width, layer));
                meshData.AddUV(new Vector3(height, 0, layer));
            }

            if (back)
            {
                meshData.AddTriangle(0, index);
                meshData.AddTriangle(0, index + 3);
                meshData.AddTriangle(0, index + 2);

                meshData.AddTriangle(0, index + 2);
                meshData.AddTriangle(0, index + 1);
                meshData.AddTriangle(0, index);
                return;
            }

            meshData.AddTriangle(0, index);
            meshData.AddTriangle(0, index + 1);
            meshData.AddTriangle(0, index + 2);

            meshData.AddTriangle(0, index + 2);
            meshData.AddTriangle(0, index + 3);
            meshData.AddTriangle(0, index);
        }