public VoxModel LoadModel(string absolutePath) { VoxModel output = new VoxModel(); var name = Path.GetFileNameWithoutExtension(absolutePath); _logOutputFile = name + "-" + DateTime.Now.ToString("y-MM-d_HH.m.s") + ".txt"; 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 (output.palette == null) { output.palette = LoadDefaultPalette(); } return(output); }
/// <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(); }
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, d, h); _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); } 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; } } 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); } } }
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(); } }