Ejemplo n.º 1
0
        static void TestSlices()
        {
            Console.WriteLine("Hello World!");

            VoxelSet <Vec4b> colors = new VoxelSet <Vec4b>(32);

            colors.Set(new Vec4b(0));
            colors.Slice(new Vec3i(1), new Vec3i(30)).Set(new Vec4b(255));
            colors.Slice(new Vec3i(3), new Vec3i(28)).Set(new Vec4b(0));
            colors.Slice(new Vec3i(5), new Vec3i(26)).Set(new Vec4b(255));

            for (int i = 0; i < 32; ++i)
            {
                if (colors[16, i, 16].x == 0)
                {
                    Console.Write(".");
                }
                else
                {
                    Console.Write("#");
                }
            }
            Console.Write("\nPress any key to continue ... ");
            Console.ReadKey();
        }
Ejemplo n.º 2
0
    /// Loads a MagicaVoxel model into the current model.
    public void LoadMagicaModel(string magicaVoxelFile, bool retainVoxels, VoxelFactory.ColliderType colliderType, MagicaFlags flags)
    {
        Clear();

        this.colliderType = colliderType;

        PointQuadList opaqueFaces      = new PointQuadList();
        PointQuadList transparentFaces = new PointQuadList();

        IntPtr model = OpenBoxNative.MagicaLoadModel(magicaVoxelFile, flags);

        OpenBoxNative.MagicaExtractFaces(model, ref opaqueFaces, ref transparentFaces);

        if (retainVoxels || colliderType != VoxelFactory.ColliderType.None)
        {
            // Copy voxels over to the C# side
            voxels = new VoxelSet <Color32>(OpenBoxNative.MagicaModelSize(model));
            OpenBoxNative.MagicaCopyVoxels(voxels.Pin(), model);
            voxels.Unpin();

            // TODO: Calculate colliders natively
            UpdateColliders();
        }

        OpenBoxNative.MagicaFreeModel(model);

        MakeMeshFromQuadLists(opaqueFaces, transparentFaces);

        OpenBoxNative.FreeFacesHandle(opaqueFaces.handle);
        OpenBoxNative.FreeFacesHandle(transparentFaces.handle);
    }
Ejemplo n.º 3
0
    public void OnAfterDeserialize()
    {
        if (serializeVoxelColors == null)
        {
            return;
        }

        voxels = new VoxelSet <Color32>(
            serializeVoxelDimension.x,
            serializeVoxelDimension.y,
            serializeVoxelDimension.z
            );

        // TODO: MemCopy would be better
        for (int z = 0; z < serializeVoxelDimension.z; ++z)
        {
            for (int y = 0; y < serializeVoxelDimension.y; ++y)
            {
                int offset = y * serializeVoxelDimension.x
                             + z * serializeVoxelDimension.y * serializeVoxelDimension.x;
                for (int x = 0; x < serializeVoxelDimension.x; ++x)
                {
                    voxels[x, y, z] = serializeVoxelColors[offset + x];
                }
            }
        }

        serializeVoxelColors = null;
    }
Ejemplo n.º 4
0
        static void SmearDirection(VoxelSet <float> voxels, float transference, Vec3i dir)
        {
            Vec3i dx = new Vec3i(Math.Abs(dir.y), Math.Abs(dir.z), Math.Abs(dir.x));
            Vec3i dy = new Vec3i(Math.Abs(dir.z), Math.Abs(dir.x), Math.Abs(dir.y));

            Vec3i start = new Vec3i(0);

            if (Vec3i.Dot(dir, new Vec3i(1)) < 0)
            {
                start = voxels.Size.Dot(dir) * dir + dir;
            }

            int y = 0;

            while (voxels.IsValid(start + y * dy))
            {
                int x = 0;
                while (voxels.IsValid(start + y * dy + x * dx))
                {
                    SmearLine(voxels, transference, dir, start + y * dy + x * dx);
                    x++;
                }
                y++;
            }
        }
Ejemplo n.º 5
0
        public static List <Box> MakeBoxes(VoxelSet <bool> shape)
        {
            List <Box> boxes = new List <Box>();

            // Directions to explore
            Vec3i[] dirs = new[] {
                new Vec3i(1, 0, 0),
                new Vec3i(0, 1, 0),
                new Vec3i(0, 0, 1)
            };

            // TODO: Iteration order may need to be reversed
            for (int z = 0; z < shape.Size.z; z++)
            {
                for (int y = 0; y < shape.Size.y; y++)
                {
                    for (int x = 0; x < shape.Size.x; x++)
                    {
                        if (!shape[x, y, z])
                        {
                            continue;
                        }

                        Vec3i idx    = new Vec3i(x, y, z);
                        Vec3i endIdx = new Vec3i(x, y, z);

                        // Expand box in each cardinal direction as much as possible
                        foreach (var dir in dirs)
                        {
                            Vec3i checkFromIdx = idx;

                            // Expand as much as possible in the current direction
                            while (shape.IsValid(endIdx + dir))
                            {
                                checkFromIdx += dir;

                                // Create a slice for the next layer in the current dir and make sure it's solid
                                var slice = shape.Slice(checkFromIdx, endIdx + dir);
                                if (!slice.IsAllSolid(b => b))
                                {
                                    break;
                                }
                                slice.Set(false);

                                endIdx += dir;
                            }
                        }

                        Box box = new Box();
                        box.origin  = new Vec3i(x, y, z);
                        box.extents = new Vec3i(endIdx.x + 1 - idx.x, endIdx.y + 1 - idx.y, endIdx.z + 1 - idx.z);
                        boxes.Add(box);
                    }
                }
            }

            return(boxes);
        }
Ejemplo n.º 6
0
        static void SmearLine(VoxelSet <float> voxels, float transference, Vec3i dir, Vec3i start)
        {
            Vec3i idx = start + dir;

            while (voxels.IsValid(idx))
            {
                voxels[idx] += voxels[idx - dir] * transference;
                idx         += dir;
            }
        }
Ejemplo n.º 7
0
        public static MeshSimplifier VoxelsToMesh(VoxelSet <Vec4b> voxels)
        {
            MeshSimplifier ms = VoxelsToMeshFull(voxels);

            Console.WriteLine("Triangles before reduction: " + (ms.Edges.Length / 3));
            ms.Simplify();
            ms.Compact();
            Console.WriteLine("Triangles after reduction: " + (ms.Edges.Length / 3));

            return(ms);
        }
Ejemplo n.º 8
0
        private void CreateRootDictionaries()
        {
            for (int i = 0; i < Models.Length; i++)
            {
                Models[i] = new ModelSet();
            }

            for (int i = 0; i < Voxels.Length; i++)
            {
                Voxels[i] = new VoxelSet();
            }
        }
Ejemplo n.º 9
0
        private void CreateRootDictionaries()
        {
            for (int i = 0; i < Models.Length; i++)
            {
                Models[i] = new ModelSet();
            }

            for (int i = 0; i < Voxels.Length; i++)
            {
                Voxels[i] = new VoxelSet();
            }
        }
Ejemplo n.º 10
0
        public static MeshSimplifier VoxelsToMeshFull(VoxelSet <Vec4b> voxels)
        {
            var quads = VoxelsToQuads(voxels);

            Vec3f[] positions = new Vec3f[quads.Count * 4];
            Vec3f[] normals   = new Vec3f[quads.Count * 4];

            int[] tris = new int[quads.Count * 6];

            Dictionary <Vec3b, int> posRemap = new Dictionary <Vec3b, int>();

            int idx = 0;

            foreach (var q in quads)
            {
                for (int i = 0; i < 4; ++i)
                {
                    normals[idx * 4 + i] = q.normal;
                }

                positions[idx * 4 + 0] = q.offset;
                positions[idx * 4 + 1] = q.offset + q.dx;
                positions[idx * 4 + 2] = q.offset + q.dx + q.dy;
                positions[idx * 4 + 3] = q.offset + q.dy;

                int[] posIndices = new int[4];
                for (int i = 0; i < 4; ++i)
                {
                    Vec3b posKey = new Vec3b(positions[idx * 4 + i]);

                    if (!posRemap.ContainsKey(posKey))
                    {
                        posRemap[posKey] = idx * 4 + i;
                    }

                    posIndices[i] = posRemap[posKey];
                }

                tris[idx * 6 + 0] = posIndices[0];
                tris[idx * 6 + 1] = posIndices[1];
                tris[idx * 6 + 2] = posIndices[2];

                tris[idx * 6 + 3] = posIndices[0];
                tris[idx * 6 + 4] = posIndices[2];
                tris[idx * 6 + 5] = posIndices[3];
                idx++;
            }

            MeshSimplifier ms = new MeshSimplifier(positions, tris);

            return(ms);
        }
Ejemplo n.º 11
0
    public void Clear()
    {
        voxels = null;

#if !UNITY_EDITOR
        MeshFilter mf = GetComponent <MeshFilter>();
        if (mf.sharedMesh != null)
        {
            Destroy(mf.sharedMesh);
            mf.sharedMesh = null;
        }
#endif
    }
Ejemplo n.º 12
0
    // Makes a set of covers to completely cover the given shape.
    static List <BoxMaker.Box> MakeBoxes(VoxelSet <bool> shape, int scale)
    {
        List <BoxMaker.Box> boxes = BoxMaker.MakeBoxes(shape);

        if (scale != 1)
        {
            foreach (var box in boxes)
            {
                box.extents *= scale;
                box.origin  *= scale;
            }
        }

        return(boxes);
    }
Ejemplo n.º 13
0
    // Reduces the size of the given shape by the given factor.
    static VoxelSet <bool> ReduceShape(VoxelSet <bool> shape, int factor)
    {
        Vec3i size = Vec3i.Max(shape.Size / factor, new Vec3i(1));

        Debug.Log("Old size: " + shape.Size + "     New size: " + size);

        VoxelSet <bool> reducedShape = new VoxelSet <bool>(size);

        shape.Apply((v, idx) => {
            Vec3i targetIdx         = Vec3i.Min(size - 1, idx / factor);
            reducedShape[targetIdx] = reducedShape[targetIdx] || v;
        });

        return(reducedShape);
    }
Ejemplo n.º 14
0
    // Makes a mesh from the given voxel set.
    public static void MakeMeshNative(VoxelSet <Vec4b> voxels, out Mesh mesh, out Material[] materials)
    {
        PointQuadList opaqueFaces      = new PointQuadList();
        PointQuadList transparentFaces = new PointQuadList();

        IntPtr voxelsPtr = voxels.Pin();

        obx_ExtractFaces(voxelsPtr, voxels.Size, ref opaqueFaces, ref transparentFaces);
        voxels.Unpin();

        MakeMeshFromQuadLists(opaqueFaces, transparentFaces, out mesh, out materials);

        obx_FreeFacesHandle(opaqueFaces.handle);
        obx_FreeFacesHandle(transparentFaces.handle);
    }
Ejemplo n.º 15
0
        public static VoxelSet <bool> LowPassFilter(VoxelSet <Vec4b> voxels, float transference, float threshold)
        {
            VoxelSet <float> fVoxels = voxels.Project(ToFloat);

            Vec3i[] dirs =
            {
                new Vec3i(1,   0,  0),
                new Vec3i(-1,  0,  0),
                new Vec3i(0,   1,  0),
                new Vec3i(0,  -1,  0),
                new Vec3i(0,   0,  1),
                new Vec3i(0,   0, -1),
            };

            foreach (var dir in dirs)
            {
                SmearDirection(fVoxels, transference, dir);
            }

            return(fVoxels.Project(v => v >= threshold));
        }
Ejemplo n.º 16
0
        // Loads the given model into a voxel set and returns it.
        VoxelSet <Vec4b> LoadModelChunk(Chunk sizeChunk, Chunk idxChunk)
        {
            if (sizeChunk.chunkId != kChunkSize)
            {
                throw new Exception("Bad size chunk");
            }

            if (idxChunk.chunkId != kChunkXyzi)
            {
                throw new Exception("Bad index chunk");
            }

            BinaryReader sizeReader = sizeChunk.OpenReader();
            BinaryReader idxReader  = idxChunk.OpenReader();

            // TODO: This seems to load models rotated 180 degrees
            Vec3i size = new Vec3i();

            size.x = sizeReader.ReadInt32();
            size.z = sizeReader.ReadInt32();
            size.y = sizeReader.ReadInt32();
            VoxelSet <Vec4b> model = new VoxelSet <Vec4b>(size);

            // Read individual voxels
            int numVoxels = idxReader.ReadInt32();

            for (int j = 0; j < numVoxels; ++j)
            {
                //Vec3i idx = new Vec3i(br.ReadByte(), br.ReadByte(), br.ReadByte());
                Vec3i idx = new Vec3i(0);
                idx.x = idxReader.ReadByte();
                idx.z = idxReader.ReadByte();
                idx.y = idxReader.ReadByte();

                // For now just store the index into the palette
                model[idx] = new Vec4b(idxReader.ReadByte());
            }

            return(model);
        }
Ejemplo n.º 17
0
    // Adds colliders to the given game object.
    public static void AddColliders(GameObject obj, VoxelSet <Color32> voxels, ColliderType colliderType)
    {
        if (colliderType != ColliderType.None)
        {
            VoxelSet <bool> shape = voxels.Project(v => v.a > 0);
            int             scale = 1;
            if (colliderType == ColliderType.HalfScale)
            {
                //shape = ReduceShape(shape);
                shape = ReduceShape(shape, 2);
                scale = 2;
            }

            if (colliderType == ColliderType.ThirdScale)
            {
                shape = ReduceShape(shape, 3);
                scale = 3;
            }

            if (colliderType == ColliderType.QuarterScale)
            {
                //shape = ReduceShape(ReduceShape(shape));
                shape = ReduceShape(shape, 4);
                scale = 4;
            }

            List <BoxMaker.Box> boxes = MakeBoxes(shape, scale);

            // Add box colliders
            foreach (var boxDesc in boxes)
            {
                BoxCollider box = obj.AddComponent <BoxCollider>();
                box.size   = new Vector3(boxDesc.extents.x, boxDesc.extents.y, boxDesc.extents.z);
                box.center = new Vector3(boxDesc.origin.x, boxDesc.origin.y, boxDesc.origin.z) + box.size / 2.0f;
            }
        }
    }
Ejemplo n.º 18
0
 public IPDMeshCreator(VoxelSet voxelSet)
 {
     VoxelSet = voxelSet;
 }
Ejemplo n.º 19
0
 public IPDMeshCreator(VoxelSet voxelSet, bool smartUpdate, bool influenceRegion2) : this(voxelSet, smartUpdate)
 {
     this.influenceRegion2 = influenceRegion2;
 }
Ejemplo n.º 20
0
        public void GetMesh(VoxelSet <Vec4b> voxels,
                            out int[] indices, out Vec3f[] points, out Vec3f[] normals, out Vec2f[] uvs,
                            out VoxelSet <Vec4b> textureAtlas)
        {
            List <int>   indicesList = new List <int>();
            List <Vec3f> pointsList  = new List <Vec3f>();
            List <Vec3f> normalsList = new List <Vec3f>();
            List <Vec2f> uvsList     = new List <Vec2f>();

            Dictionary <int, int> vertIdxRemap = new Dictionary <int, int>();

            List <Bin> bins = new List <Bin>();

            foreach (var poly in AllPolygons())
            {
                // For each connected polygon
                vertIdxRemap.Clear();
                Vec3f normal = Normal(poly.First());

                Vec3f maxP = new Vec3f(-1);
                Vec3f minP = new Vec3f(1024 * 1024);

                AtlasEntry atlasEntry = new AtlasEntry();
                atlasEntry.startVertIdx = pointsList.Count;
                atlasEntry.normal       = new Vec3i(
                    (int)Math.Round(normal.x),
                    (int)Math.Round(normal.y),
                    (int)Math.Round(normal.z)
                    );

                foreach (var baseEdge in poly)
                {
                    // Each triangle that makes up the polygon
                    foreach (var e in new int[] { baseEdge, Next(baseEdge), Prev(baseEdge) })
                    {
                        // Each vertex of each triangle
                        int vertIdx = Edges[e].vertexIdx;
                        if (!vertIdxRemap.ContainsKey(vertIdx))
                        {
                            vertIdxRemap.Add(vertIdx, pointsList.Count);
                            pointsList.Add(Points[vertIdx]);
                            normalsList.Add(normal);

                            maxP = Max3f(maxP, Points[vertIdx]);
                            minP = Min3f(minP, Points[vertIdx]);

                            // TODO: Add UV here
                        }

                        indicesList.Add(vertIdxRemap[vertIdx]);
                    }
                }

                atlasEntry.vertCount = pointsList.Count - atlasEntry.startVertIdx;

                // TODO: Add to texture atlas here
                Vec3f deltaP = maxP - minP;

                // Determine which dimension is flat
                int flatIdx = -1;
                for (int i = 0; i < 3; ++i)
                {
                    if (deltaP[i] == 0)
                    {
                        if (flatIdx >= 0)
                        {
                            throw new Exception("Two or more flat dimensions found");
                        }
                        flatIdx = i;
                    }
                }

                Vec2i size;
                if (flatIdx == 0)
                {
                    size = new Vec2i((int)Math.Round(deltaP.y), (int)Math.Round(deltaP.z));
                }
                else if (flatIdx == 1)
                {
                    size = new Vec2i((int)Math.Round(deltaP.x), (int)Math.Round(deltaP.z));
                }
                else
                {
                    size = new Vec2i((int)Math.Round(deltaP.x), (int)Math.Round(deltaP.y));
                }

                atlasEntry.flatDimension = flatIdx;
                atlasEntry.max           = new Vec3i(maxP + new Vec3f(0.5f));
                atlasEntry.min           = new Vec3i(minP + new Vec3f(0.5f));

                Bin b = new Bin();
                b.Size     = size;
                b.UserData = atlasEntry;
                bins.Add(b);
            }

            indices = indicesList.ToArray();
            points  = pointsList.ToArray();
            normals = normalsList.ToArray();

            //BinPacker bp = new BinPacker(512);
            BinPacker bp = new BinPacker(512);

            bp.BinPadding = new Vec2i(2);
            bp.Pack(bins);
            bp.MakePow2();

            textureAtlas = new VoxelSet <Vec4b>(bp.Width, bp.Height, 1);

            for (int y = 0; y < textureAtlas.Size.y; ++y)
            {
                for (int x = 0; x < textureAtlas.Size.x; ++x)
                {
                    textureAtlas[x, y, 0] = new Vec4b(0, 255, 0, 255);
                }
            }

            uvs = new Vec2f[points.Length];
            foreach (var bin in bp.Bins)
            {
                var atlasEntry = (AtlasEntry)bin.UserData;

                // Copy to atlas
                var toSlice = textureAtlas.Slice(new Vec3i(bin.Position, 0),
                                                 new Vec3i(bin.Position + bin.Size - 1, 0));

                Vec3i voxelOffset = new Vec3i(0);

                if (atlasEntry.normal.Dot(new Vec3i(1)) > 0)
                {
                    voxelOffset = atlasEntry.normal * -1;
                }
                else
                {
                    //voxelOffset = atlasEntry.normal * -1;
                    voxelOffset = new Vec3i(0);
                }

                var fromSlice = voxels.Slice(
                    atlasEntry.min + voxelOffset,
                    atlasEntry.max - atlasEntry.min + atlasEntry.Basis() * new Vec3i(0, 0, 1),
                    atlasEntry.Basis()
                    );

                if (toSlice.Size.x != fromSlice.Size.x ||
                    toSlice.Size.y != fromSlice.Size.y ||
                    toSlice.Size.z != fromSlice.Size.z)
                {
                    throw new Exception();
                }

                /*for (int y = 0; y < toSlice.Size.y; ++y) {
                 *  for (int x = 0; x < toSlice.Size.x; ++x) {
                 *      toSlice[x, y, 0] = fromSlice[x, y, 0];
                 *  }
                 * }*/

                for (int y = 0; y < toSlice.Size.y; ++y)
                {
                    for (int x = 0; x < toSlice.Size.x; ++x)
                    {
                        if (Vec4b.Dot(toSlice[x, y, 0], new Vec4b(1)) != 0)
                        {
                            ////throw new Exception();
                        }
                        toSlice[x, y, 0] = voxels[atlasEntry.To3d(new Vec2i(x, y)) + voxelOffset];
                        //toSlice[x, y, 0] = c;
                    }
                }

                // Compute UVs
                for (int i = atlasEntry.startVertIdx; i < atlasEntry.startVertIdx + atlasEntry.vertCount; ++i)
                {
                    Vec2f uv = new Vec2f(atlasEntry.To2d(new Vec3i(points[i])));

                    //uv *= new Vec2f(bin.Size - 1) / new Vec2f(bin.Size);
                    //uv += 0.5f;

                    uv *= (new Vec2f(bin.Size) - 0.01f) / new Vec2f(bin.Size);
                    uv += 0.005f;

                    /////////
                    //uv *= 0.998f;
                    //uv += 0.01f;

                    uv += new Vec2f(bin.Position);

                    ///////
                    //uv += 0.25f;

                    uv.x /= bp.Width;
                    uv.y /= bp.Height;

                    uvs[i] = uv;
                }
            }

            Console.WriteLine("Total size: {0} x {1}", bp.Width, bp.Height);
        }
Ejemplo n.º 21
0
 public IPDMeshCreator(VoxelSet voxelSet, bool smartUpdate, bool influenceRegion2, bool energyFunction2, float regionAngle) : this(voxelSet, smartUpdate, influenceRegion2)
 {
     this.energyFunction2 = energyFunction2;
     this.regionAngle     = regionAngle;
 }
Ejemplo n.º 22
0
    ////////////////////////////////////////////////////////////////////////////



    // Adds all faces for the given index of the given voxels to the list of quads.
    static void AddFaces(VoxelSet <Vec4b> voxels, List <Quad> quads, Vec3i idx)
    {
        Vec3i[] normals =
        {
            new Vec3i(1,   0, 0),
            new Vec3i(-1,  0, 0),

            new Vec3i(0,   1, 0),
            new Vec3i(0,  -1, 0),

            new Vec3i(0,   0, 1),
            new Vec3i(0,   0, -1)
        };

        bool transparent = IsTransparent(voxels, idx);

        for (int i = 0; i < normals.Length; ++i)
        {
            Vec3i normal   = normals[i];
            Vec3i neighbor = idx + normal;
            if (voxels.IsValid(neighbor) && (voxels[neighbor].w > 0))
            {
                if (transparent && IsTransparent(voxels, neighbor))
                {
                    // Two transparent voxels - face is hidden.
                    continue;
                }

                if (transparent && voxels[neighbor].w == 255)
                {
                    // Transparent self and opaque neighbor - hidden to avoid z-fighting.
                    continue;
                }

                if (!transparent && voxels[neighbor].w == 255)
                {
                    // Two opaque voxels - face is hidden.
                    continue;
                }
            }

            var  c = voxels[idx];
            Quad q = new Quad();

            q.color = new Color32(c.x, c.y, c.z, c.w);

            Vec3i pos = idx;

            if (Vec3i.Dot(normal, new Vec3i(1)) > 0)
            {
                pos += normal;
            }

            q.position = new Vector3(pos.x, pos.y, pos.z);
            q.uv       = new Vector2(i, 0);

            quads.Add(q);

            if (transparent)
            {
                // Add back facing as well for transparent quads
                //q.uv = new Vector2((i - (i % 2)) + ((i + 1) % 2), 0);
                q.uv = new Vector2(i ^ 1, 0);
                //q.position += new Vector3(normal.x, normal.y, normal.z);
                quads.Add(q);
            }
        }
    }
Ejemplo n.º 23
0
        public static List <Quad> VoxelsToQuads(VoxelSet <Vec4b> voxels)
        {
            List <Quad> quads = new List <Quad>();

            Vec3f[] normals =
            {
                new Vec3f(1,   0, 0),
                new Vec3f(-1,  0, 0),
                new Vec3f(0,   1, 0),
                new Vec3f(0,  -1, 0),
                new Vec3f(0,   0, 1),
                new Vec3f(0,   0, -1)
            };

            Vec3f[] dxs =
            {
                new Vec3f(0, 1, 0),
                new Vec3f(0, 0, 1),
                new Vec3f(0, 0, 1),
                new Vec3f(1, 0, 0),
                new Vec3f(1, 0, 0),
                new Vec3f(0, 1, 0)
            };

            Vec3f[] dys =
            {
                new Vec3f(0, 0, 1),
                new Vec3f(0, 1, 0),
                new Vec3f(1, 0, 0),
                new Vec3f(0, 0, 1),
                new Vec3f(0, 1, 0),
                new Vec3f(1, 0, 0)
            };

            voxels.Apply((Vec4b c, Vec3i idx) => {
                if (c.w == 0)
                {
                    // Voxel is empty
                    //return;
                }

                // Check each face
                for (int i = 0; i < 6; ++i)
                {
                    Quad quad   = new Quad();
                    quad.normal = normals[i];
                    quad.dx     = dxs[i];
                    quad.dy     = dys[i];
                    quad.offset = new Vec3f(idx.x, idx.y, idx.z);
                    quad.color  = c;

                    Vec3i neighbor = idx + new Vec3i(new Vec3f(quad.normal.x, quad.normal.y, quad.normal.z));
                    if (c.w == 0 || voxels.IsValid(neighbor) && voxels[neighbor].w > 0)
                    {
                        // Voxel face is covered
                        continue;
                    }

                    if (quad.normal.x > 0 || quad.normal.y > 0 || quad.normal.z > 0)
                    {
                        quad.offset += quad.normal;
                    }

                    quads.Add(quad);
                }
            });

            return(quads);
        }
Ejemplo n.º 24
0
    // Makes a mesh from the given voxel set.
    public static void MakeMesh(VoxelSet <Vec4b> voxels, out Mesh mesh, out Material[] materials)
    {
        List <Quad> quads            = new List <Quad>();
        List <Quad> transparentQuads = new List <Quad>();

        // Find all visible faces
        for (int z = 0; z < voxels.Size.z; ++z)
        {
            for (int y = 0; y < voxels.Size.y; ++y)
            {
                for (int x = 0; x < voxels.Size.x; ++x)
                {
                    if (voxels[x, y, z].w <= 0)
                    {
                        // Empty; skip
                        continue;
                    }

                    if (voxels[x, y, z].w < 255)
                    {
                        AddFaces(voxels, transparentQuads, new Vec3i(x, y, z));
                    }
                    else
                    {
                        AddFaces(voxels, quads, new Vec3i(x, y, z));
                    }
                }
            }
        }

        mesh             = new Mesh();
        mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;

        int subMeshCount = AddMeshGeometry(new List <Quad>[] {
            quads,
            transparentQuads
        }, mesh);

        mesh.subMeshCount = subMeshCount;

        materials = new Material[subMeshCount];

        int submeshIdx   = 0;
        int nextPointIdx = 0;

        // Opaque quads
        if (quads.Count > 0)
        {
            AddMeshIndices(quads.Count, mesh, nextPointIdx, submeshIdx);
            materials[submeshIdx] = new Material(Shader.Find("Voxel/PointQuads"));

            nextPointIdx += quads.Count;
            submeshIdx++;
        }

        // Transparent quads
        if (transparentQuads.Count > 0)
        {
            AddMeshIndices(transparentQuads.Count, mesh, nextPointIdx, submeshIdx);
            materials[submeshIdx] = new Material(Shader.Find("Voxel/PointQuadsTransparent"));

            nextPointIdx += transparentQuads.Count;
            submeshIdx++;
        }
    }
Ejemplo n.º 25
0
 public static List <Box> MakeBoxes(VoxelSet <Vec4b> voxels)
 {
     return(MakeBoxes(voxels.Project(ToSolid)));
 }
Ejemplo n.º 26
0
 public IPDMeshCreator(VoxelSet voxelSet, bool smartUpdate) : this(voxelSet)
 {
     this.smartUpdate = smartUpdate;
 }
Ejemplo n.º 27
0
 static bool IsTransparent(VoxelSet <Vec4b> voxels, Vec3i idx)
 {
     return(voxels[idx].w > 0 && voxels[idx].w < 255);
 }