[
  {
    "path": ".gitattributes",
    "content": "# git files\n.gitattributes export-ignore\n.gitignore export-ignore\n# Folders/Files\nScreenshots/ export-ignore"
  },
  {
    "path": ".gitignore",
    "content": "*.meta\nStandard Assets\nMaterials"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 ~ 2018 Rui\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "MagicaVoxel for Unity 2017\n========\n### VOXFileLoader ###\n　　The VOXFileLoader is a .vox reader to convert the .vox file from [MagicaVoxel](https://ephtracy.github.io/) to static GameObject and Prefab with optimized obj file.\n\n![Alt](./Screenshots/screenshots.png)\n\nHow to use:\n========\n* Download a zip archive from the github page\n* Un-zip the archive\n* Copy the VOXFileLoader folder to Assets folder\n* Open Window -> Tools -> Cubizer -> show VOXFileLoader inspector\n* Select .vox file in the project view\n* Click 'Create Prefab from .vox file' button, you'll get a prefab and obj file from project view\n\nFeatures:\n------------\n* Voxel file import for [MagicalVoxel](http://voxel.codeplex.com/)\n* Mesh Optimization\n* Level of detail\n\nRequirements:\n========\n* Unity 2017.2.0 or higher\n\nContact:\n------------\n\n* Reach me via Twitter: [@Rui](https://twitter.com/Rui_cg).\n\n[License (MIT)](https://raw.githubusercontent.com/ray-cast/ray-mmd/developing/LICENSE.txt)\n-------------------------------------------------------------------------------\n    Copyright (C) 2016-2017 Ray-MMD Developers. All rights reserved.\n\n    https://github.com/ray-cast/UnityVOXFileImport\n\n    Permission is hereby granted, free of charge, to any person obtaining a\n    copy of this software and associated documentation files (the \"Software\"),\n    to deal in the Software without restriction, including without limitation\n    the rights to use, copy, modify, merge, publish, distribute, sublicense,\n    and/or sell copies of the Software, and to permit persons to whom the\n    Software is furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included\n    in all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n    BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\n    AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nReferences:\n--------\n* Meshing in a Minecraft Game \\[[link](https://0fps.net/2012/07/07/meshing-minecraft-part-2/)\\]"
  },
  {
    "path": "VOXFileLoader/Editor/VOXFileLoader.cs",
    "content": "﻿using System;\nusing System.IO;\n\nusing UnityEngine;\nusing UnityEditor;\n\nusing Cubizer;\nusing Cubizer.Model;\n\npublic class VOXFileLoader : EditorWindow\n{\n\tpublic bool _isSelectCreatePrefab = true;\n\tpublic bool _isSelectCreateAssetbundle = true;\n\n\t[MenuItem(\"Tools/Cubizer/Show VOXFileLoader Inspector\")]\n\tpublic static void ShowWindow()\n\t{\n\t\tVOXFileLoader.CreateInstance<VOXFileLoader>().Show();\n\t}\n\n\t[MenuItem(\"Tools/Cubizer/Load .vox file as Prefab\")]\n\tpublic static void LoadVoxelFileAsPrefab()\n\t{\n\t\tvar filepath = EditorUtility.OpenFilePanel(\"Load .vox file\", \"\", \"vox\");\n\t\tif (!String.IsNullOrEmpty(filepath))\n\t\t{\n\t\t\tif (!filepath.Contains(\".vox\"))\n\t\t\t{\n\t\t\t\tEditorUtility.DisplayDialog(\"Invalid File\", \"The end of the path wasn't \\\".vox\\\"\", \"Ok\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tVoxFileImport.LoadVoxelFileAsPrefab(filepath);\n\t\t}\n\t}\n\n\t[MenuItem(\"Tools/Cubizer/Load .vox file as GameObject\")]\n\tpublic static void LoadVoxelFileAsGameObject()\n\t{\n\t\tvar filepath = EditorUtility.OpenFilePanel(\"Load .vox file\", \"\", \"vox\");\n\t\tif (!String.IsNullOrEmpty(filepath))\n\t\t{\n\t\t\tif (!filepath.Contains(\".vox\"))\n\t\t\t{\n\t\t\t\tEditorUtility.DisplayDialog(\"Invalid File\", \"The end of the path wasn't \\\".vox\\\"\", \"Ok\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tVoxFileImport.LoadVoxelFileAsGameObject(filepath);\n\t\t}\n\t}\n\n\tpublic void OnGUI()\n\t{\n\t\tGUILayout.Label(\"Selected Object:\", EditorStyles.boldLabel);\n\n\t\tthis._isSelectCreatePrefab = EditorGUILayout.Foldout(this._isSelectCreatePrefab, \"Create Model from .vox file\");\n\t\tif (this._isSelectCreatePrefab)\n\t\t{\n\t\t\tif (GUILayout.Button(\"Create Prefab from .vox file\"))\n\t\t\t\tCreateVoxelPrefabsFromSelection();\n\n\t\t\tif (GUILayout.Button(\"Create Prefab LOD from .vox file\"))\n\t\t\t\tCreateVoxelPrefabsFromSelection(3);\n\n\t\t\tif (GUILayout.Button(\"Create GameObject from .vox file\"))\n\t\t\t\tCreateVoxelGameObjectFromSelection();\n\n\t\t\tif (GUILayout.Button(\"Create GameObject LOD from .vox file\"))\n\t\t\t\tCreateVoxelGameObjectFromSelection(3);\n\t\t}\n\n\t\tthis._isSelectCreateAssetbundle = EditorGUILayout.Foldout(this._isSelectCreateAssetbundle, \"Create AssetBundle\");\n\t\tif (this._isSelectCreateAssetbundle)\n\t\t{\n\t\t\tif (GUILayout.Button(\"Selection To StreamingAssets folder\"))\n\t\t\t\tCreateAssetBundlesFromSelectionToStreamingAssets();\n\n\t\t\tif (GUILayout.Button(\"Selection To Selected Folder\"))\n\t\t\t\tCreateAssetBundlesWithFolderPanel();\n\t\t}\n\t}\n\n\tprivate static bool CreateVoxelPrefabsFromSelection(int lodLevel = 0)\n\t{\n\t\tvar SelectedAsset = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.DeepAssets);\n\t\tif (SelectedAsset.Length == 0)\n\t\t{\n\t\t\tEditorUtility.DisplayDialog(\"No Object Selected\", \"Please select any .vox file to create to prefab\", \"Ok\");\n\t\t\treturn false;\n\t\t}\n\n\t\tforeach (var asset in SelectedAsset)\n\t\t{\n\t\t\tvar path = AssetDatabase.GetAssetPath(asset);\n\t\t\tif (Path.GetExtension(path) != \".vox\")\n\t\t\t{\n\t\t\t\tEditorUtility.DisplayDialog(\"Invalid File\", \"The end of the path wasn't \\\".vox\\\"\", \"Ok\");\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (path.Remove(0, path.LastIndexOf('.')) == \".vox\")\n\t\t\t{\n\t\t\t\tif (lodLevel == 0)\n\t\t\t\t\tVoxFileImport.LoadVoxelFileAsPrefab(path);\n\t\t\t\telse\n\t\t\t\t\tVoxFileImport.LoadVoxelFileAsPrefab(path, \"Assets/\", lodLevel);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate static bool CreateVoxelGameObjectFromSelection(int lodLevel = 0)\n\t{\n\t\tvar SelectedAsset = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.DeepAssets);\n\t\tif (SelectedAsset.Length == 0)\n\t\t{\n\t\t\tEditorUtility.DisplayDialog(\"No Object Selected\", \"Please select any .vox file to create to prefab\", \"Ok\");\n\t\t\treturn false;\n\t\t}\n\n\t\tforeach (var asset in SelectedAsset)\n\t\t{\n\t\t\tvar path = AssetDatabase.GetAssetPath(asset);\n\t\t\tif (Path.GetExtension(path) != \".vox\")\n\t\t\t{\n\t\t\t\tEditorUtility.DisplayDialog(\"Invalid File\", \"The end of the path wasn't \\\".vox\\\"\", \"Ok\");\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (path.Remove(0, path.LastIndexOf('.')) == \".vox\")\n\t\t\t{\n\t\t\t\tif (lodLevel == 0)\n\t\t\t\t\tVoxFileImport.LoadVoxelFileAsGameObject(path);\n\t\t\t\telse\n\t\t\t\t\tVoxFileImport.LoadVoxelFileAsGameObjectLOD(path, lodLevel);\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate static void CreateAssetBundlesFromSelection(string targetPath, string bundleName = \"Resource\", string ext = \"\")\n\t{\n\t\tvar SelectedAsset = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.DeepAssets);\n\n\t\tif (SelectedAsset.Length > 0)\n\t\t{\n\t\t\tAssetBundleBuild[] buildMap = new AssetBundleBuild[2];\n\t\t\tbuildMap[0].assetBundleName = bundleName + ext;\n\t\t\tbuildMap[0].assetNames = new string[SelectedAsset.Length];\n\n\t\t\tfor (int i = 0; i < SelectedAsset.Length; i++)\n\t\t\t\tbuildMap[0].assetNames[i] = AssetDatabase.GetAssetPath(SelectedAsset[i]);\n\n\t\t\tif (!BuildPipeline.BuildAssetBundles(targetPath, buildMap, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows))\n\t\t\t\tUnityEngine.Debug.Log(targetPath + \": failed to load\");\n\n\t\t\tAssetDatabase.Refresh();\n\t\t}\n\t}\n\n\tprivate static void CreateAssetBundlesWithFolderPanel(string bundleName = \"Resource\", string ext = \"\")\n\t{\n\t\tvar SelectedPath = EditorUtility.SaveFolderPanel(\"Save Resource\", \"\", \"New Resource\");\n\t\tif (SelectedPath.Length == 0)\n\t\t\treturn;\n\n\t\tCreateAssetBundlesFromSelection(SelectedPath + \"/\", bundleName, ext);\n\t}\n\n\tprivate static void CreateAssetBundlesFromSelectionToStreamingAssets(string bundleName = \"Resource\", string ext = \"\")\n\t{\n\t\tCreateAssetBundlesFromSelection(Application.dataPath + \"/StreamingAssets/\", bundleName, ext);\n\t}\n}"
  },
  {
    "path": "VOXFileLoader/Scripts/ObjFileExport.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Diagnostics;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Runtime.Serialization.Formatters.Binary;\nusing System.Text;\nusing System.Linq.Expressions;\n\nusing UnityEngine;\n\nnamespace Cubizer\n{\n\tnamespace Model\n\t{\n\t\tpublic class ObjFileExport\n\t\t{\n\t\t\tpublic static string MeshToString(MeshFilter mf, Vector3 scale)\n\t\t\t{\n\t\t\t\tMesh mesh = mf.sharedMesh;\n\n\t\t\t\tDictionary<int, int> dictionary = new Dictionary<int, int>();\n\n\t\t\t\tif (mesh.subMeshCount > 1)\n\t\t\t\t{\n\t\t\t\t\tint[] triangles = mesh.GetTriangles(1);\n\n\t\t\t\t\tfor (int j = 0; j < triangles.Length; j += 3)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!dictionary.ContainsKey(triangles[j]))\n\t\t\t\t\t\t\tdictionary.Add(triangles[j], 1);\n\n\t\t\t\t\t\tif (!dictionary.ContainsKey(triangles[j + 1]))\n\t\t\t\t\t\t\tdictionary.Add(triangles[j + 1], 1);\n\n\t\t\t\t\t\tif (!dictionary.ContainsKey(triangles[j + 2]))\n\t\t\t\t\t\t\tdictionary.Add(triangles[j + 2], 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tStringBuilder stringBuilder = new StringBuilder().Append(\"mtllib design.mtl\").Append(\"\\n\").Append(\"g \").Append(mf.name).Append(\"\\n\");\n\n\t\t\t\tVector3[] vertices = mesh.vertices;\n\t\t\t\tforeach (Vector3 v in mesh.vertices)\n\t\t\t\t{\n\t\t\t\t\tstringBuilder.Append(string.Format(\"v {0} {1} {2}\\n\", v.x * scale.x, v.y * scale.y, v.z * scale.z));\n\t\t\t\t}\n\n\t\t\t\tstringBuilder.Append(\"\\n\");\n\n\t\t\t\tforeach (Vector3 n in mesh.normals)\n\t\t\t\t\tstringBuilder.Append(string.Format(\"vn {0} {1} {2}\\n\", -n.x, -n.y, n.z));\n\n\t\t\t\tfor (int num = 0; num != mesh.uv.Length; num++)\n\t\t\t\t{\n\t\t\t\t\tVector2 uv = mesh.uv[num];\n\n\t\t\t\t\tif (dictionary.ContainsKey(num))\n\t\t\t\t\t\tstringBuilder.Append(string.Format(\"vt {0} {1}\\n\", mesh.uv[num].x, mesh.uv[num].y));\n\t\t\t\t\telse\n\t\t\t\t\t\tstringBuilder.Append(string.Format(\"vt {0} {1}\\n\", uv.x, uv.y));\n\t\t\t\t}\n\n\t\t\t\tfor (int k = 0; k < mesh.subMeshCount; k++)\n\t\t\t\t{\n\t\t\t\t\tstringBuilder.Append(\"\\n\");\n\n\t\t\t\t\tif (k == 0)\n\t\t\t\t\t\tstringBuilder.Append(\"usemtl \").Append(\"Material_design\").Append(\"\\n\");\n\n\t\t\t\t\tif (k == 1)\n\t\t\t\t\t\tstringBuilder.Append(\"usemtl \").Append(\"Material_logo\").Append(\"\\n\");\n\n\t\t\t\t\tint[] triangles2 = mesh.GetTriangles(k);\n\n\t\t\t\t\tfor (int l = 0; l < triangles2.Length; l += 3)\n\t\t\t\t\t\tstringBuilder.Append(string.Format(\"f {0}/{0} {1}/{1} {2}/{2}\\n\", triangles2[l] + 1, triangles2[l + 2] + 1, triangles2[l + 1] + 1));\n\t\t\t\t}\n\n\t\t\t\treturn stringBuilder.ToString();\n\t\t\t}\n\n\t\t\tpublic static void WriteToFile(string path, MeshFilter mf, Vector3 scale)\n\t\t\t{\n\t\t\t\tusing (var sw = new StreamWriter(path))\n\t\t\t\t{\n\t\t\t\t\tsw.Write(MeshToString(mf, new Vector3(-1f, 1f, 1f)));\n\t\t\t\t\tsw.Close();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "VOXFileLoader/Scripts/VOXCruncher.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\n\nusing UnityEngine;\n\nnamespace Cubizer\n{\n\tnamespace Model\n\t{\n\t\tusing VOXMaterial = System.Int32;\n\n\t\tpublic enum VOXCruncherMode\n\t\t{\n\t\t\tStupid,\n\t\t\tCulled,\n\t\t\tGreedy,\n\t\t}\n\n\t\tpublic struct VOXVisiableFaces\n\t\t{\n\t\t\tpublic bool left;\n\t\t\tpublic bool right;\n\t\t\tpublic bool bottom;\n\t\t\tpublic bool top;\n\t\t\tpublic bool back;\n\t\t\tpublic bool front;\n\n\t\t\tpublic VOXVisiableFaces(bool _left, bool _right, bool _bottom, bool _top, bool _back, bool _front)\n\t\t\t{\n\t\t\t\tleft = _left;\n\t\t\t\tright = _right;\n\t\t\t\tbottom = _bottom;\n\t\t\t\ttop = _top;\n\t\t\t\tback = _back;\n\t\t\t\tfront = _front;\n\t\t\t}\n\t\t}\n\n\t\tpublic class VOXCruncher\n\t\t{\n\t\t\tpublic struct Vector3\n\t\t\t{\n\t\t\t\tpublic int x;\n\t\t\t\tpublic int y;\n\t\t\t\tpublic int z;\n\t\t\t}\n\n\t\t\tpublic Vector3 begin;\n\t\t\tpublic Vector3 end;\n\n\t\t\tpublic VOXMaterial material;\n\t\t\tpublic VOXVisiableFaces faces;\n\n\t\t\tpublic VOXCruncher(Vector3 begin, Vector3 end, VOXMaterial _material)\n\t\t\t{\n\t\t\t\tthis.begin = begin;\n\t\t\t\tthis.end = end;\n\n\t\t\t\tmaterial = _material;\n\n\t\t\t\tfaces.left = true;\n\t\t\t\tfaces.right = true;\n\t\t\t\tfaces.top = true;\n\t\t\t\tfaces.bottom = true;\n\t\t\t\tfaces.front = true;\n\t\t\t\tfaces.back = true;\n\t\t\t}\n\n\t\t\tpublic VOXCruncher(int begin_x, int end_x, int begin_y, int end_y, int begin_z, int end_z, VOXMaterial _material)\n\t\t\t{\n\t\t\t\tbegin.x = begin_x;\n\t\t\t\tbegin.y = begin_y;\n\t\t\t\tbegin.z = begin_z;\n\n\t\t\t\tend.x = end_x;\n\t\t\t\tend.y = end_y;\n\t\t\t\tend.z = end_z;\n\n\t\t\t\tmaterial = _material;\n\n\t\t\t\tfaces.left = true;\n\t\t\t\tfaces.right = true;\n\t\t\t\tfaces.top = true;\n\t\t\t\tfaces.bottom = true;\n\t\t\t\tfaces.front = true;\n\t\t\t\tfaces.back = true;\n\t\t\t}\n\n\t\t\tpublic VOXCruncher(int begin_x, int end_x, int begin_y, int end_y, int begin_z, int end_z, VOXVisiableFaces _faces, VOXMaterial _material)\n\t\t\t{\n\t\t\t\tbegin.x = begin_x;\n\t\t\t\tbegin.y = begin_y;\n\t\t\t\tbegin.z = begin_z;\n\n\t\t\t\tend.x = end_x;\n\t\t\t\tend.y = end_y;\n\t\t\t\tend.z = end_z;\n\n\t\t\t\tmaterial = _material;\n\t\t\t\tfaces = _faces;\n\t\t\t}\n\t\t}\n\n\t\tpublic interface IVOXCruncherStrategy\n\t\t{\n\t\t\tVOXModel CalcVoxelCruncher(VoxData chunk, Color32[] palette);\n\t\t}\n\n\t\tpublic class VOXCruncherStupid : IVOXCruncherStrategy\n\t\t{\n\t\t\tpublic VOXModel CalcVoxelCruncher(VoxData chunk, Color32[] palette)\n\t\t\t{\n\t\t\t\tvar crunchers = new VOXCruncher[chunk.count];\n\t\t\t\tvar faces = new VOXVisiableFaces(true, true, true, true, true, true);\n\n\t\t\t\tint n = 0;\n\n\t\t\t\tfor (int i = 0; i < chunk.x; ++i)\n\t\t\t\t{\n\t\t\t\t\tfor (int j = 0; j < chunk.y; ++j)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (int k = 0; k < chunk.z; ++k)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar m = chunk.voxels[i, j, k];\n\t\t\t\t\t\t\tif (m != int.MaxValue)\n\t\t\t\t\t\t\t\tcrunchers[n++] = new VOXCruncher(i, i, j, j, k, k, faces, m);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn new VOXModel(crunchers);\n\t\t\t}\n\t\t}\n\n\t\tpublic class VOXCruncherCulled : IVOXCruncherStrategy\n\t\t{\n\t\t\tpublic static bool GetVisiableFaces(VOXMaterial[,,] map, Vector3Int bound, int x, int y, int z, VOXMaterial material, Color32[] palette, out VOXVisiableFaces faces)\n\t\t\t{\n\t\t\t\tVOXMaterial[] instanceID = new VOXMaterial[6] { VOXMaterial.MaxValue, VOXMaterial.MaxValue, VOXMaterial.MaxValue, VOXMaterial.MaxValue, VOXMaterial.MaxValue, VOXMaterial.MaxValue };\n\n\t\t\t\tif (x >= 1) instanceID[0] = map[(byte)(x - 1), y, z];\n\t\t\t\tif (y >= 1) instanceID[2] = map[x, (byte)(y - 1), z];\n\t\t\t\tif (z >= 1) instanceID[4] = map[x, y, (byte)(z - 1)];\n\t\t\t\tif (x <= bound.x) instanceID[1] = map[(byte)(x + 1), y, z];\n\t\t\t\tif (y <= bound.y) instanceID[3] = map[x, (byte)(y + 1), z];\n\t\t\t\tif (z <= bound.z) instanceID[5] = map[x, y, (byte)(z + 1)];\n\n\t\t\t\tvar alpha = palette[material].a;\n\t\t\t\tif (alpha < 255)\n\t\t\t\t{\n\t\t\t\t\tbool f1 = (instanceID[0] == VOXMaterial.MaxValue) ? true : palette[instanceID[0]].a != alpha ? true : false;\n\t\t\t\t\tbool f2 = (instanceID[1] == VOXMaterial.MaxValue) ? true : palette[instanceID[1]].a != alpha ? true : false;\n\t\t\t\t\tbool f3 = (instanceID[2] == VOXMaterial.MaxValue) ? true : palette[instanceID[2]].a != alpha ? true : false;\n\t\t\t\t\tbool f4 = (instanceID[3] == VOXMaterial.MaxValue) ? true : palette[instanceID[3]].a != alpha ? true : false;\n\t\t\t\t\tbool f5 = (instanceID[4] == VOXMaterial.MaxValue) ? true : palette[instanceID[4]].a != alpha ? true : false;\n\t\t\t\t\tbool f6 = (instanceID[5] == VOXMaterial.MaxValue) ? true : palette[instanceID[5]].a != alpha ? true : false;\n\n\t\t\t\t\tfaces.left = f1;\n\t\t\t\t\tfaces.right = f2;\n\t\t\t\t\tfaces.bottom = f3;\n\t\t\t\t\tfaces.top = f4;\n\t\t\t\t\tfaces.front = f5;\n\t\t\t\t\tfaces.back = f6;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbool f1 = (instanceID[0] == VOXMaterial.MaxValue) ? true : palette[instanceID[0]].a < 255 ? true : false;\n\t\t\t\t\tbool f2 = (instanceID[1] == VOXMaterial.MaxValue) ? true : palette[instanceID[1]].a < 255 ? true : false;\n\t\t\t\t\tbool f3 = (instanceID[2] == VOXMaterial.MaxValue) ? true : palette[instanceID[2]].a < 255 ? true : false;\n\t\t\t\t\tbool f4 = (instanceID[3] == VOXMaterial.MaxValue) ? true : palette[instanceID[3]].a < 255 ? true : false;\n\t\t\t\t\tbool f5 = (instanceID[4] == VOXMaterial.MaxValue) ? true : palette[instanceID[4]].a < 255 ? true : false;\n\t\t\t\t\tbool f6 = (instanceID[5] == VOXMaterial.MaxValue) ? true : palette[instanceID[5]].a < 255 ? true : false;\n\n\t\t\t\t\tfaces.left = f1;\n\t\t\t\t\tfaces.right = f2;\n\t\t\t\t\tfaces.bottom = f3;\n\t\t\t\t\tfaces.top = f4;\n\t\t\t\t\tfaces.front = f5;\n\t\t\t\t\tfaces.back = f6;\n\t\t\t\t}\n\n\t\t\t\treturn faces.left | faces.right | faces.bottom | faces.top | faces.front | faces.back;\n\t\t\t}\n\n\t\t\tpublic VOXModel CalcVoxelCruncher(VoxData chunk, Color32[] palette)\n\t\t\t{\n\t\t\t\tvar crunchers = new List<VOXCruncher>();\n\t\t\t\tvar bound = new Vector3Int(chunk.x, chunk.y, chunk.z);\n\n\t\t\t\tfor (int i = 0; i < chunk.x; ++i)\n\t\t\t\t{\n\t\t\t\t\tfor (int j = 0; j < chunk.y; ++j)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (int k = 0; k < chunk.z; ++k)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar c = chunk.voxels[i, j, k];\n\t\t\t\t\t\t\tif (c != int.MaxValue)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tVOXVisiableFaces faces;\n\t\t\t\t\t\t\t\tif (!GetVisiableFaces(chunk.voxels, bound, i, j, k, c, palette, out faces))\n\t\t\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\t\t\tcrunchers.Add(new VOXCruncher((byte)i, (byte)i, (byte)j, (byte)j, (byte)k, (byte)k, faces, c));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar array = new VOXCruncher[crunchers.Count];\n\n\t\t\t\tint numbers = 0;\n\t\t\t\tforeach (var it in crunchers)\n\t\t\t\t\tarray[numbers++] = it;\n\n\t\t\t\treturn new VOXModel(array);\n\t\t\t}\n\t\t}\n\n\t\tpublic class VOXCruncherGreedy : IVOXCruncherStrategy\n\t\t{\n\t\t\tpublic VOXModel CalcVoxelCruncher(VoxData chunk, Color32[] palette)\n\t\t\t{\n\t\t\t\tvar crunchers = new List<VOXCruncher>();\n\t\t\t\tvar dims = new int[] { chunk.x, chunk.y, chunk.z };\n\n\t\t\t\tvar alloc = System.Math.Max(dims[0], System.Math.Max(dims[1], dims[2]));\n\t\t\t\tvar mask = new int[alloc * alloc];\n\t\t\t\tvar map = chunk.voxels;\n\n\t\t\t\tfor (var d = 0; d < 3; ++d)\n\t\t\t\t{\n\t\t\t\t\tvar u = (d + 1) % 3;\n\t\t\t\t\tvar v = (d + 2) % 3;\n\n\t\t\t\t\tvar x = new int[3] { 0, 0, 0 };\n\t\t\t\t\tvar q = new int[3] { 0, 0, 0 };\n\n\t\t\t\t\tq[d] = 1;\n\n\t\t\t\t\tvar faces = new VOXVisiableFaces(false, false, false, false, false, false);\n\n\t\t\t\t\tfor (x[d] = -1; x[d] < dims[d];)\n\t\t\t\t\t{\n\t\t\t\t\t\tvar n = 0;\n\n\t\t\t\t\t\tfor (x[v] = 0; x[v] < dims[v]; ++x[v])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (x[u] = 0; x[u] < dims[u]; ++x[u])\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvar a = x[d] >= 0 ? map[x[0], x[1], x[2]] : VOXMaterial.MaxValue;\n\t\t\t\t\t\t\t\tvar b = x[d] < dims[d] - 1 ? map[x[0] + q[0], x[1] + q[1], x[2] + q[2]] : VOXMaterial.MaxValue;\n\t\t\t\t\t\t\t\tif (a != b)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (a == VOXMaterial.MaxValue)\n\t\t\t\t\t\t\t\t\t\tmask[n++] = b;\n\t\t\t\t\t\t\t\t\telse if (b == VOXMaterial.MaxValue)\n\t\t\t\t\t\t\t\t\t\tmask[n++] = -a;\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tmask[n++] = -b;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tmask[n++] = VOXMaterial.MaxValue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t++x[d];\n\n\t\t\t\t\t\tn = 0;\n\n\t\t\t\t\t\tfor (var j = 0; j < dims[v]; ++j)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (var i = 0; i < dims[u];)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvar c = mask[n];\n\t\t\t\t\t\t\t\tif (c == VOXMaterial.MaxValue)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t++i; ++n;\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tvar w = 1;\n\t\t\t\t\t\t\t\tvar h = 1;\n\t\t\t\t\t\t\t\tvar k = 0;\n\n\t\t\t\t\t\t\t\tfor (; (i + w) < dims[u] && c == mask[n + w]; ++w) { }\n\n\t\t\t\t\t\t\t\tvar done = false;\n\t\t\t\t\t\t\t\tfor (; (j + h) < dims[v]; ++h)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfor (k = 0; k < w; ++k)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif (c != mask[n + k + h * dims[u]])\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif (done)\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tx[u] = i; x[v] = j;\n\n\t\t\t\t\t\t\t\tvar du = new int[3] { 0, 0, 0 };\n\t\t\t\t\t\t\t\tvar dv = new int[3] { 0, 0, 0 };\n\n\t\t\t\t\t\t\t\tdu[u] = w;\n\t\t\t\t\t\t\t\tdv[v] = h;\n\n\t\t\t\t\t\t\t\tvar v1 = new Vector3(x[0], x[1], x[2]);\n\t\t\t\t\t\t\t\tvar v2 = new Vector3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], x[2] + du[2] + dv[2]);\n\n\t\t\t\t\t\t\t\tv2.x = System.Math.Max(v2.x - 1, 0);\n\t\t\t\t\t\t\t\tv2.y = System.Math.Max(v2.y - 1, 0);\n\t\t\t\t\t\t\t\tv2.z = System.Math.Max(v2.z - 1, 0);\n\n\t\t\t\t\t\t\t\tif (c > 0)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfaces.front = d == 2;\n\t\t\t\t\t\t\t\t\tfaces.back = false;\n\t\t\t\t\t\t\t\t\tfaces.left = d == 0;\n\t\t\t\t\t\t\t\t\tfaces.right = false;\n\t\t\t\t\t\t\t\t\tfaces.top = false;\n\t\t\t\t\t\t\t\t\tfaces.bottom = d == 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tc = -c;\n\t\t\t\t\t\t\t\t\tfaces.front = false;\n\t\t\t\t\t\t\t\t\tfaces.back = d == 2;\n\t\t\t\t\t\t\t\t\tfaces.left = false;\n\t\t\t\t\t\t\t\t\tfaces.right = d == 0;\n\t\t\t\t\t\t\t\t\tfaces.top = d == 1;\n\t\t\t\t\t\t\t\t\tfaces.bottom = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcrunchers.Add(new VOXCruncher((byte)v1.x, (byte)(v2.x), (byte)(v1.y), (byte)(v2.y), (byte)(v1.z), (byte)(v2.z), faces, c));\n\n\t\t\t\t\t\t\t\tfor (var l = 0; l < h; ++l)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfor (k = 0; k < w; ++k)\n\t\t\t\t\t\t\t\t\t\tmask[n + k + l * dims[u]] = VOXMaterial.MaxValue;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\ti += w; n += w;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar array = new VOXCruncher[crunchers.Count];\n\n\t\t\t\tint numbers = 0;\n\t\t\t\tforeach (var it in crunchers)\n\t\t\t\t\tarray[numbers++] = it;\n\n\t\t\t\treturn new VOXModel(array);\n\t\t\t}\n\t\t}\n\n\t\tpublic class VOXPolygonCruncher\n\t\t{\n\t\t\tpublic static VOXModel CalcVoxelCruncher(VoxData chunk, Color32[] palette, VOXCruncherMode mode)\n\t\t\t{\n\t\t\t\tswitch (mode)\n\t\t\t\t{\n\t\t\t\t\tcase VOXCruncherMode.Stupid:\n\t\t\t\t\t\treturn new VOXCruncherStupid().CalcVoxelCruncher(chunk, palette);\n\n\t\t\t\t\tcase VOXCruncherMode.Culled:\n\t\t\t\t\t\treturn new VOXCruncherCulled().CalcVoxelCruncher(chunk, palette);\n\n\t\t\t\t\tcase VOXCruncherMode.Greedy:\n\t\t\t\t\t\treturn new VOXCruncherGreedy().CalcVoxelCruncher(chunk, palette);\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "VOXFileLoader/Scripts/VOXFileImport.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\n\nusing UnityEngine;\n\n#if UNITY_EDITOR\n\nusing UnityEditor;\n\n#endif\n\nnamespace Cubizer\n{\n\tnamespace Model\n\t{\n\t\tpublic struct VoxFileHeader\n\t\t{\n\t\t\tpublic byte[] header;\n\t\t\tpublic Int32 version;\n\t\t}\n\n\t\tpublic struct VoxFilePack\n\t\t{\n\t\t\tpublic byte[] name;\n\t\t\tpublic Int32 chunkContent;\n\t\t\tpublic Int32 chunkNums;\n\t\t\tpublic Int32 modelNums;\n\t\t}\n\n\t\tpublic struct VoxFileSize\n\t\t{\n\t\t\tpublic byte[] name;\n\t\t\tpublic Int32 chunkContent;\n\t\t\tpublic Int32 chunkNums;\n\t\t\tpublic Int32 x;\n\t\t\tpublic Int32 y;\n\t\t\tpublic Int32 z;\n\t\t}\n\n\t\tpublic struct VoxFileXYZI\n\t\t{\n\t\t\tpublic byte[] name;\n\t\t\tpublic Int32 chunkContent;\n\t\t\tpublic Int32 chunkNums;\n\t\t\tpublic VoxData voxels;\n\t\t}\n\n\t\tpublic struct VoxFileRGBA\n\t\t{\n\t\t\tpublic byte[] name;\n\t\t\tpublic Int32 chunkContent;\n\t\t\tpublic Int32 chunkNums;\n\t\t\tpublic uint[] values;\n\t\t}\n\n\t\tpublic struct VoxFileChunkChild\n\t\t{\n\t\t\tpublic VoxFileSize size;\n\t\t\tpublic VoxFileXYZI xyzi;\n\t\t}\n\n\t\tpublic struct VoxFileChunk\n\t\t{\n\t\t\tpublic byte[] name;\n\t\t\tpublic Int32 chunkContent;\n\t\t\tpublic Int32 chunkNums;\n\t\t}\n\n\t\tpublic struct VoxFileMaterial\n\t\t{\n\t\t\tpublic int id;\n\t\t\tpublic int type;\n\t\t\tpublic float weight;\n\t\t\tpublic int propertyBits;\n\t\t\tpublic float[] propertyValue;\n\t\t}\n\n\t\tpublic class VoxFileData\n\t\t{\n\t\t\tpublic VoxFileHeader hdr;\n\t\t\tpublic VoxFileChunk main;\n\t\t\tpublic VoxFilePack pack;\n\t\t\tpublic VoxFileChunkChild[] chunkChild;\n\t\t\tpublic VoxFileRGBA palette;\n\t\t}\n\n\t\tpublic class VoxData\n\t\t{\n\t\t\tpublic int x, y, z;\n\t\t\tpublic int[,,] voxels;\n\n\t\t\tpublic int count\n\t\t\t{\n\t\t\t\tget\n\t\t\t\t{\n\t\t\t\t\tint _count = 0;\n\n\t\t\t\t\tfor (int i = 0; i < x; ++i)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (int j = 0; j < y; ++j)\n\t\t\t\t\t\t\tfor (int k = 0; k < z; ++k)\n\t\t\t\t\t\t\t\tif (voxels[i, j, k] != int.MaxValue)\n\t\t\t\t\t\t\t\t\t_count++;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn _count;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpublic VoxData()\n\t\t\t{\n\t\t\t\tx = 0; y = 0; z = 0;\n\t\t\t}\n\n\t\t\tpublic VoxData(byte[] _voxels, int xx, int yy, int zz)\n\t\t\t{\n\t\t\t\tx = xx;\n\t\t\t\ty = zz;\n\t\t\t\tz = yy;\n\t\t\t\tvoxels = new int[x, y, z];\n\n\t\t\t\tfor (int i = 0; i < x; ++i)\n\t\t\t\t{\n\t\t\t\t\tfor (int j = 0; j < y; ++j)\n\t\t\t\t\t\tfor (int k = 0; k < z; ++k)\n\t\t\t\t\t\t\tvoxels[i, j, k] = int.MaxValue;\n\t\t\t\t}\n\n\t\t\t\tfor (int j = 0; j < _voxels.Length; j += 4)\n\t\t\t\t{\n\t\t\t\t\tvar x = _voxels[j];\n\t\t\t\t\tvar y = _voxels[j + 1];\n\t\t\t\t\tvar z = _voxels[j + 2];\n\t\t\t\t\tvar c = _voxels[j + 3];\n\n\t\t\t\t\tvoxels[x, z, y] = c;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpublic int GetMajorityColorIndex(int xx, int yy, int zz, int lodLevel)\n\t\t\t{\n\t\t\t\txx = Mathf.Min(xx, x - 2);\n\t\t\t\tyy = Mathf.Min(yy, y - 2);\n\t\t\t\tzz = Mathf.Min(zz, z - 2);\n\n\t\t\t\tint[] samples = new int[lodLevel * lodLevel * lodLevel];\n\n\t\t\t\tfor (int i = 0; i < lodLevel; i++)\n\t\t\t\t{\n\t\t\t\t\tfor (int j = 0; j < lodLevel; j++)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (int k = 0; k < lodLevel; k++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (xx + i > x - 1 || yy + j > y - 1 || zz + k > z - 1)\n\t\t\t\t\t\t\t\tsamples[i * lodLevel * lodLevel + j * lodLevel + k] = int.MaxValue;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tsamples[i * lodLevel * lodLevel + j * lodLevel + k] = voxels[xx + i, yy + j, zz + k];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tint maxNum = 1;\n\t\t\t\tint maxNumIndex = 0;\n\n\t\t\t\tint[] numIndex = new int[samples.Length];\n\n\t\t\t\tfor (int i = 0; i < samples.Length; i++)\n\t\t\t\t\tnumIndex[i] = samples[i] == int.MaxValue ? 0 : 1;\n\n\t\t\t\tfor (int i = 0; i < samples.Length; i++)\n\t\t\t\t{\n\t\t\t\t\tfor (int j = 0; j < samples.Length; j++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (i != j && samples[i] != int.MaxValue && samples[i] == samples[j])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnumIndex[i]++;\n\t\t\t\t\t\t\tif (numIndex[i] > maxNum)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmaxNum = numIndex[i];\n\t\t\t\t\t\t\t\tmaxNumIndex = i;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn samples[maxNumIndex];\n\t\t\t}\n\n\t\t\tpublic VoxData GetVoxelDataLOD(int level)\n\t\t\t{\n\t\t\t\tif (x <= 1 || y <= 1 || z <= 1)\n\t\t\t\t\treturn null;\n\n\t\t\t\tlevel = Mathf.Clamp(level, 0, 16);\n\t\t\t\tif (level <= 1)\n\t\t\t\t\treturn this;\n\n\t\t\t\tif (x <= level && y <= level && z <= level)\n\t\t\t\t\treturn this;\n\n\t\t\t\tVoxData data = new VoxData();\n\t\t\t\tdata.x = Mathf.CeilToInt((float)x / level);\n\t\t\t\tdata.y = Mathf.CeilToInt((float)y / level);\n\t\t\t\tdata.z = Mathf.CeilToInt((float)z / level);\n\n\t\t\t\tdata.voxels = new int[data.x, data.y, data.z];\n\n\t\t\t\tfor (int x = 0; x < data.x; x++)\n\t\t\t\t{\n\t\t\t\t\tfor (int y = 0; y < data.y; y++)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (int z = 0; z < data.z; z++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdata.voxels[x, y, z] = this.GetMajorityColorIndex(x * level, y * level, z * level, level);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn data;\n\t\t\t}\n\t\t}\n\n\t\tpublic class VoxFileImport\n\t\t{\n\t\t\tprivate static uint[] _paletteDefault = new uint[256]\n\t\t\t{\n\t\t\t\t0x00000000, 0xffffffff, 0xffccffff, 0xff99ffff, 0xff66ffff, 0xff33ffff, 0xff00ffff, 0xffffccff, 0xffccccff, 0xff99ccff, 0xff66ccff, 0xff33ccff, 0xff00ccff, 0xffff99ff, 0xffcc99ff, 0xff9999ff,\n\t\t\t\t0xff6699ff, 0xff3399ff, 0xff0099ff, 0xffff66ff, 0xffcc66ff, 0xff9966ff, 0xff6666ff, 0xff3366ff, 0xff0066ff, 0xffff33ff, 0xffcc33ff, 0xff9933ff, 0xff6633ff, 0xff3333ff, 0xff0033ff, 0xffff00ff,\n\t\t\t\t0xffcc00ff, 0xff9900ff, 0xff6600ff, 0xff3300ff, 0xff0000ff, 0xffffffcc, 0xffccffcc, 0xff99ffcc, 0xff66ffcc, 0xff33ffcc, 0xff00ffcc, 0xffffcccc, 0xffcccccc, 0xff99cccc, 0xff66cccc, 0xff33cccc,\n\t\t\t\t0xff00cccc, 0xffff99cc, 0xffcc99cc, 0xff9999cc, 0xff6699cc, 0xff3399cc, 0xff0099cc, 0xffff66cc, 0xffcc66cc, 0xff9966cc, 0xff6666cc, 0xff3366cc, 0xff0066cc, 0xffff33cc, 0xffcc33cc, 0xff9933cc,\n\t\t\t\t0xff6633cc, 0xff3333cc, 0xff0033cc, 0xffff00cc, 0xffcc00cc, 0xff9900cc, 0xff6600cc, 0xff3300cc, 0xff0000cc, 0xffffff99, 0xffccff99, 0xff99ff99, 0xff66ff99, 0xff33ff99, 0xff00ff99, 0xffffcc99,\n\t\t\t\t0xffcccc99, 0xff99cc99, 0xff66cc99, 0xff33cc99, 0xff00cc99, 0xffff9999, 0xffcc9999, 0xff999999, 0xff669999, 0xff339999, 0xff009999, 0xffff6699, 0xffcc6699, 0xff996699, 0xff666699, 0xff336699,\n\t\t\t\t0xff006699, 0xffff3399, 0xffcc3399, 0xff993399, 0xff663399, 0xff333399, 0xff003399, 0xffff0099, 0xffcc0099, 0xff990099, 0xff660099, 0xff330099, 0xff000099, 0xffffff66, 0xffccff66, 0xff99ff66,\n\t\t\t\t0xff66ff66, 0xff33ff66, 0xff00ff66, 0xffffcc66, 0xffcccc66, 0xff99cc66, 0xff66cc66, 0xff33cc66, 0xff00cc66, 0xffff9966, 0xffcc9966, 0xff999966, 0xff669966, 0xff339966, 0xff009966, 0xffff6666,\n\t\t\t\t0xffcc6666, 0xff996666, 0xff666666, 0xff336666, 0xff006666, 0xffff3366, 0xffcc3366, 0xff993366, 0xff663366, 0xff333366, 0xff003366, 0xffff0066, 0xffcc0066, 0xff990066, 0xff660066, 0xff330066,\n\t\t\t\t0xff000066, 0xffffff33, 0xffccff33, 0xff99ff33, 0xff66ff33, 0xff33ff33, 0xff00ff33, 0xffffcc33, 0xffcccc33, 0xff99cc33, 0xff66cc33, 0xff33cc33, 0xff00cc33, 0xffff9933, 0xffcc9933, 0xff999933,\n\t\t\t\t0xff669933, 0xff339933, 0xff009933, 0xffff6633, 0xffcc6633, 0xff996633, 0xff666633, 0xff336633, 0xff006633, 0xffff3333, 0xffcc3333, 0xff993333, 0xff663333, 0xff333333, 0xff003333, 0xffff0033,\n\t\t\t\t0xffcc0033, 0xff990033, 0xff660033, 0xff330033, 0xff000033, 0xffffff00, 0xffccff00, 0xff99ff00, 0xff66ff00, 0xff33ff00, 0xff00ff00, 0xffffcc00, 0xffcccc00, 0xff99cc00, 0xff66cc00, 0xff33cc00,\n\t\t\t\t0xff00cc00, 0xffff9900, 0xffcc9900, 0xff999900, 0xff669900, 0xff339900, 0xff009900, 0xffff6600, 0xffcc6600, 0xff996600, 0xff666600, 0xff336600, 0xff006600, 0xffff3300, 0xffcc3300, 0xff993300,\n\t\t\t\t0xff663300, 0xff333300, 0xff003300, 0xffff0000, 0xffcc0000, 0xff990000, 0xff660000, 0xff330000, 0xff0000ee, 0xff0000dd, 0xff0000bb, 0xff0000aa, 0xff000088, 0xff000077, 0xff000055, 0xff000044,\n\t\t\t\t0xff000022, 0xff000011, 0xff00ee00, 0xff00dd00, 0xff00bb00, 0xff00aa00, 0xff008800, 0xff007700, 0xff005500, 0xff004400, 0xff002200, 0xff001100, 0xffee0000, 0xffdd0000, 0xffbb0000, 0xffaa0000,\n\t\t\t\t0xff880000, 0xff770000, 0xff550000, 0xff440000, 0xff220000, 0xff110000, 0xffeeeeee, 0xffdddddd, 0xffbbbbbb, 0xffaaaaaa, 0xff888888, 0xff777777, 0xff555555, 0xff444444, 0xff222222, 0xff111111\n\t\t\t};\n\n\t\t\tprivate static UnityEngine.Object _assetPrefab;\n\n\t\t\tpublic static VoxFileData Load(string path)\n\t\t\t{\n\t\t\t\tusing (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))\n\t\t\t\t{\n\t\t\t\t\tif (stream == null)\n\t\t\t\t\t\tthrow new System.Exception(\"Failed to open file for FileStream.\");\n\n\t\t\t\t\tusing (var reader = new BinaryReader(stream))\n\t\t\t\t\t{\n\t\t\t\t\t\tVoxFileData voxel = new VoxFileData();\n\t\t\t\t\t\tvoxel.hdr.header = reader.ReadBytes(4);\n\t\t\t\t\t\tvoxel.hdr.version = reader.ReadInt32();\n\n\t\t\t\t\t\tif (voxel.hdr.header[0] != 'V' || voxel.hdr.header[1] != 'O' || voxel.hdr.header[2] != 'X' || voxel.hdr.header[3] != ' ')\n\t\t\t\t\t\t\tthrow new System.Exception(\"Bad Token: token is not VOX.\");\n\n\t\t\t\t\t\tif (voxel.hdr.version != 150)\n\t\t\t\t\t\t\tthrow new System.Exception(\"The version of file isn't 150 that version of vox, tihs version of file is \" + voxel.hdr.version + \".\");\n\n\t\t\t\t\t\tvoxel.main.name = reader.ReadBytes(4);\n\t\t\t\t\t\tvoxel.main.chunkContent = reader.ReadInt32();\n\t\t\t\t\t\tvoxel.main.chunkNums = reader.ReadInt32();\n\n\t\t\t\t\t\tif (voxel.main.name[0] != 'M' || voxel.main.name[1] != 'A' || voxel.main.name[2] != 'I' || voxel.main.name[3] != 'N')\n\t\t\t\t\t\t\tthrow new System.Exception(\"Bad Token: token is not MAIN.\");\n\n\t\t\t\t\t\tif (voxel.main.chunkContent != 0)\n\t\t\t\t\t\t\tthrow new System.Exception(\"Bad Token: chunk content is \" + voxel.main.chunkContent + \", it should be 0.\");\n\n\t\t\t\t\t\tif (reader.PeekChar() == 'P')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvoxel.pack.name = reader.ReadBytes(4);\n\t\t\t\t\t\t\tif (voxel.pack.name[0] != 'P' || voxel.pack.name[1] != 'A' || voxel.pack.name[2] != 'C' || voxel.pack.name[3] != 'K')\n\t\t\t\t\t\t\t\tthrow new System.Exception(\"Bad Token: token is not PACK\");\n\n\t\t\t\t\t\t\tvoxel.pack.chunkContent = reader.ReadInt32();\n\t\t\t\t\t\t\tvoxel.pack.chunkNums = reader.ReadInt32();\n\t\t\t\t\t\t\tvoxel.pack.modelNums = reader.ReadInt32();\n\n\t\t\t\t\t\t\tif (voxel.pack.modelNums == 0)\n\t\t\t\t\t\t\t\tthrow new System.Exception(\"Bad Token: model nums must be greater than zero.\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvoxel.pack.chunkContent = 0;\n\t\t\t\t\t\t\tvoxel.pack.chunkNums = 0;\n\t\t\t\t\t\t\tvoxel.pack.modelNums = 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvoxel.chunkChild = new VoxFileChunkChild[voxel.pack.modelNums];\n\n\t\t\t\t\t\tfor (int i = 0; i < voxel.pack.modelNums; i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar chunk = new VoxFileChunkChild();\n\n\t\t\t\t\t\t\tchunk.size.name = reader.ReadBytes(4);\n\t\t\t\t\t\t\tchunk.size.chunkContent = reader.ReadInt32();\n\t\t\t\t\t\t\tchunk.size.chunkNums = reader.ReadInt32();\n\t\t\t\t\t\t\tchunk.size.x = reader.ReadInt32();\n\t\t\t\t\t\t\tchunk.size.y = reader.ReadInt32();\n\t\t\t\t\t\t\tchunk.size.z = reader.ReadInt32();\n\n\t\t\t\t\t\t\tif (chunk.size.name[0] != 'S' || chunk.size.name[1] != 'I' || chunk.size.name[2] != 'Z' || chunk.size.name[3] != 'E')\n\t\t\t\t\t\t\t\tthrow new System.Exception(\"Bad Token: token is not SIZE\");\n\n\t\t\t\t\t\t\tif (chunk.size.chunkContent != 12)\n\t\t\t\t\t\t\t\tthrow new System.Exception(\"Bad Token: chunk content is \" + chunk.size.chunkContent + \", it should be 12.\");\n\n\t\t\t\t\t\t\tchunk.xyzi.name = reader.ReadBytes(4);\n\t\t\t\t\t\t\tif (chunk.xyzi.name[0] != 'X' || chunk.xyzi.name[1] != 'Y' || chunk.xyzi.name[2] != 'Z' || chunk.xyzi.name[3] != 'I')\n\t\t\t\t\t\t\t\tthrow new System.Exception(\"Bad Token: token is not XYZI\");\n\n\t\t\t\t\t\t\tchunk.xyzi.chunkContent = reader.ReadInt32();\n\t\t\t\t\t\t\tchunk.xyzi.chunkNums = reader.ReadInt32();\n\t\t\t\t\t\t\tif (chunk.xyzi.chunkNums != 0)\n\t\t\t\t\t\t\t\tthrow new System.Exception(\"Bad Token: chunk nums is \" + chunk.xyzi.chunkNums + \",i t should be 0.\");\n\n\t\t\t\t\t\t\tvar voxelNums = reader.ReadInt32();\n\t\t\t\t\t\t\tvar voxels = new byte[voxelNums * 4];\n\t\t\t\t\t\t\tif (reader.Read(voxels, 0, voxels.Length) != voxels.Length)\n\t\t\t\t\t\t\t\tthrow new System.Exception(\"Failed to read voxels\");\n\n\t\t\t\t\t\t\tchunk.xyzi.voxels = new VoxData(voxels, chunk.size.x, chunk.size.y, chunk.size.z);\n\n\t\t\t\t\t\t\tvoxel.chunkChild[i] = chunk;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (reader.BaseStream.Position < reader.BaseStream.Length)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbyte[] palette = reader.ReadBytes(4);\n\t\t\t\t\t\t\tif (palette[0] != 'R' || palette[1] != 'G' || palette[2] != 'B' || palette[3] != 'A')\n\t\t\t\t\t\t\t\tthrow new System.Exception(\"Bad Token: token is not RGBA\");\n\n\t\t\t\t\t\t\tvoxel.palette.chunkContent = reader.ReadInt32();\n\t\t\t\t\t\t\tvoxel.palette.chunkNums = reader.ReadInt32();\n\n\t\t\t\t\t\t\tvar bytePalette = new byte[voxel.palette.chunkContent];\n\t\t\t\t\t\t\treader.Read(bytePalette, 0, voxel.palette.chunkContent);\n\n\t\t\t\t\t\t\tvoxel.palette.values = new uint[voxel.palette.chunkContent / 4];\n\n\t\t\t\t\t\t\tfor (int i = 4; i < bytePalette.Length; i += 4)\n\t\t\t\t\t\t\t\tvoxel.palette.values[i / 4] = BitConverter.ToUInt32(bytePalette, i - 4);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvoxel.palette.values = new uint[256];\n\t\t\t\t\t\t\t_paletteDefault.CopyTo(voxel.palette.values, 0);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn voxel;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpublic static Color32[] CreateColor32FromPelatte(uint[] palette)\n\t\t\t{\n\t\t\t\tDebug.Assert(palette.Length == 256);\n\n\t\t\t\tColor32[] colors = new Color32[256];\n\n\t\t\t\tfor (uint j = 0; j < 256; j++)\n\t\t\t\t{\n\t\t\t\t\tuint rgba = palette[j];\n\n\t\t\t\t\tColor32 color = new Color32();\n\t\t\t\t\tcolor.r = (byte)((rgba >> 0) & 0xFF);\n\t\t\t\t\tcolor.g = (byte)((rgba >> 8) & 0xFF);\n\t\t\t\t\tcolor.b = (byte)((rgba >> 16) & 0xFF);\n\t\t\t\t\tcolor.a = (byte)((rgba >> 24) & 0xFF);\n\n\t\t\t\t\tcolors[j] = color;\n\t\t\t\t}\n\n\t\t\t\treturn colors;\n\t\t\t}\n\n\t\t\tpublic static Texture2D CreateTextureFromColor16x16(Color32[] colors)\n\t\t\t{\n\t\t\t\tDebug.Assert(colors.Length == 256);\n\n\t\t\t\tTexture2D texture = new Texture2D(16, 16, TextureFormat.ARGB32, false, false);\n\t\t\t\ttexture.name = \"texture\";\n\t\t\t\ttexture.SetPixels32(colors);\n\t\t\t\ttexture.Apply();\n\n\t\t\t\treturn texture;\n\t\t\t}\n\n\t\t\tpublic static Texture2D CreateTextureFromColor256(Color32[] colors)\n\t\t\t{\n\t\t\t\tDebug.Assert(colors.Length == 256);\n\n\t\t\t\tTexture2D texture = new Texture2D(256, 1, TextureFormat.ARGB32, false, false);\n\t\t\t\ttexture.name = \"texture\";\n\t\t\t\ttexture.SetPixels32(colors);\n\t\t\t\ttexture.Apply();\n\n\t\t\t\treturn texture;\n\t\t\t}\n\n\t\t\tpublic static Texture2D CreateTextureFromPelatte16x16(uint[] palette)\n\t\t\t{\n\t\t\t\tDebug.Assert(palette.Length == 256);\n\t\t\t\treturn CreateTextureFromColor16x16(CreateColor32FromPelatte(palette));\n\t\t\t}\n\n\t\t\tpublic static int CalcFaceCountAsAllocate(VOXModel model, Color32[] palette, ref Dictionary<string, int> entities)\n\t\t\t{\n\t\t\t\tentities.Add(\"opaque\", 0);\n\n\t\t\t\tforeach (var it in model.voxels)\n\t\t\t\t{\n\t\t\t\t\tbool[] visiable = new bool[] { it.faces.left, it.faces.right, it.faces.top, it.faces.bottom, it.faces.front, it.faces.back };\n\n\t\t\t\t\tint facesCount = 0;\n\n\t\t\t\t\tfor (int j = 0; j < 6; j++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (visiable[j])\n\t\t\t\t\t\t\tfacesCount++;\n\t\t\t\t\t}\n\n\t\t\t\t\tentities[\"opaque\"] += facesCount;\n\t\t\t\t}\n\n\t\t\t\treturn entities.Count;\n\t\t\t}\n\n\t\t\tpublic static GameObject CreateGameObject(string name, VoxData data, Texture2D texture, Color32[] colors, float scale)\n\t\t\t{\n\t\t\t\tvar cruncher = VOXPolygonCruncher.CalcVoxelCruncher(data, colors, VOXCruncherMode.Greedy);\n\n\t\t\t\tvar entities = new Dictionary<string, int>();\n\t\t\t\tif (CalcFaceCountAsAllocate(cruncher, colors, ref entities) == 0)\n\t\t\t\t\tthrow new System.Exception(name + \": There is no voxel for this file\");\n\n\t\t\t\tvar model = new GameObject(name);\n\n\t\t\t\tforeach (var entity in entities)\n\t\t\t\t{\n\t\t\t\t\tif (entity.Value == 0)\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\tvar index = 0;\n\t\t\t\t\tvar allocSize = entity.Value;\n\n\t\t\t\t\tvar vertices = new Vector3[allocSize * 4];\n\t\t\t\t\tvar normals = new Vector3[allocSize * 4];\n\t\t\t\t\tvar uv = new Vector2[allocSize * 4];\n\t\t\t\t\tvar triangles = new int[allocSize * 6];\n\n\t\t\t\t\tbool isTransparent = false;\n\n\t\t\t\t\tforeach (var it in cruncher.voxels)\n\t\t\t\t\t{\n\t\t\t\t\t\tVOXModel.CreateCubeMesh16x16(it, ref vertices, ref normals, ref uv, ref triangles, ref index, scale);\n\t\t\t\t\t\tisTransparent |= (colors[it.material].a < 255) ? true : false;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (triangles.Length > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tMesh mesh = new Mesh();\n\t\t\t\t\t\tmesh.name = \"mesh\";\n\t\t\t\t\t\tmesh.vertices = vertices;\n\t\t\t\t\t\tmesh.normals = normals;\n\t\t\t\t\t\tmesh.uv = uv;\n\t\t\t\t\t\tmesh.triangles = triangles;\n\n\t\t\t\t\t\tvar meshFilter = model.AddComponent<MeshFilter>();\n\t\t\t\t\t\tvar meshRenderer = model.AddComponent<MeshRenderer>();\n\n#if UNITY_EDITOR\n\t\t\t\t\t\tMeshUtility.Optimize(mesh);\n\n\t\t\t\t\t\tmeshFilter.sharedMesh = mesh;\n\t\t\t\t\t\tmeshRenderer.sharedMaterial = new Material(Shader.Find(\"Mobile/Diffuse\"));\n\t\t\t\t\t\tmeshRenderer.sharedMaterial.name = \"material\";\n\t\t\t\t\t\tmeshRenderer.sharedMaterial.mainTexture = texture;\n#else\n\t\t\t\t\t\tmeshFilter.mesh = mesh;\n\t\t\t\t\t\tmeshRenderer.material = new Material(Shader.Find(\"Mobile/Diffuse\"));\n\t\t\t\t\t\tmeshRenderer.material.mainTexture = texture;\n#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn model;\n\t\t\t}\n\n\t\t\tpublic static GameObject LoadVoxelFileAsGameObject(string name, VoxFileData voxel, int lodLevel)\n\t\t\t{\n\t\t\t\tDebug.Assert(!String.IsNullOrEmpty(name));\n\n\t\t\t\tGameObject gameObject = new GameObject();\n\t\t\t\tgameObject.name = name;\n\t\t\t\tgameObject.isStatic = true;\n\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tvar colors = CreateColor32FromPelatte(voxel.palette.values);\n\t\t\t\t\tvar texture = CreateTextureFromColor16x16(colors);\n\n\t\t\t\t\tif (lodLevel <= 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tforeach (var chunk in voxel.chunkChild)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar submesh = CreateGameObject(\"model\", chunk.xyzi.voxels, texture, colors, 1);\n\t\t\t\t\t\t\tsubmesh.transform.parent = gameObject.transform;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tforeach (var chunk in voxel.chunkChild)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (int lod = 1; lod < lodLevel + 1; lod++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvar submesh = CreateGameObject(\"lod\" + (lod - 1), chunk.xyzi.voxels.GetVoxelDataLOD(lod), texture, colors, lod);\n\t\t\t\t\t\t\t\tsubmesh.transform.parent = gameObject.transform;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar lodgroup = gameObject.AddComponent<LODGroup>();\n\t\t\t\t\t\t\tvar lods = lodgroup.GetLODs();\n\n\t\t\t\t\t\t\tfor (int i = 0; i < gameObject.transform.childCount; i++)\n\t\t\t\t\t\t\t\tlods[i].renderers = new Renderer[] { gameObject.transform.GetChild(i).GetComponent<MeshRenderer>() };\n\n\t\t\t\t\t\t\tlodgroup.SetLODs(lods);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (SystemException e)\n\t\t\t\t{\n\t\t\t\t\tGameObject.DestroyImmediate(gameObject);\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\n\t\t\t\treturn gameObject;\n\t\t\t}\n\n\t\t\tpublic static GameObject LoadVoxelFileAsGameObject(string path)\n\t\t\t{\n\t\t\t\tvar voxel = VoxFileImport.Load(path);\n\t\t\t\treturn LoadVoxelFileAsGameObject(Path.GetFileNameWithoutExtension(path), voxel, 0);\n\t\t\t}\n\n\t\t\tpublic static GameObject LoadVoxelFileAsGameObjectLOD(string path, int lodLevel)\n\t\t\t{\n\t\t\t\tvar voxel = VoxFileImport.Load(path);\n\t\t\t\treturn LoadVoxelFileAsGameObject(Path.GetFileNameWithoutExtension(path), voxel, lodLevel);\n\t\t\t}\n\n#if UNITY_EDITOR\n\n\t\t\tpublic static GameObject LoadVoxelFileAsPrefab(VoxFileData voxel, string name, string path = \"Assets/\", int lodLevel = 0)\n\t\t\t{\n\t\t\t\tDebug.Assert(!String.IsNullOrEmpty(name));\n\n\t\t\t\tGameObject gameObject = null;\n\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tgameObject = LoadVoxelFileAsGameObject(name, voxel, lodLevel);\n\n\t\t\t\t\tvar prefabPath = path + name + \".prefab\";\n\t\t\t\t\tvar prefab = PrefabUtility.CreateEmptyPrefab(prefabPath);\n\t\t\t\t\tvar prefabTextures = new Dictionary<string, int>();\n\n\t\t\t\t\tfor (int i = 0; i < gameObject.transform.childCount; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tvar subObject = gameObject.transform.GetChild(i);\n\n\t\t\t\t\t\tvar meshFilter = subObject.GetComponent<MeshFilter>();\n\t\t\t\t\t\tif (meshFilter != null)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tAssetDatabase.AddObjectToAsset(meshFilter.sharedMesh, prefabPath);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar renderer = subObject.GetComponent<MeshRenderer>();\n\t\t\t\t\t\tif (renderer != null)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (renderer.sharedMaterial != null)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tAssetDatabase.AddObjectToAsset(renderer.sharedMaterial, prefabPath);\n\n\t\t\t\t\t\t\t\tvar textureName = renderer.sharedMaterial.mainTexture.name;\n\t\t\t\t\t\t\t\tif (!prefabTextures.ContainsKey(textureName))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tprefabTextures.Add(textureName, 1);\n\n\t\t\t\t\t\t\t\t\tAssetDatabase.AddObjectToAsset(renderer.sharedMaterial.mainTexture, prefabPath);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn PrefabUtility.ReplacePrefab(gameObject, prefab, ReplacePrefabOptions.ReplaceNameBased);\n\t\t\t\t}\n\t\t\t\tfinally\n\t\t\t\t{\n\t\t\t\t\tGameObject.DestroyImmediate(gameObject);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpublic static GameObject LoadVoxelFileAsPrefab(string path, string outpath = \"Assets/\", int lodLevel = 0)\n\t\t\t{\n\t\t\t\tvar voxel = VoxFileImport.Load(path);\n\t\t\t\treturn LoadVoxelFileAsPrefab(voxel, Path.GetFileNameWithoutExtension(path), outpath, lodLevel);\n\t\t\t}\n\n#endif\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "VOXFileLoader/Scripts/VOXHashMap.cs",
    "content": "﻿using System;\nusing System.Diagnostics;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Runtime.Serialization.Formatters.Binary;\n\nusing UnityEngine;\n\nnamespace Cubizer\n{\n\tusing VOXMaterial = System.Int32;\n\n\tnamespace Model\n\t{\n\t\t[Serializable]\n\t\tpublic class VOXHashMapNode<_Tx>\n\t\t\twhere _Tx : struct\n\t\t{\n\t\t\tpublic _Tx x;\n\t\t\tpublic _Tx y;\n\t\t\tpublic _Tx z;\n\t\t\tpublic VOXMaterial element;\n\n\t\t\tpublic VOXHashMapNode()\n\t\t\t{\n\t\t\t\telement = int.MaxValue;\n\t\t\t}\n\n\t\t\tpublic VOXHashMapNode(_Tx xx, _Tx yy, _Tx zz, VOXMaterial value)\n\t\t\t{\n\t\t\t\tx = xx;\n\t\t\t\ty = yy;\n\t\t\t\tz = zz;\n\t\t\t\telement = value;\n\t\t\t}\n\n\t\t\tpublic bool is_empty()\n\t\t\t{\n\t\t\t\treturn element == int.MaxValue;\n\t\t\t}\n\t\t}\n\n\t\tpublic class VOXHashMapNodeEnumerable<_Tx> : IEnumerable\n\t\t\twhere _Tx : struct\n\t\t{\n\t\t\tprivate VOXHashMapNode<_Tx>[] _array;\n\n\t\t\tpublic VOXHashMapNodeEnumerable(VOXHashMapNode<_Tx>[] array)\n\t\t\t{\n\t\t\t\t_array = array;\n\t\t\t}\n\n\t\t\tIEnumerator IEnumerable.GetEnumerator()\n\t\t\t{\n\t\t\t\treturn (IEnumerator)GetEnumerator();\n\t\t\t}\n\n\t\t\tpublic VOXHashMapNodeEnum<_Tx> GetEnumerator()\n\t\t\t{\n\t\t\t\treturn new VOXHashMapNodeEnum<_Tx>(_array);\n\t\t\t}\n\t\t}\n\n\t\tpublic class VOXHashMapNodeEnum<_Tx> : IEnumerator\n\t\t\twhere _Tx : struct\n\n\t\t{\n\t\t\tprivate int position = -1;\n\t\t\tprivate VOXHashMapNode<_Tx>[] _array;\n\n\t\t\tpublic VOXHashMapNodeEnum(VOXHashMapNode<_Tx>[] list)\n\t\t\t{\n\t\t\t\t_array = list;\n\t\t\t}\n\n\t\t\tpublic bool MoveNext()\n\t\t\t{\n\t\t\t\tvar length = _array.Length;\n\t\t\t\tfor (position++; position < length; position++)\n\t\t\t\t{\n\t\t\t\t\tif (_array[position] == null)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif (_array[position].is_empty())\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\treturn position < _array.Length;\n\t\t\t}\n\n\t\t\tpublic void Reset()\n\t\t\t{\n\t\t\t\tposition = -1;\n\t\t\t}\n\n\t\t\tobject IEnumerator.Current\n\t\t\t{\n\t\t\t\tget\n\t\t\t\t{\n\t\t\t\t\treturn Current;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpublic VOXHashMapNode<_Tx> Current\n\t\t\t{\n\t\t\t\tget\n\t\t\t\t{\n\t\t\t\t\treturn _array[position];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t[Serializable]\n\t\tpublic class VOXHashMap\n\t\t{\n\t\t\tprotected int _count;\n\t\t\tprotected int _allocSize;\n\t\t\tprotected Vector3Int _bound;\n\n\t\t\tprotected VOXHashMapNode<System.Byte>[] _data;\n\n\t\t\tpublic int Count { get { return _count; } }\n\t\t\tpublic Vector3Int bound { get { return _bound; } }\n\n\t\t\tpublic VOXHashMap(Vector3Int bound)\n\t\t\t{\n\t\t\t\t_count = 0;\n\t\t\t\t_bound = bound;\n\t\t\t\t_allocSize = 0;\n\t\t\t}\n\n\t\t\tpublic VOXHashMap(Vector3Int bound, int count)\n\t\t\t{\n\t\t\t\t_count = 0;\n\t\t\t\t_bound = bound;\n\t\t\t\t_allocSize = 0;\n\t\t\t\tthis.Create(count);\n\t\t\t}\n\n\t\t\tpublic VOXHashMap(int bound_x, int bound_y, int bound_z, int count)\n\t\t\t{\n\t\t\t\t_count = 0;\n\t\t\t\t_bound = new Vector3Int(bound_x, bound_y, bound_z);\n\t\t\t\t_allocSize = 0;\n\t\t\t\tthis.Create(count);\n\t\t\t}\n\n\t\t\tpublic void Create(int count)\n\t\t\t{\n\t\t\t\tint usage = 1;\n\t\t\t\twhile (usage < count) usage = usage << 1 | 1;\n\n\t\t\t\t_count = 0;\n\t\t\t\t_allocSize = usage;\n\t\t\t\t_data = new VOXHashMapNode<System.Byte>[usage + 1];\n\t\t\t}\n\n\t\t\tpublic bool Set(System.Byte x, System.Byte y, System.Byte z, VOXMaterial value, bool replace = true)\n\t\t\t{\n\t\t\t\tif (_allocSize == 0)\n\t\t\t\t\tthis.Create(0xFF);\n\n\t\t\t\tvar index = HashInt(x, y, z) & _allocSize;\n\t\t\t\tvar entry = _data[index];\n\n\t\t\t\twhile (entry != null)\n\t\t\t\t{\n\t\t\t\t\tif (entry.x == x && entry.y == y && entry.z == z)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (replace)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_data[index].element = value;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tindex = (index + 1) & _allocSize;\n\t\t\t\t\tentry = _data[index];\n\t\t\t\t}\n\n\t\t\t\tif (value != VOXMaterial.MaxValue)\n\t\t\t\t{\n\t\t\t\t\t_data[index] = new VOXHashMapNode<System.Byte>(x, y, z, value);\n\t\t\t\t\t_count++;\n\n\t\t\t\t\tif (_count >= _allocSize)\n\t\t\t\t\t\tthis.Grow();\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tpublic bool Get(System.Byte x, System.Byte y, System.Byte z, ref VOXMaterial instanceID)\n\t\t\t{\n\t\t\t\tif (_allocSize == 0)\n\t\t\t\t\treturn false;\n\n\t\t\t\tvar index = HashInt(x, y, z) & _allocSize;\n\t\t\t\tvar entry = _data[index];\n\n\t\t\t\twhile (entry != null)\n\t\t\t\t{\n\t\t\t\t\tif (entry.x == x && entry.y == y && entry.z == z)\n\t\t\t\t\t{\n\t\t\t\t\t\tinstanceID = entry.element;\n\t\t\t\t\t\treturn instanceID != VOXMaterial.MaxValue;\n\t\t\t\t\t}\n\n\t\t\t\t\tindex = (index + 1) & _allocSize;\n\t\t\t\t\tentry = _data[index];\n\t\t\t\t}\n\n\t\t\t\tinstanceID = VOXMaterial.MaxValue;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tpublic bool Exists(System.Byte x, System.Byte y, System.Byte z)\n\t\t\t{\n\t\t\t\tVOXMaterial instanceID = VOXMaterial.MaxValue;\n\t\t\t\treturn this.Get(x, y, z, ref instanceID);\n\t\t\t}\n\n\t\t\tpublic bool Empty()\n\t\t\t{\n\t\t\t\treturn _count == 0;\n\t\t\t}\n\n\t\t\tpublic VOXHashMapNodeEnumerable<System.Byte> GetEnumerator()\n\t\t\t{\n\t\t\t\tif (_data == null)\n\t\t\t\t\tthrow new System.ApplicationException(\"GetEnumerator: Empty data\");\n\n\t\t\t\treturn new VOXHashMapNodeEnumerable<System.Byte>(_data);\n\t\t\t}\n\n\t\t\tpublic static bool Save(string path, VOXHashMap map)\n\t\t\t{\n\t\t\t\tUnityEngine.Debug.Assert(map != null);\n\n\t\t\t\tvar stream = new FileStream(path, FileMode.Create, FileAccess.Write);\n\t\t\t\tvar serializer = new BinaryFormatter();\n\n\t\t\t\tserializer.Serialize(stream, map);\n\t\t\t\tstream.Close();\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tpublic static VOXHashMap Load(string path)\n\t\t\t{\n\t\t\t\tvar serializer = new BinaryFormatter();\n\t\t\t\tvar loadFile = new FileStream(path, FileMode.Open, FileAccess.Read);\n\t\t\t\treturn serializer.Deserialize(loadFile) as VOXHashMap;\n\t\t\t}\n\n\t\t\tprivate bool Grow(VOXHashMapNode<System.Byte> data)\n\t\t\t{\n\t\t\t\tvar index = HashInt(data.x, data.y, data.z) & _allocSize;\n\t\t\t\tvar entry = _data[index];\n\n\t\t\t\twhile (entry != null)\n\t\t\t\t{\n\t\t\t\t\tindex = (index + 1) & _allocSize;\n\t\t\t\t\tentry = _data[index];\n\t\t\t\t}\n\n\t\t\t\tif (data.element != VOXMaterial.MaxValue)\n\t\t\t\t{\n\t\t\t\t\t_data[index] = data;\n\t\t\t\t\t_count++;\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tprivate void Grow()\n\t\t\t{\n\t\t\t\tvar map = new VOXHashMap(_bound, _allocSize << 1 | 1);\n\n\t\t\t\tforeach (var it in GetEnumerator())\n\t\t\t\t\tmap.Grow(it);\n\n\t\t\t\t_count = map._count;\n\t\t\t\t_allocSize = map._allocSize;\n\t\t\t\t_data = map._data;\n\t\t\t}\n\n\t\t\tprivate static int _hash_int(int key)\n\t\t\t{\n\t\t\t\tkey = ~key + (key << 15);\n\t\t\t\tkey = key ^ (key >> 12);\n\t\t\t\tkey = key + (key << 2);\n\t\t\t\tkey = key ^ (key >> 4);\n\t\t\t\tkey = key * 2057;\n\t\t\t\tkey = key ^ (key >> 16);\n\t\t\t\treturn key;\n\t\t\t}\n\n\t\t\tpublic static int HashInt(int x, int y, int z)\n\t\t\t{\n\t\t\t\treturn _hash_int(x) ^ _hash_int(y) ^ _hash_int(z);\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "VOXFileLoader/Scripts/VOXModel.cs",
    "content": "﻿using UnityEngine;\n\nnamespace Cubizer\n{\n\tnamespace Model\n\t{\n\t\tpublic class VOXModel\n\t\t{\n\t\t\tprivate static Vector3[,] _positions = new Vector3[6, 4]\n\t\t\t{\n\t\t\t\t{ new Vector3(-1, -1, -1), new Vector3(-1, -1, +1), new Vector3(-1, +1, -1), new Vector3(-1, +1, +1) },\n\t\t\t\t{ new Vector3(+1, -1, -1), new Vector3(+1, -1, +1), new Vector3(+1, +1, -1), new Vector3(+1, +1, +1) },\n\t\t\t\t{ new Vector3(-1, +1, -1), new Vector3(-1, +1, +1), new Vector3(+1, +1, -1), new Vector3(+1, +1, +1) },\n\t\t\t\t{ new Vector3(-1, -1, -1), new Vector3(-1, -1, +1), new Vector3(+1, -1, -1), new Vector3(+1, -1, +1) },\n\t\t\t\t{ new Vector3(-1, -1, -1), new Vector3(-1, +1, -1), new Vector3(+1, -1, -1), new Vector3(+1, +1, -1) },\n\t\t\t\t{ new Vector3(-1, -1, +1), new Vector3(-1, +1, +1), new Vector3(+1, -1, +1), new Vector3(+1, +1, +1) }\n\t\t\t};\n\n\t\t\tprivate static Vector3[] _normals = new Vector3[6]\n\t\t\t{\n\t\t\t\tnew Vector3(-1, 0, 0),\n\t\t\t\tnew Vector3(+1, 0, 0),\n\t\t\t\tnew Vector3(0, +1, 0),\n\t\t\t\tnew Vector3(0, -1, 0),\n\t\t\t\tnew Vector3(0, 0, -1),\n\t\t\t\tnew Vector3(0, 0, +1)\n\t\t\t};\n\n\t\t\tprivate static Vector2[,] _uvs = new Vector2[6, 4]\n\t\t\t{\n\t\t\t\t{ new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 1), new Vector2(1, 1) },\n\t\t\t\t{ new Vector2(1, 0), new Vector2(0, 0), new Vector2(1, 1), new Vector2(0, 1) },\n\t\t\t\t{ new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 1), new Vector2(1, 0) },\n\t\t\t\t{ new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 0), new Vector2(1, 1) },\n\t\t\t\t{ new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 0), new Vector2(1, 1) },\n\t\t\t\t{ new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 0), new Vector2(0, 1) }\n\t\t\t};\n\n\t\t\tprivate static int[,] _indices = new int[6, 6]\n\t\t\t{\n\t\t\t\t{ 0, 3, 2, 0, 1, 3 },\n\t\t\t\t{ 0, 3, 1, 0, 2, 3 },\n\t\t\t\t{ 0, 3, 2, 0, 1, 3 },\n\t\t\t\t{ 0, 3, 1, 0, 2, 3 },\n\t\t\t\t{ 0, 3, 2, 0, 1, 3 },\n\t\t\t\t{ 0, 3, 1, 0, 2, 3 }\n\t\t\t};\n\n\t\t\tpublic VOXCruncher[] voxels;\n\n\t\t\tpublic VOXModel(VOXCruncher[] array)\n\t\t\t{\n\t\t\t\tvoxels = array;\n\t\t\t}\n\n\t\t\tpublic static void CreateCubeMesh16x16(ref Vector3[] vertices, ref Vector3[] normals, ref Vector2[] uv, ref int[] triangles, ref int index, VOXVisiableFaces faces, Vector3 translate, Vector3 scale, uint palette)\n\t\t\t{\n\t\t\t\tbool[] visiable = new bool[] { faces.left, faces.right, faces.top, faces.bottom, faces.front, faces.back };\n\n\t\t\t\tfloat s = 1.0f / 16.0f;\n\t\t\t\tfloat a = 0 + 1.0f / 32.0f;\n\t\t\t\tfloat b = s - 1.0f / 32.0f;\n\n\t\t\t\tfor (int i = 0; i < 6; i++)\n\t\t\t\t{\n\t\t\t\t\tif (!visiable[i])\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\tfor (int n = index * 4, k = 0; k < 4; k++, n++)\n\t\t\t\t\t{\n\t\t\t\t\t\tVector3 v = _positions[i, k] * 0.5f;\n\t\t\t\t\t\tv.x *= scale.x;\n\t\t\t\t\t\tv.y *= scale.y;\n\t\t\t\t\t\tv.z *= scale.z;\n\t\t\t\t\t\tv += translate;\n\n\t\t\t\t\t\tfloat du = (palette % 16) * s;\n\t\t\t\t\t\tfloat dv = (palette / 16) * s;\n\n\t\t\t\t\t\tVector2 coord;\n\t\t\t\t\t\tcoord.x = du + (_uvs[i, k].x > 0 ? b : a);\n\t\t\t\t\t\tcoord.y = dv + (_uvs[i, k].y > 0 ? b : a);\n\n\t\t\t\t\t\tvertices[n] = v;\n\t\t\t\t\t\tnormals[n] = _normals[i];\n\t\t\t\t\t\tuv[n] = coord;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (int j = index * 6, k = 0; k < 6; k++, j++)\n\t\t\t\t\t\ttriangles[j] = index * 4 + _indices[i, k];\n\n\t\t\t\t\tindex++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpublic static void CreateCubeMesh16x16(VOXCruncher it, ref Vector3[] vertices, ref Vector3[] normals, ref Vector2[] uv, ref int[] triangles, ref int index, float scaling)\n\t\t\t{\n\t\t\t\tVector3 pos;\n\t\t\t\tpos.x = (it.begin.x + it.end.x + 1) * 0.5f * scaling;\n\t\t\t\tpos.y = (it.begin.y + it.end.y + 1) * 0.5f * scaling;\n\t\t\t\tpos.z = (it.begin.z + it.end.z + 1) * 0.5f * scaling;\n\n\t\t\t\tVector3 scale;\n\t\t\t\tscale.x = (it.end.x + 1 - it.begin.x) * scaling;\n\t\t\t\tscale.y = (it.end.y + 1 - it.begin.y) * scaling;\n\t\t\t\tscale.z = (it.end.z + 1 - it.begin.z) * scaling;\n\n\t\t\t\tVOXModel.CreateCubeMesh16x16(ref vertices, ref normals, ref uv, ref triangles, ref index, it.faces, pos, scale, (uint)it.material);\n\t\t\t}\n\t\t}\n\t}\n}"
  }
]