Exemple #1
0
                void AddVoxel(int x, int y, int z, Voxel_t voxel)
                {
                    var blendVoxel = _voxels[_numVoxels++];

                    ZeroInts(blendVoxel->vertexFlags, 8);
                    ZeroInts(blendVoxel->neighbors, 6);
                    blendVoxel->touched = true;
                }
Exemple #2
0
        private List <VoxInfo> BuildVoxInfo(Voxel_t[] voxels, float unit)
        {
            List <VoxInfo> vi = new List <VoxInfo>();

            if (!selectedMesh || !selectedMaterial)
            {
                return(vi);
            }

            Vector3   min = selectedMesh.bounds.min;
            Texture2D tex = GetReadableTexture(selectedMaterial.mainTexture);

            float n = 1 / unit;

            for (int i = 0; i < voxels.Length; i++)
            {
                Voxel_t v = voxels[i];
                if (v.fill == 0)
                {
                    continue;
                }
                Vector3 p = v.position - min;
                p *= n;

                int        x  = Mathf.RoundToInt(p.x);
                int        y  = Mathf.RoundToInt(p.y);
                int        z  = Mathf.RoundToInt(p.z);
                Vector3Int vp = new Vector3Int(x, y, z);

                Color col = Color.white;

                if (v.uv.x != -1)//Fill color?
                {
                    if (tex != null)
                    {
                        col = tex.GetPixel((int)(v.uv.x * tex.width), (int)(v.uv.y * tex.height));
                    }
                    else
                    {
                        col = selectedMaterial.color;
                    }
                }

                VoxInfo nvi = new VoxInfo
                {
                    pos = vp,
                    col = col,
                    idx = 1
                };
                vi.Add(nvi);
            }

            return(vi);
        }
Exemple #3
0
    private void SymmetrizeVoxels(List <Voxel_t> voxels)
    {
        // Calculate the center of the voxels
        Vector3 center = Vector3.zero;

        foreach (Voxel_t voxel in voxels)
        {
            center += voxel.position;
        }
        center /= voxels.Count;

        // Create a list of previous voxels whose x-values are left or equal to center
        List <Voxel_t> sideVoxels = new List <Voxel_t>(voxels.Count);

        foreach (Voxel_t voxel in voxels)
        {
            if (voxel.position.x <= center.x + EPSILON)
            {
                sideVoxels.Add(voxel);
            }
        }

        // Clear the voxels and only add the ones whose x-value is left or equal to center
        voxels.Clear();
        foreach (Voxel_t sideVoxel in sideVoxels)
        {
            // Add the voxel for this side into the result
            voxels.Add(sideVoxel);

            // Add the opposite side voxel into the result
            // (Only do this if the voxel isn't along the center line)
            if (!Eq(sideVoxel.position.x, center.x))
            {
                Vector3 reversePosition = sideVoxel.position;
                reversePosition.x = -reversePosition.x;

                Voxel_t reverseVoxel = sideVoxel;
                reverseVoxel.position = reversePosition;

                voxels.Add(reverseVoxel);
            }
        }
    }
Exemple #4
0
                void EmitVoxelFaces(int index, int x, int y, int z, Voxel_t voxel, bool isBorderVoxel)
                {
                    var contents = _tables.blockContents[(int)voxel.type];

                    Color32 color;

                    if ((voxel.flags & EVoxelBlockFlags.FullVoxel) != 0)
                    {
                        color = Color.red;
                    }
                    else
                    {
                        GetBlockColor(voxel.type, x, y, z, out color);
                    }

                    for (int i = 0; i < 6; ++i)
                    {
                        if (_vnc[i] < contents)
                        {
                            var v0 = _tables.voxelFaces[i][0];

                            for (int k = 1; k <= 2; ++k)
                            {
                                var v1 = _tables.voxelFaces[i][k];
                                var v2 = _tables.voxelFaces[i][k + 1];

                                if ((v0 != v1) && (v0 != v2) && (v1 != v2))
                                {
                                    _smoothVerts.EmitTri(
                                        x + _tables.voxelVerts[v0][0] - BORDER_SIZE, y + _tables.voxelVerts[v0][1] - BORDER_SIZE, z + _tables.voxelVerts[v0][2] - BORDER_SIZE,
                                        x + _tables.voxelVerts[v1][0] - BORDER_SIZE, y + _tables.voxelVerts[v1][1] - BORDER_SIZE, z + _tables.voxelVerts[v1][2] - BORDER_SIZE,
                                        x + _tables.voxelVerts[v2][0] - BORDER_SIZE, y + _tables.voxelVerts[v2][1] - BORDER_SIZE, z + _tables.voxelVerts[v2][2] - BORDER_SIZE,
                                        color, isBorderVoxel
                                        );
                                }
                            }
                        }
                    }
                }
Exemple #5
0
    public static void Voxelize(Vector3[] vertices, int[] indices, Bounds bounds, int resolution, out float unit)
    {
        float maxLength = Mathf.Max(bounds.size.x, Mathf.Max(bounds.size.y, bounds.size.z));

        unit = maxLength / resolution;
        float hunit = unit * 0.5f;

        start = bounds.min - new Vector3(hunit, hunit, hunit);
        Vector3 end  = bounds.max + new Vector3(hunit, hunit, hunit);
        Vector3 size = end - start;

        width  = Mathf.CeilToInt(size.x / unit);
        height = Mathf.CeilToInt(size.y / unit);
        depth  = Mathf.CeilToInt(size.z / unit);

        volume            = new Voxel_t[width, height, depth];
        Bounds[, ,] boxes = new Bounds[width, height, depth];
        Vector3 voxelSize = Vector3.one * unit;

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                for (int z = 0; z < depth; z++)
                {
                    Vector3 p    = new Vector3(x, y, z) * unit + start;
                    Bounds  aabb = new Bounds(p, voxelSize);
                    boxes[x, y, z]  = aabb;
                    volume[x, y, z] = new Voxel_t();
                }
            }
        }

        Vector3 direction = Vector3.forward;

        for (int i = 0, n = indices.Length; i < n; i += 3)
        {
            MegaTriangle tri = new MegaTriangle(vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]], direction, i);

            Vector3 min = tri.bounds.min - start;
            Vector3 max = tri.bounds.max - start;
            int     iminX = (int)(min.x / unit), iminY = (int)(min.y / unit), iminZ = (int)(min.z / unit);
            int     imaxX = (int)(max.x / unit), imaxY = (int)(max.y / unit), imaxZ = (int)(max.z / unit);

            iminX = Mathf.Clamp(iminX, 0, width - 1);
            iminY = Mathf.Clamp(iminY, 0, height - 1);
            iminZ = Mathf.Clamp(iminZ, 0, depth - 1);
            imaxX = Mathf.Clamp(imaxX, 0, width - 1);
            imaxY = Mathf.Clamp(imaxY, 0, height - 1);
            imaxZ = Mathf.Clamp(imaxZ, 0, depth - 1);

            for (int x = iminX; x <= imaxX; x++)
            {
                for (int y = iminY; y <= imaxY; y++)
                {
                    for (int z = iminZ; z <= imaxZ; z++)
                    {
                        if (Intersects(tri, boxes[x, y, z]))
                        {
                            Voxel_t voxel = volume[x, y, z];
                            voxel.position = boxes[x, y, z].center;
                            voxel.tris.Add(tri);
                            volume[x, y, z] = voxel;
                        }
                    }
                }
            }
        }
    }
Exemple #6
0
    public static unsafe PinnedChunkData_t DecompressChunkData(byte *ptr, int len, PinnedChunkData_t chunk, FinalMeshVerts_t verts)
    {
        var src = ptr;

        {
            var decorationCount = *((int *)src);
            src += 4;

            for (int i = 0; i < decorationCount; ++i)
            {
                var d = default(Decoration_t);
                d.pos.x = *((float *)src);
                src    += 4;
                d.pos.y = *((float *)src);
                src    += 4;
                d.pos.z = *((float *)src);
                src    += 4;
                d.type  = (EDecorationType)(*((int *)src));
                src    += 4;

                chunk.AddDecoration(d);
            }
        }

        if ((chunk.flags & EChunkFlags.SOLID) == 0)
        {
            // empty chunk
            chunk.voxeldata.Broadcast(EVoxelBlockType.Air);

            for (int i = 0; i < verts.counts.Length; ++i)
            {
                verts.counts[i] = 0;
            }

            for (int i = 0; i < verts.submeshes.Length; ++i)
            {
                verts.submeshes[i] = 0;
            }

            return(chunk);
        }

        {
            var voxeldata = chunk.voxeldata;
            var count     = chunk.voxeldata.length;
            for (int i = 0; i < count; ++i)
            {
                voxeldata[i] = new Voxel_t(src[i]);
            }
        }

        src += chunk.voxeldata.length;

        for (int i = 0; i < verts.counts.Length; ++i)
        {
            verts.counts[i] = *((int *)src);
            src            += 4;
        }
        for (int i = 0; i < verts.submeshes.Length; ++i)
        {
            verts.submeshes[i] = *((int *)src);
            src += 4;
        }

        int totalVerts = *((int *)src);

        src += 4;
        int totalIndices = *((int *)src);

        src += 4;

        for (int i = 0; i < totalVerts; ++i)
        {
            Vector3 v3;
            v3.x = *((float *)src);
            src += 4;
            v3.y = *((float *)src);
            src += 4;
            v3.z = *((float *)src);
            src += 4;
            verts.positions[i] = v3;
        }
        for (int i = 0; i < totalVerts; ++i)
        {
            Vector3 v3;
            v3.x             = *((float *)src);
            src             += 4;
            v3.y             = *((float *)src);
            src             += 4;
            v3.z             = *((float *)src);
            src             += 4;
            verts.normals[i] = v3;
        }
        for (int i = 0; i < totalVerts; ++i)
        {
            uint c = *((uint *)src);
            src            += 4;
            verts.colors[i] = Utils.GetColor32FromUIntRGBA(c);
        }
        for (int i = 0; i < totalIndices; ++i)
        {
            verts.indices[i] = *((int *)src);
            src += 4;
        }

        return(chunk);
    }
                void Run(PinnedChunkData_t chunk)
                {
                    _smoothVerts.Init();

                    if ((chunk.flags & EChunkFlags.SOLID) == 0)
                    {
                        // no solid blocks in this chunk it can't have any visible faces.
                        _smoothVerts.Finish();
                        return;
                    }

                    byte * grid       = stackalloc byte[8];
                    int *  x          = stackalloc int[3];
                    int *  edges      = stackalloc int[12];
                    byte * edgeBlocks = stackalloc byte[24];
                    float *nv         = stackalloc float[3];

                    for (x[2] = -2; x[2] < VOXEL_CHUNK_SIZE_Y + 1; ++x[2])
                    {
                        for (x[1] = -2; x[1] < VOXEL_CHUNK_SIZE_XZ + 1; ++x[1])
                        {
                            for (x[0] = -2; x[0] < VOXEL_CHUNK_SIZE_XZ + 1; ++x[0])
                            {
                                // read voxels around this vertex
                                // note the mask, and grid verts for the cubes are X/Y/Z, but unity
                                // is Y up so we have to swap Z/Y

                                bool isBorder = (x[0] < 0) || (x[0] >= VOXEL_CHUNK_SIZE_XZ) || (x[1] < 0) || (x[1] >= VOXEL_CHUNK_SIZE_XZ) || (x[2] < 0) || (x[2] >= VOXEL_CHUNK_SIZE_Y);

                                int cubeIndex = 0;

                                for (int i = 0; i < 8; ++i)
                                {
                                    var v = _tables.mc_cubeVerts[i];

                                    var iz    = x[2] + v[2];
                                    var zwrap = Wrap(iz, VOXEL_CHUNK_SIZE_Y);
                                    var zofs  = VOXEL_CHUNK_SIZE_XZ * VOXEL_CHUNK_SIZE_XZ * zwrap;                                  // zofs is really yofs in voxel data
                                    var cz    = (iz < 0) ? 0 : (iz < VOXEL_CHUNK_SIZE_Y) ? 1 : 2;

                                    var iy    = x[1] + v[1];
                                    var ywrap = Wrap(iy, VOXEL_CHUNK_SIZE_XZ);
                                    var yofs  = VOXEL_CHUNK_SIZE_XZ * ywrap;                                    // yofs is really zofs in voxel data

                                    var cy = (iy < 0) ? 0 : (iy < VOXEL_CHUNK_SIZE_XZ) ? 1 : 2;

                                    var ix    = x[0] + v[0];
                                    var xwrap = Wrap(ix, VOXEL_CHUNK_SIZE_XZ);
                                    var xofs  = xwrap;

                                    var cx = (ix < 0) ? 0 : (ix < VOXEL_CHUNK_SIZE_XZ) ? 1 : 2;

                                    var chunkIndex = cx + (cz * Y_PITCH) + (cy * Z_PITCH);
                                    var POS_X      = chunkIndex + 1;
                                    var NEG_X      = chunkIndex - 1;
                                    var POS_Y      = chunkIndex + Y_PITCH;
                                    var NEG_Y      = chunkIndex - Y_PITCH;
                                    var POS_Z      = chunkIndex + Z_PITCH;
                                    var NEG_Z      = chunkIndex - Z_PITCH;

                                    var neighbor = _area[chunkIndex];
                                    var voxel    = neighbor.valid != 0 ? neighbor.voxeldata[xofs + yofs + zofs] : EVoxelBlockType.Air;
                                    grid[i] = voxel.raw;
                                    if (_tables.blockContents[(int)voxel.type] == EVoxelBlockContents.None)
                                    {
                                        cubeIndex |= 1 << i;
                                    }
                                }

                                var edgeMask = _tables.mc_edgeTable[cubeIndex];

                                if (edgeMask == 0)
                                {
                                    // no contents change
                                    continue;
                                }

                                for (int i = 0; i < 12; ++i)
                                {
                                    edges[i] = -1;

                                    if ((edgeMask & (1 << i)) == 0)
                                    {
                                        continue;
                                    }

                                    nv[0] = 0; nv[1] = 0; nv[2] = 0;
                                    var e  = _tables.mc_edgeIndex[i];
                                    var v0 = _tables.mc_cubeVerts[e[0]];
                                    var v1 = _tables.mc_cubeVerts[e[1]];

                                    edgeBlocks[i * 2 + 0] = grid[e[0]];
                                    edgeBlocks[i * 2 + 1] = grid[e[1]];

                                    var t = 0.5f;

                                    for (int j = 0; j < 3; ++j)
                                    {
                                        nv[j] = (x[j] + v0[j] + 0.5f) + t * (v1[j] - v0[j]);
                                    }

                                    edges[i] = _smoothVerts.EmitVert(new Vector3(nv[0], nv[2], nv[1]));
                                }

                                var faces = _tables.mc_triTable[cubeIndex];
                                for (int i = 0; (i < faces.length) && (faces[i] != -1); i += 3)
                                {
                                    BoundsCheckAndThrow(faces[i + 0], 0, 12);
                                    BoundsCheckAndThrow(faces[i + 1], 0, 12);
                                    BoundsCheckAndThrow(faces[i + 2], 0, 12);

                                    Voxel_t             voxel = default(Voxel_t);
                                    EVoxelBlockContents vc    = default(EVoxelBlockContents);

                                    for (int j = 0; j < 3; ++j)
                                    {
                                        var v0v = new Voxel_t(edgeBlocks[faces[i + j] * 2 + 0]);
                                        var v1v = new Voxel_t(edgeBlocks[faces[i + j] * 2 + 1]);
                                        var v0c = _tables.blockContents[(int)v0v.type];
                                        var v1c = _tables.blockContents[(int)v1v.type];
                                        if (j > 0)
                                        {
                                            if (v0c > v1c)
                                            {
                                                if (v0c > vc)
                                                {
                                                    vc    = v0c;
                                                    voxel = v0v;
                                                }
                                            }
                                            else if (v1c > vc)
                                            {
                                                vc    = v1c;
                                                voxel = v1v;
                                            }
                                        }
                                        else
                                        {
                                            vc    = (v0c > v1c) ? v0c : v1c;
                                            voxel = (v0c > v1c) ? v0v : v1v;
                                        }
                                    }

                                    int     mat, layer;
                                    uint    smg;
                                    Color32 color;
                                    float   smoothing;

                                    GetBlockColorAndSmoothing(voxel.type, out color, out smg, out smoothing, out layer);
                                    mat = _blockMaterials[(int)voxel.type - 1];

                                    _smoothVerts.EmitTri(edges[faces[i]], edges[faces[i + 2]], edges[faces[i + 1]], smg, smoothing, color, layer, mat, isBorder);
                                }
                            }
                        }
                    }

                    _smoothVerts.Finish();
                }