Ejemplo n.º 1
0
        static VoxelData Read(BinaryReader reader)
        {
            var magic   = reader.ReadUInt32();
            var version = reader.ReadInt32();

            if (magic != VOX_)
            {
                return(null);
            }

            var voxelData = null as VoxelData;
            var colors    = null as Color[];

            while (reader.PeekChar() != -1)
            {
                var chunkId     = reader.ReadUInt32();
                var chunkSize   = reader.ReadInt32();
                var childChunks = reader.ReadInt32();

                switch (chunkId)
                {
                case SIZE:
                    var sx = reader.ReadInt32();
                    var sy = reader.ReadInt32();
                    var sz = reader.ReadInt32();
                    reader.ReadBytes(chunkSize - sizeof(int) * 3);
                    voxelData = new VoxelData(new XYZ(sx, sy, sz), new Color[256]);
                    break;

                case XYZI:
                    var n = reader.ReadInt32();
                    for (var i = 0; i < n; ++i)
                    {
                        var x = reader.ReadByte();
                        var y = reader.ReadByte();
                        var z = reader.ReadByte();
                        var c = reader.ReadByte();
                        voxelData[new XYZ(x, y, z)] = new Voxel()
                        {
                            Index = c
                        };
                    }
                    break;

                case RGBA:
                    colors = new Color[256];
                    // last color is not used, so we only need to read 255 colors
                    for (var i = 1; i < 256; ++i)
                    {
                        byte r = reader.ReadByte();
                        byte g = reader.ReadByte();
                        byte b = reader.ReadByte();
                        byte a = reader.ReadByte();
                        voxelData.Colors[i] = new Color(r, g, b, a);
                    }
                    // NOTICE : skip the last reserved color
                    reader.ReadUInt32();
                    break;

                default:
                    reader.ReadBytes(chunkSize);
                    break;
                }
            }

            if (voxelData != null && colors == null)
            {
                for (var i = 0; i < DefaultColors.Length; ++i)
                {
                    voxelData.Colors[i] = new Color(DefaultColors[i]);
                }
            }

            return(voxelData);
        }
Ejemplo n.º 2
0
        void RenderQuad(VoxelData voxelData, XYZ p, Color color, float lightLevel, XYZ faceUp)
        {
            // Only render quad if face it isn't hidden by voxel above it
            if (voxelData[p + faceUp].Index == 0)
            {
                // Calculate adjacent voxels
                var adjacent = new XYZ[] { XYZ.Zero, XYZ.Zero, XYZ.Zero, XYZ.Zero };
                if (faceUp == -XYZ.OneX)
                {
                    adjacent = new[] { XYZ.OneY, XYZ.OneZ, -XYZ.OneY, -XYZ.OneZ };
                }
                if (faceUp == -XYZ.OneY)
                {
                    adjacent = new[] { XYZ.OneZ, XYZ.OneX, -XYZ.OneZ, -XYZ.OneX };
                }
                if (faceUp == -XYZ.OneZ)
                {
                    adjacent = new[] { XYZ.OneX, XYZ.OneY, -XYZ.OneX, -XYZ.OneY };
                }
                if (faceUp == XYZ.OneX)
                {
                    adjacent = new[] { XYZ.OneZ, XYZ.OneY, -XYZ.OneZ, -XYZ.OneY };
                }
                if (faceUp == XYZ.OneY)
                {
                    adjacent = new[] { XYZ.OneX, XYZ.OneZ, -XYZ.OneX, -XYZ.OneZ };
                }
                if (faceUp == XYZ.OneZ)
                {
                    adjacent = new[] { XYZ.OneY, XYZ.OneX, -XYZ.OneY, -XYZ.OneX };
                }

                // Calculate ambient occlusion vertex colors
                var a00 = AmbientOcclusion.CalculateAO(voxelData, p, adjacent[0], adjacent[1], faceUp);
                var a01 = AmbientOcclusion.CalculateAO(voxelData, p, adjacent[1], adjacent[2], faceUp);
                var a11 = AmbientOcclusion.CalculateAO(voxelData, p, adjacent[2], adjacent[3], faceUp);
                var a10 = AmbientOcclusion.CalculateAO(voxelData, p, adjacent[3], adjacent[0], faceUp);

                // Ignore shadow face there is no occlusion
                if (p.Z == -1 && (a00 + a01 + a11 + a10) == 12)
                {
                    return;
                }

                // Store vertex colors
                colors.AddRange(new[] { color *lightLevel, color *lightLevel, color *lightLevel, color *lightLevel });

                // Calculate occlusion values
                occlusion.Add(AmbientOcclusion.AOToOcclusion(a00));
                occlusion.Add(AmbientOcclusion.AOToOcclusion(a01));
                occlusion.Add(AmbientOcclusion.AOToOcclusion(a11));
                occlusion.Add(AmbientOcclusion.AOToOcclusion(a10));

                // Calculate quad vertices based on adjacent voxels
                var v0 = p + (adjacent[0] + adjacent[1] + faceUp + XYZ.One) / 2;
                var v1 = p + (adjacent[1] + adjacent[2] + faceUp + XYZ.One) / 2;
                var v2 = p + (adjacent[2] + adjacent[3] + faceUp + XYZ.One) / 2;
                var v3 = p + (adjacent[3] + adjacent[0] + faceUp + XYZ.One) / 2;
                var n  = vertices.Count;
                vertices.AddRange(new[] { v0, v1, v2, v3 });

                // Populate Normals
                normals.AddRange(new[] { faceUp, faceUp, faceUp, faceUp });

                // Add face primitives for MeshType
                var i0 = (n + 0);
                var i1 = (n + 1);
                var i2 = (n + 2);
                var i3 = (n + 3);
                switch (settings.MeshType)
                {
                case MeshType.Triangles:
                    // Change quad -> triangle face orientation based on ambient occlusion
                    if (a00 + a11 <= a01 + a10)
                    {
                        faces.AddRange(new[] { i1, i2, i3, i3, i0, i1 });
                    }
                    else
                    {
                        faces.AddRange(new[] { i0, i1, i2, i2, i3, i0 });
                    }
                    break;

                case MeshType.Quads:
                    faces.AddRange(new [] { i0, i1, i2, i3 });
                    break;
                }
            }
        }
Ejemplo n.º 3
0
 public static void Write(Stream stream, VoxelData voxelData)
 {
     Write(new BinaryWriter(stream), voxelData);
 }
Ejemplo n.º 4
0
 public MeshBuilder(VoxelData voxelData, MeshSettings settings)
 {
     this.settings = settings;
     CreateMesh(voxelData);
 }