Last active
February 18, 2020 22:33
-
-
Save coty-crg/378d560f622f6c5a2558a32ca5a730a7 to your computer and use it in GitHub Desktop.
Helper script for importing magicavoxel files into c#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using System.IO; | |
[System.Serializable] | |
public class MagicaVoxelModel_PACK : MagicaVoxelChunk | |
{ | |
public int numModels; // num of SIZE and SYZI chunks | |
public bool TryFillFromBuffer(byte[] buffer, ref int startIndex) | |
{ | |
base.FillFromBuffer(buffer, ref startIndex); | |
var matching = Id[0] == 'P' && Id[1] == 'A' && Id[2] == 'C' && Id[3] == 'K'; | |
if (!matching) | |
{ | |
startIndex -= 4; // char[4] | |
startIndex -= 4; // int | |
startIndex -= 4; // int | |
return false; | |
} | |
numModels = MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
return true; | |
} | |
} | |
[System.Serializable] | |
public class MagicaVoxelModel_SIZE : MagicaVoxelChunk | |
{ | |
public int size_x; | |
public int size_y; | |
public int size_z; // gravity direction | |
public override void FillFromBuffer(byte[] buffer, ref int startIndex) | |
{ | |
base.FillFromBuffer(buffer, ref startIndex); | |
MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
} | |
} | |
[System.Serializable] | |
public class MagicaVoxelVoxel | |
{ | |
public byte x; | |
public byte y; | |
public byte z; | |
public byte colorIndex; | |
public void FillFromBuffer(byte[] buffer, ref int startIndex) | |
{ | |
x = MathExtensions.ReadFromStreamByte(buffer, ref startIndex); | |
y = MathExtensions.ReadFromStreamByte(buffer, ref startIndex); | |
z = MathExtensions.ReadFromStreamByte(buffer, ref startIndex); | |
colorIndex = MathExtensions.ReadFromStreamByte(buffer, ref startIndex); | |
} | |
} | |
[System.Serializable] | |
public class MagicaVoxelModel_XYZI : MagicaVoxelChunk | |
{ | |
public int numVoxels; | |
public MagicaVoxelVoxel[] voxels; | |
public override void FillFromBuffer(byte[] buffer, ref int startIndex) | |
{ | |
base.FillFromBuffer(buffer, ref startIndex); | |
numVoxels = MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
if(numVoxels < 0) | |
{ | |
Debug.LogWarningFormat("Tried to make voxel buffer size: {0}", numVoxels); | |
voxels = new MagicaVoxelVoxel[0]; | |
return; | |
} | |
voxels = new MagicaVoxelVoxel[numVoxels]; | |
for(var i = 0; i < numVoxels; ++i) | |
{ | |
var voxel = new MagicaVoxelVoxel(); | |
voxel.FillFromBuffer(buffer, ref startIndex); | |
voxels[i] = voxel; | |
} | |
} | |
} | |
[System.Serializable] | |
public class MagicaVoxelPalleteEntry | |
{ | |
public byte r; | |
public byte g; | |
public byte b; | |
public byte a; | |
public void FillFromBuffer(byte[] buffer, ref int startIndex) | |
{ | |
r = MathExtensions.ReadFromStreamByte(buffer, ref startIndex); | |
g = MathExtensions.ReadFromStreamByte(buffer, ref startIndex); | |
b = MathExtensions.ReadFromStreamByte(buffer, ref startIndex); | |
a = MathExtensions.ReadFromStreamByte(buffer, ref startIndex); | |
} | |
} | |
[System.Serializable] | |
public class MagicaVoxelModel_RGBA : MagicaVoxelChunk | |
{ | |
public MagicaVoxelPalleteEntry[] Pallette = new MagicaVoxelPalleteEntry[256]; // (R, G, B, A) : 1 byte for each component | |
public bool TryFillFromBuffer(byte[] buffer, ref int startIndex) | |
{ | |
base.FillFromBuffer(buffer, ref startIndex); | |
var matching = Id[0] == 'R' && Id[1] == 'G' && Id[2] == 'B' && Id[3] == 'A'; | |
if (!matching) | |
{ | |
startIndex -= 4; // char[4] | |
startIndex -= 4; // int | |
startIndex -= 4; // int | |
return false; | |
} | |
for (var i = 0; i < Pallette.Length; ++i) | |
{ | |
var entry = new MagicaVoxelPalleteEntry(); | |
entry.FillFromBuffer(buffer, ref startIndex); | |
Pallette[i] = entry; | |
} | |
return true; | |
} | |
} | |
[System.Serializable] | |
public class MagicaVoxelModel_MATT : MagicaVoxelChunk | |
{ | |
public int MatId; | |
public int materialType; | |
public int materialWeight; | |
public int propertyBits; | |
public float[] normalizedPropertyValue; // (N) | |
// danger, not overloading | |
public bool TryFillFromBuffer(byte[] buffer, ref int startIndex) | |
{ | |
base.FillFromBuffer(buffer, ref startIndex); | |
var matching = Id[0] == 'M' && Id[1] == 'A' && Id[2] == 'T' && Id[3] == 'T'; | |
if (!matching) | |
{ | |
startIndex -= 4; // char[4] | |
startIndex -= 4; // int | |
startIndex -= 4; // int | |
return false; | |
} | |
MatId = MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
materialType = MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
materialWeight = MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
propertyBits = MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
normalizedPropertyValue = new float[numBytesOfChunkContent]; | |
for (var i = 0; i < numBytesOfChunkContent; ++i) | |
{ | |
normalizedPropertyValue[i] = MathExtensions.ReadFromStreamFloatReversed(buffer, ref startIndex); | |
} | |
return true; | |
} | |
} | |
[System.Serializable] | |
public class MagicaVoxelChunk | |
{ | |
public char[] Id = new char[4]; | |
public int numBytesOfChunkContent; // (N) | |
public int numBytesOfChildrenChunks; // (M) | |
public virtual void FillFromBuffer(byte[] buffer, ref int startIndex) | |
{ | |
MathExtensions.ReadFromStreamCharBuffer(buffer, Id, 0, Id.Length, ref startIndex); | |
numBytesOfChunkContent = MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
numBytesOfChildrenChunks = MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
Debug.LogFormat("{0}{1}{2}{3}: {4}, {5}", | |
Id[0], Id[1], Id[2], Id[3], numBytesOfChunkContent, numBytesOfChildrenChunks); | |
} | |
} | |
[System.Serializable] | |
public class MagicaVoxelFile | |
{ | |
public char[] Id = new char[4]; | |
public int Version; | |
public MagicaVoxelChunk ChunkMain = new MagicaVoxelChunk(); | |
public List<MagicaVoxelModel_SIZE> SizeChunks = new List<MagicaVoxelModel_SIZE>(); | |
public List<MagicaVoxelModel_XYZI> XYZIChunks = new List<MagicaVoxelModel_XYZI>(); | |
public MagicaVoxelModel_RGBA RGBAChunk = new MagicaVoxelModel_RGBA(); | |
public List<MagicaVoxelModel_MATT> MattChunks = new List<MagicaVoxelModel_MATT>(); | |
// not from file, dont serialize | |
public bool HasRGBAChunk; | |
public static MagicaVoxelFile ReadFromBuffer(byte[] buffer, ref int startIndex) | |
{ | |
// file info | |
var magicaVoxelFile = new MagicaVoxelFile(); | |
MathExtensions.ReadFromStreamCharBuffer(buffer, magicaVoxelFile.Id, 0, magicaVoxelFile.Id.Length, ref startIndex); | |
magicaVoxelFile.Version = MathExtensions.ReadFromStreamReversed(buffer, ref startIndex); | |
// main chunk | |
magicaVoxelFile.ChunkMain.FillFromBuffer(buffer, ref startIndex); | |
var targetIndex = startIndex + magicaVoxelFile.ChunkMain.numBytesOfChildrenChunks - sizeof(int) * 256 - 4 - 4 - 4; | |
while(startIndex < targetIndex && startIndex < buffer.Length) // danger zone | |
{ | |
Debug.LogFormat("startIndex: {0} / targetIndex: {1}", startIndex, targetIndex); | |
var sizeChunk = new MagicaVoxelModel_SIZE(); | |
sizeChunk.FillFromBuffer(buffer, ref startIndex); | |
magicaVoxelFile.SizeChunks.Add(sizeChunk); | |
var xyziChunk = new MagicaVoxelModel_XYZI(); | |
xyziChunk.FillFromBuffer(buffer, ref startIndex); | |
magicaVoxelFile.XYZIChunks.Add(xyziChunk); | |
} | |
magicaVoxelFile.HasRGBAChunk = magicaVoxelFile.RGBAChunk.TryFillFromBuffer(buffer, ref startIndex); | |
if (magicaVoxelFile.HasRGBAChunk) | |
{ | |
// might be more matts, not checking yet | |
} | |
return magicaVoxelFile; | |
} | |
public static uint[] default_palette = new uint[256] { | |
0x00000000, 0xffffffff, 0xffccffff, 0xff99ffff, 0xff66ffff, 0xff33ffff, 0xff00ffff, 0xffffccff, 0xffccccff, 0xff99ccff, 0xff66ccff, 0xff33ccff, 0xff00ccff, 0xffff99ff, 0xffcc99ff, 0xff9999ff, | |
0xff6699ff, 0xff3399ff, 0xff0099ff, 0xffff66ff, 0xffcc66ff, 0xff9966ff, 0xff6666ff, 0xff3366ff, 0xff0066ff, 0xffff33ff, 0xffcc33ff, 0xff9933ff, 0xff6633ff, 0xff3333ff, 0xff0033ff, 0xffff00ff, | |
0xffcc00ff, 0xff9900ff, 0xff6600ff, 0xff3300ff, 0xff0000ff, 0xffffffcc, 0xffccffcc, 0xff99ffcc, 0xff66ffcc, 0xff33ffcc, 0xff00ffcc, 0xffffcccc, 0xffcccccc, 0xff99cccc, 0xff66cccc, 0xff33cccc, | |
0xff00cccc, 0xffff99cc, 0xffcc99cc, 0xff9999cc, 0xff6699cc, 0xff3399cc, 0xff0099cc, 0xffff66cc, 0xffcc66cc, 0xff9966cc, 0xff6666cc, 0xff3366cc, 0xff0066cc, 0xffff33cc, 0xffcc33cc, 0xff9933cc, | |
0xff6633cc, 0xff3333cc, 0xff0033cc, 0xffff00cc, 0xffcc00cc, 0xff9900cc, 0xff6600cc, 0xff3300cc, 0xff0000cc, 0xffffff99, 0xffccff99, 0xff99ff99, 0xff66ff99, 0xff33ff99, 0xff00ff99, 0xffffcc99, | |
0xffcccc99, 0xff99cc99, 0xff66cc99, 0xff33cc99, 0xff00cc99, 0xffff9999, 0xffcc9999, 0xff999999, 0xff669999, 0xff339999, 0xff009999, 0xffff6699, 0xffcc6699, 0xff996699, 0xff666699, 0xff336699, | |
0xff006699, 0xffff3399, 0xffcc3399, 0xff993399, 0xff663399, 0xff333399, 0xff003399, 0xffff0099, 0xffcc0099, 0xff990099, 0xff660099, 0xff330099, 0xff000099, 0xffffff66, 0xffccff66, 0xff99ff66, | |
0xff66ff66, 0xff33ff66, 0xff00ff66, 0xffffcc66, 0xffcccc66, 0xff99cc66, 0xff66cc66, 0xff33cc66, 0xff00cc66, 0xffff9966, 0xffcc9966, 0xff999966, 0xff669966, 0xff339966, 0xff009966, 0xffff6666, | |
0xffcc6666, 0xff996666, 0xff666666, 0xff336666, 0xff006666, 0xffff3366, 0xffcc3366, 0xff993366, 0xff663366, 0xff333366, 0xff003366, 0xffff0066, 0xffcc0066, 0xff990066, 0xff660066, 0xff330066, | |
0xff000066, 0xffffff33, 0xffccff33, 0xff99ff33, 0xff66ff33, 0xff33ff33, 0xff00ff33, 0xffffcc33, 0xffcccc33, 0xff99cc33, 0xff66cc33, 0xff33cc33, 0xff00cc33, 0xffff9933, 0xffcc9933, 0xff999933, | |
0xff669933, 0xff339933, 0xff009933, 0xffff6633, 0xffcc6633, 0xff996633, 0xff666633, 0xff336633, 0xff006633, 0xffff3333, 0xffcc3333, 0xff993333, 0xff663333, 0xff333333, 0xff003333, 0xffff0033, | |
0xffcc0033, 0xff990033, 0xff660033, 0xff330033, 0xff000033, 0xffffff00, 0xffccff00, 0xff99ff00, 0xff66ff00, 0xff33ff00, 0xff00ff00, 0xffffcc00, 0xffcccc00, 0xff99cc00, 0xff66cc00, 0xff33cc00, | |
0xff00cc00, 0xffff9900, 0xffcc9900, 0xff999900, 0xff669900, 0xff339900, 0xff009900, 0xffff6600, 0xffcc6600, 0xff996600, 0xff666600, 0xff336600, 0xff006600, 0xffff3300, 0xffcc3300, 0xff993300, | |
0xff663300, 0xff333300, 0xff003300, 0xffff0000, 0xffcc0000, 0xff990000, 0xff660000, 0xff330000, 0xff0000ee, 0xff0000dd, 0xff0000bb, 0xff0000aa, 0xff000088, 0xff000077, 0xff000055, 0xff000044, | |
0xff000022, 0xff000011, 0xff00ee00, 0xff00dd00, 0xff00bb00, 0xff00aa00, 0xff008800, 0xff007700, 0xff005500, 0xff004400, 0xff002200, 0xff001100, 0xffee0000, 0xffdd0000, 0xffbb0000, 0xffaa0000, | |
0xff880000, 0xff770000, 0xff550000, 0xff440000, 0xff220000, 0xff110000, 0xffeeeeee, 0xffdddddd, 0xffbbbbbb, 0xffaaaaaa, 0xff888888, 0xff777777, 0xff555555, 0xff444444, 0xff222222, 0xff111111 | |
}; | |
} | |
public class MagicaVoxelFormatHelper : MonobehaviorSingleton<MagicaVoxelFormatHelper> | |
{ | |
public MagicaVoxelFile file = new MagicaVoxelFile(); | |
public Mesh tempMesh; | |
public string magicaVoxelFilename = "default.vox"; | |
public string saveChunkDataAs = "magicaToChunkData.world"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
note for the missing extension helper: