示例#1
0
        /// <summary>
        /// Count the size of all materials chunks
        /// </summary>
        /// <returns></returns>
        private int CountMaterialChunkSize()
        {
            int usedIndexColor = 0;

            Console.WriteLine("[LOG] Started to create an optimized palette...");
            int globalIndex = 0;

            using (ProgressBar progressBar = new ProgressBar())
            {
                for (int i = 0; i < _models.Count; i++)
                {
                    VoxModel model = _models[i];
                    for (int j = 0; j < model.palette.Length; j++)
                    {
                        Color color = model.palette[j];
                        if (_usedColors.Count < 256 && !_usedColors.Contains(color) && color != Color.Empty && _models[i].colorUsed.Contains(j))
                        {
                            _usedIndexColors[usedIndexColor] = new KeyValuePair <int, int>(i, j);
                            _usedColors.Add(color);
                            usedIndexColor++;
                        }

                        globalIndex++;
                        progressBar.Report(globalIndex / (float)(_models.Count * 256));
                    }
                }
            }
            Console.WriteLine("[LOG] Done.");

            int size = 0;

            for (int i = 0; i < 256; i++)
            {
                if (_usedIndexColors.ContainsKey(i))
                {
                    KeyValuePair <int, int> modelIndex = _usedIndexColors[i];
                    if (_models[modelIndex.Key].materialChunks.Count > modelIndex.Value - 1)
                    {
                        size += Encoding.UTF8.GetByteCount(MATL) + 16;

                        size += _models[modelIndex.Key].materialChunks[modelIndex.Value - 1].properties.Sum(keyValue => 8 + Encoding.UTF8.GetByteCount(keyValue.Key) + Encoding.UTF8.GetByteCount(keyValue.Value));
                    }
                }
                else
                {
                    if (_models[0].materialChunks.Count > 0)
                    {
                        size += Encoding.UTF8.GetByteCount(MATL) + 16;
                        size += _models[0].materialChunks[0].properties.Sum(keyValue => 8 + Encoding.UTF8.GetByteCount(keyValue.Key) + Encoding.UTF8.GetByteCount(keyValue.Value));
                    }
                }
            }

            return(size);
        }
示例#2
0
        private void CheckDuplicateChildGroupIds(VoxModel output)
        {
            List <int> childIds   = output.groupNodeChunks.SelectMany(t => t.childIds).ToList();
            List <int> duplicates = childIds.GroupBy(x => x)
                                    .Where(g => g.Count() > 1)
                                    .Select(y => y.Key)
                                    .ToList();

            foreach (int id in duplicates)
            {
                Console.WriteLine("[ERROR] Duplicate child group ID: " + id);
            }
        }
示例#3
0
        public VoxModel LoadModel(string absolutePath, bool writeLog = false, bool debug = false)
        {
            VoxModel output = new VoxModel();

            output.colorUsed = new HashSet <int>();
            var name = Path.GetFileNameWithoutExtension(absolutePath);

            _voxelCountLastXYZIChunk = 0;
            _logOutputFile           = name + "-" + DateTime.Now.ToString("y-MM-d_HH.m.s") + ".txt";
            _writeLog = writeLog;
            using (var reader = new BinaryReader(new MemoryStream(File.ReadAllBytes(absolutePath))))
            {
                var head = new string(reader.ReadChars(4));
                if (!head.Equals(HEADER))
                {
                    Console.WriteLine("Not a Magicavoxel file! " + output);
                    return(null);
                }
                int version = reader.ReadInt32();
                if (version != VERSION)
                {
                    Console.WriteLine("Version number: " + version + " Was designed for version: " + VERSION);
                }
                ResetModel(output);
                _childCount = 0;
                _chunkCount = 0;
                while (reader.BaseStream.Position != reader.BaseStream.Length)
                {
                    ReadChunk(reader, output);
                }
            }

            if (debug)
            {
                CheckDuplicateIds(output);
                CheckDuplicateChildGroupIds(output);
                CheckTransformIdNotInGroup(output);
                Console.ReadKey();
            }


            if (output.palette == null)
            {
                output.palette = LoadDefaultPalette();
            }
            return(output);
        }
示例#4
0
 /// <summary>
 /// Clear model data
 /// </summary>
 /// <param name="model"></param>
 protected void ResetModel(VoxModel model)
 {
     if (model.voxelFrames != null)
     {
         model.voxelFrames.Clear();
     }
     else
     {
         model.voxelFrames = new List <VoxelData>();
     }
     model.materialChunks.Clear();
     model.transformNodeChunks.Clear();
     model.groupNodeChunks.Clear();
     model.shapeNodeChunks.Clear();
     model.layerChunks.Clear();
     model.rendererSettingChunks.Clear();
 }
示例#5
0
        private void CheckDuplicateIds(VoxModel output)
        {
            List <int> allIds = output.groupNodeChunks.Select(t => t.id).ToList();

            allIds.AddRange(output.transformNodeChunks.Select(t => t.id));
            allIds.AddRange(output.shapeNodeChunks.Select(t => t.id));

            List <int> duplicates = allIds.GroupBy(x => x)
                                    .Where(g => g.Count() > 1)
                                    .Select(y => y.Key)
                                    .ToList();

            foreach (int id in duplicates)
            {
                Console.WriteLine("[ERROR] Duplicate ID: " + id);
            }
        }
示例#6
0
        private void CheckTransformIdNotInGroup(VoxModel output)
        {
            List <int> ids      = output.transformNodeChunks.Select(t => t.id).ToList();
            List <int> childIds = output.groupNodeChunks.SelectMany(t => t.childIds).ToList();

            List <int> empty = new List <int>();

            foreach (int id in ids)
            {
                if (childIds.IndexOf(id) == -1 && id != 0)
                {
                    empty.Add(id);
                }
            }

            foreach (int id in empty)
            {
                Console.WriteLine("[ERROR] Transform ID never called in any group: " + id);
            }
        }
示例#7
0
        /// <summary>
        /// Write XYZI chunk
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="index"></param>
        private int WriteXyziChunk(BinaryWriter writer, VoxModel model, int index)
        {
            int byteWritten = 0;

            writer.Write(Encoding.UTF8.GetBytes(XYZI));
            //int testA = (model.voxelFrames[index].Colors.Count(t => t != 0));
            //int testB = model.voxelFrames[index].Colors.Length;
            writer.Write((model.voxelFrames[index].Colors.Count(t => t != 0) * 4) + 4); //XYZI chunk size
            writer.Write(0);                                                            //Child chunk size (constant)
            writer.Write(model.voxelFrames[index].Colors.Count(t => t != 0));           //Blocks count

            byteWritten += Encoding.UTF8.GetByteCount(XYZI) + 12;
            int count = 0;

            for (int y = 0; y < model.voxelFrames[index].VoxelsTall; y++)
            {
                for (int z = 0; z < model.voxelFrames[index].VoxelsDeep; z++)
                {
                    for (int x = 0; x < model.voxelFrames[index].VoxelsWide; x++)
                    {
                        int   paletteIndex = model.voxelFrames[index].Get(x, y, z);
                        Color color        = model.palette[paletteIndex];

                        if (color != Color.Empty)
                        {
                            writer.Write((byte)(x % model.voxelFrames[index].VoxelsWide));
                            writer.Write((byte)(y % model.voxelFrames[index].VoxelsTall));
                            writer.Write((byte)(z % model.voxelFrames[index].VoxelsDeep));

                            int i = _usedColors.IndexOf(color) + 1;
                            writer.Write((i != 0) ? (byte)i : (byte)1);
                            count++;

                            byteWritten += 4;
                        }
                    }
                }
            }

            return(byteWritten);
        }
示例#8
0
        private void WriteLogs(string chunkName, int chunkSize, int childChunkSize, VoxModel output)
        {
            if (!Directory.Exists("logs"))
            {
                Directory.CreateDirectory("logs");
            }

            string path = "logs/" + _logOutputFile;

            using (var writer = new StreamWriter(path, true))
            {
                writer.WriteLine("CHUNK NAME: " + chunkName + " (" + _chunkCount + ")");
                writer.WriteLine("CHUNK SIZE: " + chunkSize + " BYTES");
                writer.WriteLine("CHILD CHUNK SIZE: " + childChunkSize);
                switch (chunkName)
                {
                case SIZE:
                    var frame = output.voxelFrames[_childCount - 1];
                    writer.WriteLine("-> SIZE: " + frame.VoxelsWide + " " + frame.VoxelsTall + " " + frame.VoxelsDeep);
                    break;

                case XYZI:
                    writer.WriteLine("-> XYZI: " + _voxelCountLastXYZIChunk);
                    break;

                case nTRN:
                    var transform = output.transformNodeChunks.Last();
                    writer.WriteLine("-> TRANSFORM NODE: " + transform.id);
                    writer.WriteLine("--> CHILD ID: " + transform.childId);
                    writer.WriteLine("--> RESERVED ID: " + transform.reservedId);
                    writer.WriteLine("--> LAYER ID: " + transform.layerId);
                    DisplayAttributes(transform.attributes, writer);
                    DisplayFrameAttributes(transform.frameAttributes, writer);
                    break;

                case nGRP:
                    var group = output.groupNodeChunks.Last();
                    writer.WriteLine("-> GROUP NODE: " + group.id);
                    group.childIds.ToList().ForEach(t => writer.WriteLine("--> CHILD ID: " + t));
                    DisplayAttributes(group.attributes, writer);
                    break;

                case nSHP:
                    var shape = output.shapeNodeChunks.Last();
                    writer.WriteLine("-> SHAPE NODE: " + shape.id);
                    DisplayAttributes(shape.attributes, writer);
                    DisplayModelAttributes(shape.models, writer);
                    break;

                case LAYR:
                    var layer = output.layerChunks.Last();
                    writer.WriteLine("-> LAYER NODE: " + layer.id + " " +
                                     layer.Name + " " +
                                     layer.Hidden + " " +
                                     layer.unknown);
                    DisplayAttributes(layer.attributes, writer);
                    break;

                case MATL:
                    var material = output.materialChunks.Last();
                    writer.WriteLine("-> MATERIAL NODE: " + material.id.ToString("F1"));
                    writer.WriteLine("--> ALPHA: " + material.Alpha.ToString("F1"));
                    writer.WriteLine("--> EMISSION: " + material.Emission.ToString("F1"));
                    writer.WriteLine("--> FLUX: " + material.Flux.ToString("F1"));
                    writer.WriteLine("--> METALLIC: " + material.Metallic.ToString("F1"));
                    writer.WriteLine("--> ROUGH: " + material.Rough.ToString("F1"));
                    writer.WriteLine("--> SMOOTHNESS: " + material.Smoothness.ToString("F1"));
                    writer.WriteLine("--> SPEC: " + material.Spec.ToString("F1"));
                    writer.WriteLine("--> WEIGHT: " + material.Weight.ToString("F1"));
                    DisplayAttributes(material.properties, writer);
                    break;
                }
                writer.WriteLine("");
                writer.Close();
            }
        }
示例#9
0
        private void ReadChunk(BinaryReader reader, VoxModel output)
        {
            var chunkName      = new string(reader.ReadChars(4));
            var chunkSize      = reader.ReadInt32();
            var childChunkSize = reader.ReadInt32();
            var chunk          = reader.ReadBytes(chunkSize);
            var children       = reader.ReadBytes(childChunkSize);

            _chunkCount++;

            using (var chunkReader = new BinaryReader(new MemoryStream(chunk)))
            {
                switch (chunkName)
                {
                case MAIN:
                    break;

                case SIZE:
                    int w = chunkReader.ReadInt32();
                    int h = chunkReader.ReadInt32();
                    int d = chunkReader.ReadInt32();
                    if (_childCount >= output.voxelFrames.Count)
                    {
                        output.voxelFrames.Add(new VoxelData());
                    }
                    output.voxelFrames[_childCount].Resize(w, h, d);
                    _childCount++;
                    break;

                case XYZI:
                    _voxelCountLastXYZIChunk = chunkReader.ReadInt32();
                    var  frame = output.voxelFrames[_childCount - 1];
                    byte x, y, z, color;
                    for (int i = 0; i < _voxelCountLastXYZIChunk; i++)
                    {
                        x     = chunkReader.ReadByte();
                        y     = chunkReader.ReadByte();
                        z     = chunkReader.ReadByte();
                        color = chunkReader.ReadByte();
                        frame.Set(x, y, z, color);
                        output.colorUsed.Add(color);
                    }
                    break;

                case RGBA:
                    output.palette = LoadPalette(chunkReader);
                    break;

                case MATT:
                    break;

                case PACK:
                    int frameCount = chunkReader.ReadInt32();
                    for (int i = 0; i < frameCount; i++)
                    {
                        output.voxelFrames.Add(new VoxelData());
                    }
                    break;

                case nTRN:
                    output.transformNodeChunks.Add(ReadTransformNodeChunk(chunkReader));
                    break;

                case nGRP:
                    output.groupNodeChunks.Add(ReadGroupNodeChunk(chunkReader));
                    break;

                case nSHP:
                    output.shapeNodeChunks.Add(ReadShapeNodeChunk(chunkReader));
                    break;

                case LAYR:
                    output.layerChunks.Add(ReadLayerChunk(chunkReader));
                    break;

                case MATL:
                    output.materialChunks.Add(ReadMaterialChunk(chunkReader));
                    break;

                case rOBJ:
                    output.rendererSettingChunks.Add(ReaddRObjectChunk(chunkReader));
                    break;

                default:
                    Console.WriteLine($"Unknown chunk: \"{chunkName}\"");
                    break;
                }
            }

            if (_writeLog)
            {
                WriteLogs(chunkName, chunkSize, childChunkSize, output);
            }

            //read child chunks
            using (var childReader = new BinaryReader(new MemoryStream(children)))
            {
                while (childReader.BaseStream.Position != childReader.BaseStream.Length)
                {
                    ReadChunk(childReader, output);
                }
            }
        }