Exemplo n.º 1
0
        public void SetData(IReadableDataset <VoxelData> readableData, IWriteableDataset <VoxelData> writeableData)
        {
            readable  = readableData;
            writeable = writeableData;

            for (int i = 0; i < m_dirty.Length; i++)
            {
                m_dirty[i] = true;
            }
        }
Exemplo n.º 2
0
        public void Rebuild(IReadableDataset <VoxelData> data, IntRect region)
        {
            if (region.size.x <= 0 || region.size.y <= 0)
            {
                ClearBuffers();
                AssignMeshData();
                transform.position = nextPosition;
                return;
            }

            m_rebuildTask = new Task(() => {
                ClearBuffers();
                GenerateMesh(data, region, m_meshOut);
            });
            m_rebuildTask.Start();
        }
Exemplo n.º 3
0
        private void GenerateGreedyQuad(IReadableDataset <VoxelData> data, IntRect region, int x, int y, MeshOutput o)
        {
            float voxelSize = m_settings.voxelSize;

            int startX = x;
            int startY = y;
            int endX   = x;
            int endY   = y;

            VoxelData compare = data.Sample(region.origin.x + x, region.origin.y + y);

            for (int xx = x + 1; xx < region.size.x - 1; xx++)
            {
                if (o.batched[y * m_maxWidth + xx] == true)
                {
                    break;
                }                                                          // Encountered another batch, stop expanding

                VoxelData a = data.Sample(region.origin.x + xx + 1, region.origin.y + y);
                VoxelData b = data.Sample(region.origin.x + xx + 1, region.origin.y + y + 1);

                if (compare.CompareWithoutExtent(a) && compare.CompareWithoutExtent(b))
                {
                    endX = xx;
                }
                else
                {
                    break;
                }              // Change in voxel data detected, stop extending
            }

            bool validUp = true;

            for (int yy = y + 1; yy < region.size.y - 1 && validUp == true; yy++)
            {
                for (int xx = startX; xx <= endX && validUp == true; xx++)
                {
                    if (o.batched[yy * m_maxWidth + xx] == true)
                    {
                        validUp = false; break;
                    }                                                                            // Encountered another batch, stop expanding

                    VoxelData a = data.Sample(region.origin.x + xx + 1, region.origin.y + yy + 1);
                    VoxelData b = data.Sample(region.origin.x + xx, region.origin.y + yy + 1);

                    if (compare.CompareWithoutExtent(a) == false || compare.CompareWithoutExtent(b) == false)
                    {
                        validUp = false;
                        break;
                    }
                }

                if (validUp == true)   // Collect line
                {
                    endY = yy;
                }
            }

            // Mark batch
            for (int yy = startY; yy <= endY; yy++)
            {
                for (int xx = startX; xx <= endX; xx++)
                {
                    o.batched[yy * m_maxWidth + xx] = true;
                }
            }

            // Build quad mesh data
            float x0 = startX * voxelSize;
            float x1 = (endX + 1) * voxelSize;
            float y0 = startY * voxelSize;
            float y1 = (endY + 1) * voxelSize;

            Vector3 v0 = new Vector3(x0, y0);
            Vector3 v1 = new Vector3(x0, y1);
            Vector3 v2 = new Vector3(x1, y1);
            Vector3 v3 = new Vector3(x1, y0);

            int vcount = o.verts.Count;

            o.verts.Add(v0);
            o.verts.Add(v1);
            o.verts.Add(v2);
            o.verts.Add(v3);

            o.tris.Add(vcount);
            o.tris.Add(vcount + 1);
            o.tris.Add(vcount + 2);

            o.tris.Add(vcount);
            o.tris.Add(vcount + 2);
            o.tris.Add(vcount + 3);

            o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
            o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
            o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
            o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);
        }
Exemplo n.º 4
0
        private void GenerateMesh(IReadableDataset <VoxelData> data, IntRect region, MeshOutput o)
        {
            float voxelSize = m_settings.voxelSize;

            for (int y = 0; y < region.size.y - 1; y++)
            {
                for (int x = 0; x < region.size.x - 1; x++)
                {
                    if (o.batched[y * m_maxWidth + x] == true)
                    {
                        continue;
                    }                                                                                      // Cell is already a part of existing batch, skip it...

                    VoxelData bottomLeft  = data.Sample(region.origin.x + x, region.origin.y + y);         // v = 1
                    VoxelData bottomRight = data.Sample(region.origin.x + x + 1, region.origin.y + y);     // v = 2
                    VoxelData topRight    = data.Sample(region.origin.x + x + 1, region.origin.y + y + 1); // v = 4
                    VoxelData topLeft     = data.Sample(region.origin.x + x, region.origin.y + y + 1);     // v = 8

                    byte index = 0;
                    if ((bottomLeft.cell & VoxelData.CELL_MASK_SOLID) > 0)
                    {
                        index |= (1 << 0);
                    }
                    if ((bottomRight.cell & VoxelData.CELL_MASK_SOLID) > 0)
                    {
                        index |= (1 << 1);
                    }
                    if ((topRight.cell & VoxelData.CELL_MASK_SOLID) > 0)
                    {
                        index |= (1 << 2);
                    }
                    if ((topLeft.cell & VoxelData.CELL_MASK_SOLID) > 0)
                    {
                        index |= (1 << 3);
                    }

                    float x0 = x * voxelSize;
                    float x1 = (x + 1) * voxelSize;
                    float y0 = y * voxelSize;
                    float y1 = (y + 1) * voxelSize;

                    switch (index)
                    {
                    case 0: break;      // Empty cell

                    case 1:
                    {
                        float xstep = bottomLeft.GetExtentRightNormalized() * voxelSize;
                        float ystep = bottomLeft.GetExtentTopNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x0, y0);
                        Vector3 v1 = new Vector3(x0, y0 + ystep);
                        Vector3 v2 = new Vector3(x0 + xstep, y0);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);

                        AppendContour(v1, v2, o);
                    }
                    break;

                    case 2:
                    {
                        float xstep = bottomRight.GetExtentLeftNormalized() * voxelSize;
                        float ystep = bottomRight.GetExtentTopNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x1 - xstep, y0);
                        Vector3 v1 = new Vector3(x1, y0 + ystep);
                        Vector3 v2 = new Vector3(x1, y0);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);

                        AppendContour(v0, v1, o);
                    }
                    break;

                    case 3:
                    {
                        float ystep  = bottomLeft.GetExtentTopNormalized() * voxelSize;
                        float ystep2 = bottomRight.GetExtentTopNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x0, y0);
                        Vector3 v1 = new Vector3(x0, y0 + ystep);
                        Vector3 v2 = new Vector3(x1, y0 + ystep2);
                        Vector3 v3 = new Vector3(x1, y0);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);
                        o.verts.Add(v3);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 2);
                        o.tris.Add(vcount + 3);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);

                        AppendContour(v1, v2, o);
                    }
                    break;

                    case 4:
                    {
                        float xstep = topRight.GetExtentLeftNormalized() * voxelSize;
                        float ystep = topRight.GetExtentBottomNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x1, y1);
                        Vector3 v1 = new Vector3(x1, y1 - ystep);
                        Vector3 v2 = new Vector3(x1 - xstep, y1);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);

                        AppendContour(v1, v2, o);
                    }
                    break;

                    case 5:
                    {
                        float xstep  = bottomLeft.GetExtentRightNormalized() * voxelSize;
                        float ystep  = bottomLeft.GetExtentTopNormalized() * voxelSize;
                        float xstep2 = topRight.GetExtentLeftNormalized() * voxelSize;
                        float ystep2 = topRight.GetExtentBottomNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x0, y0);
                        Vector3 v1 = new Vector3(x0, y0 + ystep);
                        Vector3 v2 = new Vector3(x0 + xstep, y0);
                        Vector3 v3 = new Vector3(x1 - xstep2, y1);
                        Vector3 v4 = new Vector3(x1, y1);
                        Vector3 v5 = new Vector3(x1, y1 - ystep2);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);
                        o.verts.Add(v3);
                        o.verts.Add(v4);
                        o.verts.Add(v5);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.tris.Add(vcount + 3);
                        o.tris.Add(vcount + 4);
                        o.tris.Add(vcount + 5);

                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 3);
                        o.tris.Add(vcount + 2);

                        o.tris.Add(vcount + 2);
                        o.tris.Add(vcount + 3);
                        o.tris.Add(vcount + 5);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v5) / m_settings.voxelSize);

                        AppendContour(v1, v3, o);
                        AppendContour(v5, v2, o);
                    }
                    break;

                    case 6:
                    {
                        float xstep  = topRight.GetExtentLeftNormalized() * voxelSize;
                        float xstep2 = bottomRight.GetExtentLeftNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x1 - xstep2, y0);
                        Vector3 v1 = new Vector3(x1 - xstep, y1);
                        Vector3 v2 = new Vector3(x1, y1);
                        Vector3 v3 = new Vector3(x1, y0);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);
                        o.verts.Add(v3);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 2);
                        o.tris.Add(vcount + 3);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);

                        AppendContour(v0, v1, o);
                    }
                    break;

                    case 7:
                    {
                        float xstep = topRight.GetExtentLeftNormalized() * voxelSize;
                        float ystep = bottomLeft.GetExtentTopNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x0, y0);
                        Vector3 v1 = new Vector3(x0, y0 + ystep);
                        Vector3 v2 = new Vector3(x1 - xstep, y1);
                        Vector3 v3 = new Vector3(x1, y1);
                        Vector3 v4 = new Vector3(x1, y0);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);
                        o.verts.Add(v3);
                        o.verts.Add(v4);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 4);

                        o.tris.Add(vcount + 4);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.tris.Add(vcount + 4);
                        o.tris.Add(vcount + 2);
                        o.tris.Add(vcount + 3);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize);

                        AppendContour(v1, v2, o);
                    }
                    break;

                    case 8:
                    {
                        float xstep = topLeft.GetExtentRightNormalized() * voxelSize;
                        float ystep = topLeft.GetExtentBottomNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x0, y1 - ystep);
                        Vector3 v1 = new Vector3(x0, y1);
                        Vector3 v2 = new Vector3(x0 + xstep, y1);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);

                        AppendContour(v2, v0, o);
                    }
                    break;

                    case 9:
                    {
                        float xstep  = topLeft.GetExtentRightNormalized() * voxelSize;
                        float xstep2 = bottomLeft.GetExtentRightNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x0, y0);
                        Vector3 v1 = new Vector3(x0, y1);
                        Vector3 v2 = new Vector3(x0 + xstep, y1);
                        Vector3 v3 = new Vector3(x0 + xstep2, y0);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);
                        o.verts.Add(v3);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 2);
                        o.tris.Add(vcount + 3);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);

                        AppendContour(v2, v3, o);
                    }
                    break;

                    case 10:
                    {
                        float xstep  = topLeft.GetExtentRightNormalized() * voxelSize;
                        float ystep  = topLeft.GetExtentBottomNormalized() * voxelSize;
                        float xstep2 = bottomRight.GetExtentLeftNormalized() * voxelSize;
                        float ystep2 = bottomRight.GetExtentTopNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x0, y1 - ystep);
                        Vector3 v1 = new Vector3(x0, y1);
                        Vector3 v2 = new Vector3(x0 + xstep, y1);
                        Vector3 v3 = new Vector3(x1 - xstep2, y0);
                        Vector3 v4 = new Vector3(x1, y0 + ystep2);
                        Vector3 v5 = new Vector3(x1, y0);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);
                        o.verts.Add(v3);
                        o.verts.Add(v4);
                        o.verts.Add(v5);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.tris.Add(vcount + 3);
                        o.tris.Add(vcount + 4);
                        o.tris.Add(vcount + 5);

                        o.tris.Add(vcount + 3);
                        o.tris.Add(vcount + 0);
                        o.tris.Add(vcount + 2);

                        o.tris.Add(vcount + 3);
                        o.tris.Add(vcount + 2);
                        o.tris.Add(vcount + 4);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v5) / m_settings.voxelSize);

                        AppendContour(v3, v0, o);
                        AppendContour(v2, v4, o);
                    }
                    break;

                    case 11:
                    {
                        float xstep = topLeft.GetExtentRightNormalized() * voxelSize;
                        float ystep = bottomRight.GetExtentTopNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x0, y0);
                        Vector3 v1 = new Vector3(x0, y1);
                        Vector3 v2 = new Vector3(x0 + xstep, y1);
                        Vector3 v3 = new Vector3(x1, y0 + ystep);
                        Vector3 v4 = new Vector3(x1, y0);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);
                        o.verts.Add(v3);
                        o.verts.Add(v4);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 2);
                        o.tris.Add(vcount + 3);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 3);
                        o.tris.Add(vcount + 4);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize);

                        AppendContour(v2, v3, o);
                    }
                    break;

                    case 12:
                    {
                        float ystep  = topLeft.GetExtentBottomNormalized() * voxelSize;
                        float ystep2 = topRight.GetExtentBottomNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x0, y1 - ystep);
                        Vector3 v1 = new Vector3(x0, y1);
                        Vector3 v2 = new Vector3(x1, y1);
                        Vector3 v3 = new Vector3(x1, y1 - ystep2);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);
                        o.verts.Add(v3);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 2);
                        o.tris.Add(vcount + 3);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);

                        AppendContour(v3, v0, o);
                    }
                    break;

                    case 13:
                    {
                        float xstep = bottomLeft.GetExtentRightNormalized() * voxelSize;
                        float ystep = topRight.GetExtentBottomNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x0, y0);
                        Vector3 v1 = new Vector3(x0, y1);
                        Vector3 v2 = new Vector3(x1, y1);
                        Vector3 v3 = new Vector3(x1, y1 - ystep);
                        Vector3 v4 = new Vector3(x0 + xstep, y0);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);
                        o.verts.Add(v3);
                        o.verts.Add(v4);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 4);

                        o.tris.Add(vcount + 4);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 3);

                        o.tris.Add(vcount + 3);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize);

                        AppendContour(v3, v4, o);
                    }
                    break;

                    case 14:
                    {
                        float xstep = bottomRight.GetExtentLeftNormalized() * voxelSize;
                        float ystep = topLeft.GetExtentBottomNormalized() * voxelSize;

                        Vector3 v0 = new Vector3(x0, y1 - ystep);
                        Vector3 v1 = new Vector3(x0, y1);
                        Vector3 v2 = new Vector3(x1, y1);
                        Vector3 v3 = new Vector3(x1, y0);
                        Vector3 v4 = new Vector3(x1 - xstep, y0);

                        int vcount = o.verts.Count;

                        o.verts.Add(v0);
                        o.verts.Add(v1);
                        o.verts.Add(v2);
                        o.verts.Add(v3);
                        o.verts.Add(v4);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 1);
                        o.tris.Add(vcount + 2);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 2);
                        o.tris.Add(vcount + 3);

                        o.tris.Add(vcount);
                        o.tris.Add(vcount + 3);
                        o.tris.Add(vcount + 4);

                        o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);
                        o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize);

                        AppendContour(v4, v0, o);
                    }
                    break;

                    case 15:
                    {
                        if (topLeft.CompareWithoutExtent(bottomLeft) && topRight.CompareWithoutExtent(bottomRight) && bottomLeft.CompareWithoutExtent(bottomRight))
                        {
                            GenerateGreedyQuad(data, region, x, y, o);
                        }
                        else
                        {
                            Vector3 v0 = new Vector3(x0, y0);
                            Vector3 v1 = new Vector3(x0, y1);
                            Vector3 v2 = new Vector3(x1, y1);
                            Vector3 v3 = new Vector3(x1, y0);

                            int vcount = o.verts.Count;

                            o.verts.Add(v0);
                            o.verts.Add(v1);
                            o.verts.Add(v2);
                            o.verts.Add(v3);

                            o.tris.Add(vcount);
                            o.tris.Add(vcount + 1);
                            o.tris.Add(vcount + 2);

                            o.tris.Add(vcount);
                            o.tris.Add(vcount + 2);
                            o.tris.Add(vcount + 3);

                            o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize);
                            o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize);
                            o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize);
                            o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize);
                        }
                    }
                    break;
                    }
                }
            }

            CombineContours(o);

            if (m_settings.generateCollision)
            {
                BuildCollision(o);
            }
            if (m_settings.meshContour)
            {
                BuildContourMesh(o);
            }

            if (m_settings.generateNormals)
            {
                for (int v = 0; v < o.verts.Count; v++)
                {
                    o.normals.Add(Vector3.back);
                }
            }
        }