├── Voxels.Test ├── 1x2x3.vox ├── 2x2x2.vox ├── 3x3x1.vox ├── 3x3x3.vox ├── 8x8x8.vox ├── Nerds.qb ├── cars.vox ├── packages.config ├── Properties │ └── AssemblyInfo.cs ├── TestQubicle.cs ├── TestColor.cs ├── TestMagicaVoxel.cs ├── TestAmbientOcclusion.cs └── Voxels.Test.csproj ├── Voxels.Setup ├── Voxels.ico ├── Voxels.Setup.wixproj ├── Bundle.wxs └── License.rtf ├── Voxels.Website ├── cars.gif ├── mmmm.png ├── 2x2x2.png ├── 3x3x3.png ├── 8x8x8.png ├── T-Rex.gif ├── wizard.png ├── 2kTerrain.png ├── Arlorean.png ├── QbThumbnails.PNG ├── QubicleNerds.png ├── Voxels-Itch.png ├── alien_egg2.png ├── ZacharySoares.png ├── QubicleThumbnails.png ├── UnityFloorShadows.PNG ├── WindowsExplorer.png ├── 2x2x2.svg ├── 3x3x3.svg ├── 8x8x8.svg └── wizard.svg ├── Voxels.CommandLine ├── 1x1x1.vox ├── 1x2x3.vox ├── 2x2x2.vox ├── 3x3x3.vox ├── 8x8x8.vox ├── Axes.vox ├── Nerds.qb ├── Nerds.qbcl ├── wizard.vox ├── App.config ├── packages.config ├── Animation.cs ├── Properties │ └── AssemblyInfo.cs ├── ImageToVoxel.cs ├── Slicer.cs ├── Voxels.CommandLine.csproj └── Program.cs ├── Voxels.SkiaSharp ├── SigningKey.snk ├── packages.config ├── Voxels.SkiaSharp.csproj.user ├── NativeLibrary.cs ├── Properties │ └── AssemblyInfo.cs ├── Voxels.SkiaSharp.csproj └── Renderer.cs ├── Voxels.ShellExtensions ├── SigningKey.snk ├── packages.config ├── ThumbnailHandlerQbcl.cs ├── ThumbnailHandlerQb.cs ├── ThumbnailHandlerVox.cs ├── Properties │ └── AssemblyInfo.cs └── Voxels.ShellExtensions.csproj ├── .gitmodules ├── Voxels.Installer ├── SwapGuids.ps1 ├── Voxels.Installer.wixproj └── Product.wxs ├── LICENSE ├── .gitignore ├── README.md └── Voxels.sln /Voxels.Test/1x2x3.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Test/1x2x3.vox -------------------------------------------------------------------------------- /Voxels.Test/2x2x2.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Test/2x2x2.vox -------------------------------------------------------------------------------- /Voxels.Test/3x3x1.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Test/3x3x1.vox -------------------------------------------------------------------------------- /Voxels.Test/3x3x3.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Test/3x3x3.vox -------------------------------------------------------------------------------- /Voxels.Test/8x8x8.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Test/8x8x8.vox -------------------------------------------------------------------------------- /Voxels.Test/Nerds.qb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Test/Nerds.qb -------------------------------------------------------------------------------- /Voxels.Test/cars.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Test/cars.vox -------------------------------------------------------------------------------- /Voxels.Setup/Voxels.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Setup/Voxels.ico -------------------------------------------------------------------------------- /Voxels.Website/cars.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/cars.gif -------------------------------------------------------------------------------- /Voxels.Website/mmmm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/mmmm.png -------------------------------------------------------------------------------- /Voxels.Website/2x2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/2x2x2.png -------------------------------------------------------------------------------- /Voxels.Website/3x3x3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/3x3x3.png -------------------------------------------------------------------------------- /Voxels.Website/8x8x8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/8x8x8.png -------------------------------------------------------------------------------- /Voxels.Website/T-Rex.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/T-Rex.gif -------------------------------------------------------------------------------- /Voxels.Website/wizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/wizard.png -------------------------------------------------------------------------------- /Voxels.CommandLine/1x1x1.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.CommandLine/1x1x1.vox -------------------------------------------------------------------------------- /Voxels.CommandLine/1x2x3.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.CommandLine/1x2x3.vox -------------------------------------------------------------------------------- /Voxels.CommandLine/2x2x2.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.CommandLine/2x2x2.vox -------------------------------------------------------------------------------- /Voxels.CommandLine/3x3x3.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.CommandLine/3x3x3.vox -------------------------------------------------------------------------------- /Voxels.CommandLine/8x8x8.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.CommandLine/8x8x8.vox -------------------------------------------------------------------------------- /Voxels.CommandLine/Axes.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.CommandLine/Axes.vox -------------------------------------------------------------------------------- /Voxels.CommandLine/Nerds.qb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.CommandLine/Nerds.qb -------------------------------------------------------------------------------- /Voxels.Website/2kTerrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/2kTerrain.png -------------------------------------------------------------------------------- /Voxels.Website/Arlorean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/Arlorean.png -------------------------------------------------------------------------------- /Voxels.CommandLine/Nerds.qbcl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.CommandLine/Nerds.qbcl -------------------------------------------------------------------------------- /Voxels.CommandLine/wizard.vox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.CommandLine/wizard.vox -------------------------------------------------------------------------------- /Voxels.SkiaSharp/SigningKey.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.SkiaSharp/SigningKey.snk -------------------------------------------------------------------------------- /Voxels.Website/QbThumbnails.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/QbThumbnails.PNG -------------------------------------------------------------------------------- /Voxels.Website/QubicleNerds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/QubicleNerds.png -------------------------------------------------------------------------------- /Voxels.Website/Voxels-Itch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/Voxels-Itch.png -------------------------------------------------------------------------------- /Voxels.Website/alien_egg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/alien_egg2.png -------------------------------------------------------------------------------- /Voxels.Website/ZacharySoares.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/ZacharySoares.png -------------------------------------------------------------------------------- /Voxels.Website/QubicleThumbnails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/QubicleThumbnails.png -------------------------------------------------------------------------------- /Voxels.Website/UnityFloorShadows.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/UnityFloorShadows.PNG -------------------------------------------------------------------------------- /Voxels.Website/WindowsExplorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.Website/WindowsExplorer.png -------------------------------------------------------------------------------- /Voxels.ShellExtensions/SigningKey.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arlorean/Voxels/HEAD/Voxels.ShellExtensions/SigningKey.snk -------------------------------------------------------------------------------- /Voxels.Test/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Voxels.SkiaSharp/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Voxels.CommandLine/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Voxels.ShellExtensions/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Voxels.Core"] 2 | path = Voxels.Core 3 | url = https://github.com/Arlorean/Voxels.Core.git 4 | update = merge 5 | 6 | [submodule "NGif.SkiaSharp"] 7 | path = NGif.SkiaSharp 8 | url = https://github.com/Arlorean/NGif.SkiaSharp 9 | update = merge 10 | -------------------------------------------------------------------------------- /Voxels.SkiaSharp/Voxels.SkiaSharp.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ProjectFiles 5 | 6 | -------------------------------------------------------------------------------- /Voxels.CommandLine/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Voxels.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("UnitTestProject1")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("Arlorean")] 9 | [assembly: AssemblyProduct("UnitTestProject1")] 10 | [assembly: AssemblyCopyright("Copyright © Adam Davidson 2023")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | 14 | [assembly: ComVisible(false)] 15 | 16 | [assembly: Guid("44fd680f-9699-49d0-926c-e392b8cf521c")] 17 | 18 | // [assembly: AssemblyVersion("1.0.*")] 19 | [assembly: AssemblyVersion("1.7.0.0")] 20 | [assembly: AssemblyFileVersion("1.7.0.0")] 21 | -------------------------------------------------------------------------------- /Voxels.SkiaSharp/NativeLibrary.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace Voxels.SkiaSharp { 6 | public static class NativeLibrary { 7 | 8 | [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] 9 | extern static IntPtr LoadLibrary(string dllPath); 10 | 11 | public static void Initialize() { 12 | var dir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); 13 | var arch = IntPtr.Size == 8 ? "x64" : "x86"; 14 | var path = Path.Combine(dir, arch, "libSkiaSharp.dll"); 15 | if (LoadLibrary(path) == IntPtr.Zero) { 16 | Console.Error.WriteLine("Cannot load library: " + path); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Voxels.Installer/SwapGuids.ps1: -------------------------------------------------------------------------------- 1 | ## GuidSwap.ps1 2 | ## 3 | ## Reads a file, finds any GUIDs in the file, and swaps them for a NewGUID 4 | ## 5 | 6 | $filename = "Product.wxs" 7 | $outputFilename = "Product_upgraded.wxs" 8 | 9 | $text = [string]::join([environment]::newline, (get-content -path $filename)) 10 | 11 | $sbNew = new-object system.text.stringBuilder 12 | 13 | $pattern = "[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12}" 14 | 15 | $lastStart = 0 16 | $null = ([regex]::matches($text, $pattern) | %{ 17 | $sbNew.Append($text.Substring($lastStart, $_.Index - $lastStart)) 18 | $guid = [system.guid]::newguid() 19 | $sbNew.Append($guid) 20 | $lastStart = $_.Index + $_.Length 21 | }) 22 | $null = $sbNew.Append($text.Substring($lastStart)) 23 | 24 | $sbNew.ToString() | out-file -encoding ASCII $outputFilename 25 | 26 | Write-Output "Done" 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Adam Davidson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Voxels.ShellExtensions/ThumbnailHandlerQbcl.cs: -------------------------------------------------------------------------------- 1 | using SharpShell.Attributes; 2 | using SharpShell.SharpThumbnailHandler; 3 | using System.Drawing; 4 | using System.Drawing.Imaging; 5 | using System.Runtime.InteropServices; 6 | using Voxels.SkiaSharp; 7 | 8 | namespace Voxels.ShellExtensions { 9 | [ComVisible(true)] 10 | [COMServerAssociation(AssociationType.FileExtension, ".qbcl")] 11 | public class ThumbnailHandlerQbcl : SharpThumbnailHandler { 12 | protected override Bitmap GetThumbnailImage(uint width) { 13 | var thumb = QbclFile.Read(SelectedItemStream); 14 | var format = PixelFormat.Format32bppArgb; 15 | var bitmap = new Bitmap(thumb.Width, thumb.Height, format); 16 | var bitmapData = bitmap.LockBits(new Rectangle(0, 0, thumb.Width, thumb.Height), ImageLockMode.WriteOnly, format); 17 | Marshal.Copy(thumb.Bytes, 0, bitmapData.Scan0, thumb.Bytes.Length); 18 | bitmap.UnlockBits(bitmapData); 19 | return bitmap; 20 | } 21 | 22 | static ThumbnailHandlerQbcl() { 23 | NativeLibrary.Initialize(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | /.vs 6 | /Voxels/obj 7 | /Voxels.CommandLine/obj 8 | *.cache 9 | *.csproj.user 10 | /packages 11 | /packages 12 | /Voxels/bin/Debug 13 | /Voxels.CommandLine/bin/Debug 14 | /Voxels.Installer/bin/Debug 15 | /Voxels.Installer/obj/Debug 16 | /Voxels.ShellExtensions/bin/Debug 17 | /Voxels.ShellExtensions/obj/Debug 18 | /Voxels.SkiaSharp/bin/Debug 19 | /Voxels.Test/bin/Debug 20 | /Voxels.Test/obj/Debug 21 | /Voxels/bin/Release 22 | /Voxels.CommandLine/bin/Release 23 | /Voxels.CommandLine/bin/Release/x64 24 | /Voxels.CommandLine/bin/Release/x86 25 | /Voxels.Installer/bin/Release 26 | /Voxels.Installer/obj/Release 27 | /Voxels.ShellExtensions/bin/Release 28 | /Voxels.ShellExtensions/obj/Release 29 | /Voxels.SkiaSharp/bin/Release 30 | /Voxels.SkiaSharp/obj 31 | /Voxels.Test/bin/Release 32 | /Voxels.Test/obj/Release 33 | /Voxels.CommandLine/bin.old 34 | /Voxels.Setup/bin/Release 35 | /Voxels.Setup/obj/Release 36 | *.user 37 | /Voxels.Setup/Voxels.Setup.wixproj.user 38 | -------------------------------------------------------------------------------- /Voxels.Test/TestQubicle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using System.IO; 4 | 5 | namespace Voxels.Test { 6 | [TestFixture] 7 | public class TestQubicle { 8 | [OneTimeSetUp] 9 | public void SetUp() { 10 | Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); 11 | } 12 | 13 | /// 14 | /// The Nerds.qb is the test file that comes with the Qubicle demo. 15 | /// 16 | [Test] 17 | public void TestNerds() { 18 | using (var stream = File.OpenRead("Nerds.qb")) { 19 | var qubicle = new QbFile(); 20 | qubicle.Read(stream); 21 | 22 | Assert.AreEqual(257, qubicle.Version); 23 | 24 | var voxelData = qubicle.Flatten(); 25 | 26 | Assert.AreEqual(new XYZ(48,45,44), voxelData.Size); 27 | 28 | Assert.AreEqual(15965, voxelData.Count); 29 | 30 | // Left size speaker foot 31 | Assert.AreEqual(new Color(89, 93, 96), voxelData.ColorOf(XYZ.Zero)); 32 | 33 | // Middle nerd's hair 34 | Assert.AreEqual(new Color(83, 33, 21), voxelData.ColorOf(new XYZ(24, 40, 43))); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Voxels.Website/2x2x2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Voxels.ShellExtensions/ThumbnailHandlerQb.cs: -------------------------------------------------------------------------------- 1 | using SharpShell.Attributes; 2 | using SharpShell.SharpThumbnailHandler; 3 | using System.Drawing; 4 | using System.Drawing.Imaging; 5 | using System.Runtime.InteropServices; 6 | using Voxels.SkiaSharp; 7 | 8 | namespace Voxels.ShellExtensions { 9 | [ComVisible(true)] 10 | [COMServerAssociation(AssociationType.FileExtension, ".qb")] 11 | public class ThumbnailHandlerQb : SharpThumbnailHandler { 12 | protected override Bitmap GetThumbnailImage(uint width) { 13 | var size = (int)width; 14 | var voxelData = QbFile.ReadAndFlatten(SelectedItemStream); 15 | if (voxelData == null) { 16 | return null; 17 | } 18 | 19 | var renderSettings = new RenderSettings() { Size = size }; 20 | var bitmapBytes = Renderer.RenderBitmap(voxelData, renderSettings); 21 | 22 | // Convert Skia bytes to GDI Bitmap 23 | var format = PixelFormat.Format32bppArgb; 24 | var bitmap = new Bitmap(size, size, format); 25 | var bitmapData = bitmap.LockBits(new Rectangle(0,0,size,size), ImageLockMode.WriteOnly, format); 26 | Marshal.Copy(bitmapBytes, 0, bitmapData.Scan0, bitmapBytes.Length); 27 | bitmap.UnlockBits(bitmapData); 28 | return bitmap; 29 | } 30 | 31 | static ThumbnailHandlerQb() { 32 | NativeLibrary.Initialize(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Voxels.ShellExtensions/ThumbnailHandlerVox.cs: -------------------------------------------------------------------------------- 1 | using SharpShell.Attributes; 2 | using SharpShell.SharpThumbnailHandler; 3 | using System.Drawing; 4 | using System.Drawing.Imaging; 5 | using System.Runtime.InteropServices; 6 | using Voxels.SkiaSharp; 7 | 8 | namespace Voxels.ShellExtensions { 9 | [ComVisible(true)] 10 | [COMServerAssociation(AssociationType.FileExtension, ".vox")] 11 | public class ThumbnailHandlerVox : SharpThumbnailHandler { 12 | protected override Bitmap GetThumbnailImage(uint width) { 13 | var size = (int)width; 14 | var voxelData = VoxFile.Read(SelectedItemStream); 15 | if (voxelData == null) { 16 | return null; 17 | } 18 | 19 | var renderSettings = new RenderSettings() { Size = size }; 20 | var bitmapBytes = Renderer.RenderBitmap(voxelData, renderSettings); 21 | 22 | // Convert Skia bytes to GDI Bitmap 23 | var format = PixelFormat.Format32bppArgb; 24 | var bitmap = new Bitmap(size, size, format); 25 | var bitmapData = bitmap.LockBits(new Rectangle(0,0,size,size), ImageLockMode.WriteOnly, format); 26 | Marshal.Copy(bitmapBytes, 0, bitmapData.Scan0, bitmapBytes.Length); 27 | bitmap.UnlockBits(bitmapData); 28 | return bitmap; 29 | } 30 | 31 | static ThumbnailHandlerVox() { 32 | NativeLibrary.Initialize(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Voxels.CommandLine/Animation.cs: -------------------------------------------------------------------------------- 1 | using NGif.Components; 2 | using SkiaSharp; 3 | using System; 4 | using System.IO; 5 | using Voxels.SkiaSharp; 6 | 7 | namespace Voxels.CommandLine { 8 | internal static class Animation { 9 | public static byte[] RenderGif(RenderSettings renderSettings, int frames, float duration, int cameraOrbits, BoundsXYZ worldBounds, Func flattenFrame) { 10 | var delay = (int)(duration / frames * 1000); 11 | 12 | var encoder = new AnimatedGifEncoder(); 13 | var memory = new MemoryStream(); 14 | encoder.Start(memory); 15 | encoder.SetDelay(delay); 16 | //-1:no repeat,0:always repeat 17 | encoder.SetRepeat(0); 18 | encoder.SetTransparent(SKColors.Black); 19 | 20 | //var worldBounds = magicaVoxel.GetWorldAABB(0, frames - 1); 21 | 22 | var startAngle = renderSettings.Yaw; 23 | var stepAngle = (360*cameraOrbits) / frames; 24 | for (var i=0; i < frames; i++) { 25 | renderSettings.Yaw = startAngle + stepAngle * i; 26 | 27 | //var voxelData = magicaVoxel.Flatten(worldBounds, i); 28 | var voxelData = flattenFrame(i); 29 | var bytes = Renderer.RenderPng(voxelData, renderSettings); 30 | var image = SKImage.FromBitmap(SKBitmap.Decode(bytes)); 31 | encoder.AddFrame(image); 32 | } 33 | renderSettings.Yaw = startAngle; 34 | 35 | encoder.Finish(); 36 | 37 | return memory.ToArray(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Voxels.SkiaSharp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Voxels.SkiaSharp")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Arlorean")] 12 | [assembly: AssemblyProduct("Voxels.SkiaSharp")] 13 | [assembly: AssemblyCopyright("Copyright © Adam Davidson 2023")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5275868a-6c22-469c-8c12-c039898e305c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.7.0.0")] 36 | [assembly: AssemblyFileVersion("1.7.0.0")] 37 | -------------------------------------------------------------------------------- /Voxels.CommandLine/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("VoxelsCommandLine")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Arlorean")] 12 | [assembly: AssemblyProduct("VoxelsCommandLine")] 13 | [assembly: AssemblyCopyright("Copyright © Adam Davidson 2023")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1e4d9af1-41e1-4c81-9d9a-ef22f101e69f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.7.0.0")] 36 | [assembly: AssemblyFileVersion("1.7.0.0")] 37 | -------------------------------------------------------------------------------- /Voxels.ShellExtensions/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Voxels.ShellExtensions")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Arlorean")] 12 | [assembly: AssemblyProduct("Voxels.ShellExtensions")] 13 | [assembly: AssemblyCopyright("Copyright © Adam Davidson 2023")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f8a32354-da2b-406c-aebe-dcefd85fd033")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.7.0.0")] 36 | [assembly: AssemblyFileVersion("1.7.0.0")] 37 | -------------------------------------------------------------------------------- /Voxels.Test/TestColor.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Voxels.Test { 9 | [TestFixture] 10 | 11 | public class TestColor { 12 | [Test] 13 | public void TestHSV() { 14 | float h, s, v; 15 | 16 | Color.Black.ToHSV(out h, out s, out v); 17 | Assert.AreEqual(0, h); 18 | Assert.AreEqual(0, s); 19 | Assert.AreEqual(0, v); 20 | Assert.AreEqual(Color.Black, Color.FromHSV(h, s, v)); 21 | 22 | Color.White.ToHSV(out h, out s, out v); 23 | Assert.AreEqual(0, h); 24 | Assert.AreEqual(0, s); 25 | Assert.AreEqual(1, v); 26 | Assert.AreEqual(Color.White, Color.FromHSV(h, s, v)); 27 | 28 | Color.Red.ToHSV(out h, out s, out v); 29 | Assert.AreEqual(0, h); 30 | Assert.AreEqual(1, s); 31 | Assert.AreEqual(1, v); 32 | Assert.AreEqual(Color.Red, Color.FromHSV(h, s, v)); 33 | 34 | Color.Green.ToHSV(out h, out s, out v); 35 | Assert.AreEqual(120, h); 36 | Assert.AreEqual(1, s); 37 | Assert.AreEqual(1, v); 38 | Assert.AreEqual(Color.Green, Color.FromHSV(h, s, v)); 39 | 40 | Color.Blue.ToHSV(out h, out s, out v); 41 | Assert.AreEqual(240, h); 42 | Assert.AreEqual(1, s); 43 | Assert.AreEqual(1, v); 44 | Assert.AreEqual(Color.Blue, Color.FromHSV(h, s, v)); 45 | 46 | Color.Tan.ToHSV(out h, out s, out v); 47 | Assert.AreEqual(34, h); 48 | Assert.AreEqual(0.3333333, s, 1e-6); 49 | Assert.AreEqual(0.8235294, v, 1e-6); 50 | Assert.AreEqual(Color.Tan, Color.FromHSV(h, s, v)); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Voxels.CommandLine/ImageToVoxel.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Voxels.CommandLine { 10 | internal static class ImageToVoxel { 11 | public static VoxelData Import(string path, Color[] palette) { 12 | using (var bitmap = SKBitmap.Decode(path)) { 13 | if (bitmap == null) return null; 14 | 15 | var size = new XYZ(bitmap.Width, 1, bitmap.Height); 16 | var voxelData = new VoxelDataBytes(size, palette); 17 | 18 | for (var x = 0; x < bitmap.Width; x++) { 19 | for (var y = 0; y < bitmap.Height; y++) { 20 | var p = bitmap.GetPixel(x, y); 21 | if (p.Alpha != 0) { 22 | var c = new Color(p.Red, p.Green, p.Blue, p.Alpha); 23 | var i = Array.IndexOf(palette, c); 24 | voxelData[new XYZ(x, 0, bitmap.Height-y-1)] = new Voxel((uint)i); 25 | } 26 | } 27 | } 28 | 29 | return voxelData; 30 | } 31 | } 32 | 33 | public static void ExtractColors(string path, HashSet colorsUsed) { 34 | using (var bitmap = SKBitmap.Decode(path)) { 35 | if (bitmap == null) return; 36 | 37 | for (var x = 0; x < bitmap.Width; x++) { 38 | for (var y = 0; y < bitmap.Height; y++) { 39 | var p = bitmap.GetPixel(x, y); 40 | if (p.Alpha != 0) { 41 | var c = new Color(p.Red, p.Green, p.Blue, p.Alpha); 42 | colorsUsed.Add(c); 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Voxels.CommandLine/Slicer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using SkiaSharp; 8 | 9 | namespace Voxels.CommandLine { 10 | public class Slicer { 11 | /// 12 | /// Render each slice of the voxel data into a long single PNG file for use as a 3D texture in Unity. 13 | /// Unity 3D textures are sliced along the Unity Z axis, which is the Voxel Y axis (front to back). 14 | /// 15 | /// 16 | /// A byte array of the voxel slices in PNG format. 17 | public static byte[] RenderTexture3D(VoxelData voxels, int columns, int rows) { 18 | using (var bitmap = new SKBitmap(voxels.Size.X*columns, voxels.Size.Z*rows)) { 19 | if (bitmap == null) return null; 20 | 21 | for (var y = 0; y < voxels.Size.Y; y++) { 22 | var dx = (y%columns) * voxels.Size.X; 23 | var dz = (y/columns) * voxels.Size.Z; 24 | for (var x = 0; x < voxels.Size.X; x++) { 25 | for (var z = 0; z < voxels.Size.Z; z++) { 26 | var c = voxels.ColorOf(new XYZ(x, y, (voxels.Size.Z-z-1))); 27 | bitmap.SetPixel(x + dx, z + dz, new SKColor(c.R, c.G, c.B, c.A)); 28 | } 29 | } 30 | } 31 | 32 | using (var image = SKImage.FromBitmap(bitmap)) { 33 | using (var data = image.Encode()) { 34 | var ms = new MemoryStream(); 35 | data.SaveTo(ms); 36 | return ms.ToArray(); 37 | } 38 | } 39 | } 40 | } 41 | 42 | /// 43 | /// Unity does not like really wide textures so we have to create the most square texture we can. 44 | /// 45 | /// 46 | /// 47 | /// 48 | public static void MakeSquare(XYZ size, out int rows, out int columns) { 49 | rows = 1; 50 | columns = size.Y; 51 | 52 | while (columns % 2 == 0) { 53 | columns /= 2; 54 | rows *= 2; 55 | 56 | // Closest we can get to a square 57 | if (columns <= rows) { 58 | return; 59 | } 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Voxels.Test/TestMagicaVoxel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using System.IO; 4 | 5 | namespace Voxels.Test { 6 | [TestFixture] 7 | public class TestMagicaVoxel { 8 | [OneTimeSetUp] 9 | public void SetUp() { 10 | Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); 11 | } 12 | 13 | [Test] 14 | public void Test1x2x3() { 15 | using (var stream = File.OpenRead("1x2x3.vox")) { 16 | var magicaVoxel = new MagicaVoxel(); 17 | magicaVoxel.Read(stream); 18 | 19 | var voxelData = magicaVoxel.Flatten(); 20 | Assert.AreEqual(6, voxelData.Count); 21 | Assert.AreEqual(1, voxelData.Size.X); 22 | Assert.AreEqual(2, voxelData.Size.Y); 23 | Assert.AreEqual(3, voxelData.Size.Z); 24 | } 25 | } 26 | 27 | [Test] 28 | public void Test3x3x3() { 29 | using (var stream = File.OpenRead("3x3x3.vox")) { 30 | var magicaVoxel = new MagicaVoxel(); 31 | magicaVoxel.Read(stream); 32 | 33 | var voxelData = magicaVoxel.Flatten(); 34 | Assert.AreEqual(20, voxelData.Count); 35 | } 36 | } 37 | 38 | [Test] 39 | public void Test8x8x8() { 40 | using (var stream = File.OpenRead("8x8x8.vox")) { 41 | var magicaVoxel = new MagicaVoxel(); 42 | magicaVoxel.Read(stream); 43 | 44 | var voxelData = magicaVoxel.Flatten(); 45 | Assert.AreEqual(80, voxelData.Count); 46 | } 47 | } 48 | 49 | /// 50 | /// The cars.vox is the MagicaVoxel example of using multiple voxel models 51 | /// with rotations and translations to place them in a larger world. 52 | /// 53 | [Test] 54 | public void TestCars() { 55 | using (var stream = File.OpenRead("cars.vox")) { 56 | var magicaVoxel = new MagicaVoxel(); 57 | magicaVoxel.Read(stream); 58 | 59 | Assert.AreEqual(200, magicaVoxel.Version); 60 | Assert.AreEqual(2, magicaVoxel.Models.Count); 61 | 62 | Assert.AreEqual(3132, magicaVoxel.Models[0].Count); 63 | Assert.AreEqual(3235, magicaVoxel.Models[1].Count); 64 | 65 | Assert.AreEqual(32, magicaVoxel.Layers.Count); // Not sure how this got created since the default layer count is 16 66 | 67 | Assert.AreEqual(3132 + 3235, magicaVoxel.Flatten().Count); 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Voxels.Installer/Voxels.Installer.wixproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 3.10 7 | 4ce76915-e1ea-46af-9c22-737f7b9b0c27 8 | 2.0 9 | Voxels.Installer 10 | Package 11 | Voxels.Installer 12 | 13 | 14 | bin\$(Configuration)\ 15 | obj\$(Configuration)\ 16 | Debug 17 | 18 | 19 | bin\$(Configuration)\ 20 | obj\$(Configuration)\ 21 | 22 | 23 | 24 | 25 | 26 | 27 | Voxels.CommandLine 28 | {1e4d9af1-41e1-4c81-9d9a-ef22f101e69f} 29 | True 30 | True 31 | Binaries;Content;Satellites 32 | INSTALLFOLDER 33 | 34 | 35 | Voxels.ShellExtensions 36 | {f8a32354-da2b-406c-aebe-dcefd85fd033} 37 | True 38 | True 39 | Binaries;Content;Satellites 40 | INSTALLFOLDER 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 56 | -------------------------------------------------------------------------------- /Voxels.Setup/Voxels.Setup.wixproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 3.10 7 | 74833944-18a2-406d-ad28-63b36eb8795d 8 | 2.0 9 | Voxels.Setup 10 | Bundle 11 | 12 | 13 | bin\$(Configuration)\ 14 | obj\$(Configuration)\ 15 | Debug 16 | 17 | 18 | bin\$(Configuration)\ 19 | obj\$(Configuration)\ 20 | 21 | 22 | 23 | 24 | 25 | 26 | $(WixExtDir)\WixUIExtension.dll 27 | WixUIExtension 28 | 29 | 30 | $(WixExtDir)\WixUtilExtension.dll 31 | WixUtilExtension 32 | 33 | 34 | $(WixExtDir)\WixBalExtension.dll 35 | WixBalExtension 36 | 37 | 38 | 39 | 40 | Voxels.Installer 41 | {4ce76915-e1ea-46af-9c22-737f7b9b0c27} 42 | True 43 | True 44 | Binaries;Content;Satellites 45 | INSTALLFOLDER 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 65 | -------------------------------------------------------------------------------- /Voxels.Test/TestAmbientOcclusion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using System.IO; 4 | 5 | namespace Voxels.Test { 6 | [TestFixture] 7 | public class TestAmbientOcclusion { 8 | [OneTimeSetUp] 9 | public void SetUp() { 10 | Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); 11 | } 12 | 13 | [Test] 14 | public void TestCase0() { 15 | using (var stream = File.OpenRead("3x3x3.vox")) { 16 | var magicaVoxel = new MagicaVoxel(); 17 | magicaVoxel.Read(stream); 18 | 19 | var voxelData = magicaVoxel.Flatten(); 20 | Assert.AreEqual(0, AmbientOcclusion.CalculateAO(voxelData, new XYZ(1, 1, 1), XYZ.OneY, XYZ.OneX, XYZ.OneZ)); 21 | } 22 | } 23 | 24 | [Test] 25 | public void TestCase1() { 26 | using (var stream = File.OpenRead("3x3x3.vox")) { 27 | var magicaVoxel = new MagicaVoxel(); 28 | magicaVoxel.Read(stream); 29 | 30 | var voxelData = magicaVoxel.Flatten(); 31 | Assert.AreEqual(1, AmbientOcclusion.CalculateAO(voxelData, new XYZ(1, 0, 1), XYZ.OneY, XYZ.OneX, XYZ.OneZ)); 32 | Assert.AreEqual(1, AmbientOcclusion.CalculateAO(voxelData, new XYZ(0, 1, 1), XYZ.OneY, XYZ.OneX, XYZ.OneZ)); 33 | } 34 | } 35 | [Test] 36 | public void TestCase2() { 37 | using (var stream = File.OpenRead("3x3x3.vox")) { 38 | var magicaVoxel = new MagicaVoxel(); 39 | magicaVoxel.Read(stream); 40 | 41 | var voxelData = magicaVoxel.Flatten(); 42 | Assert.AreEqual(2, AmbientOcclusion.CalculateAO(voxelData, new XYZ(1, 1, 0), XYZ.OneY, XYZ.OneX, XYZ.OneZ)); 43 | } 44 | } 45 | [Test] 46 | public void TestCase3() { 47 | using (var stream = File.OpenRead("3x3x3.vox")) { 48 | var magicaVoxel = new MagicaVoxel(); 49 | magicaVoxel.Read(stream); 50 | 51 | var voxelData = magicaVoxel.Flatten(); 52 | Assert.AreEqual(3, AmbientOcclusion.CalculateAO(voxelData, new XYZ(2, 2, 2), XYZ.OneY, XYZ.OneX, XYZ.OneZ)); 53 | } 54 | } 55 | [Test] 56 | public void TestCaseComplex() { 57 | using (var stream = File.OpenRead("2x2x2.vox")) { 58 | var magicaVoxel = new MagicaVoxel(); 59 | magicaVoxel.Read(stream); 60 | 61 | var voxelData = magicaVoxel.Flatten(); 62 | Assert.AreEqual(0, AmbientOcclusion.CalculateAO(voxelData, new XYZ(0, 0, 0), XYZ.OneY, XYZ.OneX, XYZ.OneZ)); 63 | Assert.AreEqual(0, AmbientOcclusion.CalculateAO(voxelData, new XYZ(0, 1, 1), XYZ.OneX, -XYZ.OneZ, -XYZ.OneY)); 64 | Assert.AreEqual(0, AmbientOcclusion.CalculateAO(voxelData, new XYZ(1, 0, 1), -XYZ.OneZ, XYZ.OneY, -XYZ.OneX)); 65 | Assert.AreEqual(2, AmbientOcclusion.CalculateAO(voxelData, new XYZ(0, 0, 0), -XYZ.OneX, XYZ.OneY, XYZ.OneZ)); 66 | Assert.AreEqual(2, AmbientOcclusion.CalculateAO(voxelData, new XYZ(0, 0, 0), XYZ.OneX, -XYZ.OneY, XYZ.OneZ)); 67 | Assert.AreEqual(3, AmbientOcclusion.CalculateAO(voxelData, new XYZ(0, 0, 0), -XYZ.OneX, -XYZ.OneY, XYZ.OneZ)); 68 | } 69 | } 70 | 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Voxel Windows Explorer Thumbnails 2 | 3 | The [Voxels.Setup.exe](https://github.com/Arlorean/Voxels/releases/latest) provides Windows Explorer Thumbnails for: 4 | - [MagicaVoxel](https://ephtracy.github.io/) [**.vox** files](https://github.com/ephtracy/voxel-model/blob/master/MagicaVoxel-file-format-vox.txt) 5 | - [Voxlap Engine](http://advsys.net/ken/voxlap.htm) [**.vox** files](http://advsys.net/ken/build.htm) 6 | - [Qubicle](http://minddesk.com) [**.qbcl** project files](http://minddesk.com/learn/article.php?id=100) 7 | - [Qubicle](http://minddesk.com) [**.qb** binary files](http://minddesk.com/learn/article.php?id=22) 8 | 9 | Here are the MagicaVoxel sample file thumbnails: 10 | ![Windows Explorer Thumbnails](Voxels.Website/WindowsExplorer.png) 11 | 12 | Here are some of [Mike Judge's mmmm](https://mikelovesrobots.github.io/mmmm/) collections file thumbnails: 13 | ![mmmm Thumbnails](Voxels.Website/mmmm.png) 14 | 15 | Special thanks to Voxel Artist [Zachary Soares](https://www.zsinked.com/) for a screenshot of his [Qubicle](http://minddesk.com) project file thumbnails: 16 | ![ZacharySoares Thumbnails](Voxels.Website/ZacharySoares.png) 17 | 18 | The library uses [SkiaSharp](https://github.com/mono/SkiaSharp#using-skiasharp) which requires [Visual C++ Redistributable for Visual Studio 2015](https://www.microsoft.com/en-us/download/details.aspx?id=48145) to be installed. The exe setup does this for you. 19 | 20 | # PNG and SVG output 21 | 22 | The Voxels.CommandLine.exe tool converts .vox files to .png and .svg (512x512). Here is my example [wizard.vox](Voxels.CommandLine/wizard.vox) file converted: 23 | 24 | PNG | SVG 25 | ----------------|------------------------- 26 | ![PNG](Voxels.Website/wizard.png) | ![SVG](https://cdn.rawgit.com/Arlorean/Voxels/df6f605a/Voxels.Website/wizard.svg) 27 | 28 | # Command Line Build 29 | 30 | 1. Install ``Visual Studio 2017`` 31 | 1. Open ``Voxels.sln`` 32 | 1. Set ``Voxels.CommandLine`` as the startup project 33 | 1. Set ``Debug -> Command line arguments`` to be ``wizard.vox`` 34 | 1. Press ``Start`` in Visual Studio 2017 35 | 1. Open Windows Explorer on the ``Voxels.CommandLine\bin\Debug directory`` 36 | 1. There should be two new files: ``wizard.png`` and ``wizard.svg`` 37 | 38 | # Setup Build 39 | 40 | 1. Install ``Visual Studio 2017`` 41 | 1. Open ``Voxels.sln`` 42 | 1. Install [WiX Toolset](http://wixtoolset.org/) v3.11 43 | 1. Install [Wix Toolset Visual Studio 2017 Extension](https://marketplace.visualstudio.com/items?itemName=RobMensching.WixToolsetVisualStudio2017Extension) 44 | 1. Build ``Voxels.Setup`` to create the [Voxels.Setup.exe](https://github.com/Arlorean/Voxels/releases/download/v1.1/Voxels.Setup.exe) setup file. 45 | 46 | # Third Party Credits 47 | 48 | 1. [SkiaSharp](https://github.com/mono/SkiaSharp) - Xamarin C# wrapper for Google's Skia 2D rendering library 49 | 1. [SharpShell](https://github.com/dwmkerr/sharpshell) - Dave Kerr's ShellExtensions Library for .NET 50 | 1. [SharpShellTools](https://github.com/dwmkerr/sharpshell) - Dave Kerr's ShellExtensions Tools for .NET 51 | 1. [WiX Toolset](http://wixtoolset.org/) - ~~Simple~~ XML based windows installer scripting 52 | 1. [Ambient Occlusion](https://0fps.net/2013/07/03/ambient-occlusion-for-minecraft-like-worlds/) algorithm by [Mikola Lysenko](https://github.com/mikolalysenko). 53 | 1. [Wix VC++ 2015 Setup](https://gist.github.com/nathancorvussolis/6852ba282647aeb0c5c00e742e28eb48) gist for installing VC++ 2015 dlls. 54 | 55 | The 3x3x3.vox, 8x8x8.vox files are directly from the [MagicaVoxel](https://ephtracy.github.io/) distribution for authentic testing. 56 | 57 | # TODO 58 | 59 | * Add shell context menus to export PNG/SVG interactively 60 | -------------------------------------------------------------------------------- /Voxels.SkiaSharp/Voxels.SkiaSharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5275868A-6C22-469C-8C12-C039898E305C} 8 | Library 9 | Properties 10 | Voxels.SkiaSharp 11 | Voxels.SkiaSharp 12 | v4.8 13 | 512 14 | 15 | 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | AnyCPU 27 | 28 | 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | true 38 | 39 | 40 | SigningKey.snk 41 | 42 | 43 | 44 | ..\packages\SkiaSharp.1.59.1\lib\net45\SkiaSharp.dll 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Designer 63 | 64 | 65 | 66 | 67 | 68 | {5f012250-ca19-4c6a-a3a0-7144dae5e8ae} 69 | Voxels 70 | 71 | 72 | 73 | 74 | 75 | 76 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /Voxels.ShellExtensions/Voxels.ShellExtensions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F8A32354-DA2B-406C-AEBE-DCEFD85FD033} 8 | Library 9 | Properties 10 | Voxels.ShellExtensions 11 | Voxels.ShellExtensions 12 | v4.8 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | false 25 | AnyCPU 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | true 37 | 38 | 39 | SigningKey.snk 40 | 41 | 42 | 43 | ..\packages\SharpShellTools.2.2.0.0\lib\Apex.WinForms.dll 44 | 45 | 46 | ..\packages\SharpShellTools.2.2.0.0\lib\ServerManager.exe 47 | 48 | 49 | ..\packages\SharpShellTools.2.2.0.0\lib\SharpShell.dll 50 | 51 | 52 | ..\packages\SharpShellTools.2.2.0.0\lib\srm.exe 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | {5f012250-ca19-4c6a-a3a0-7144dae5e8ae} 78 | Voxels 79 | 80 | 81 | {5275868a-6c22-469c-8c12-c039898e305c} 82 | Voxels.SkiaSharp 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /Voxels.Test/Voxels.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {44FD680F-9699-49D0-926C-E392B8CF521C} 7 | Library 8 | false 9 | Voxels.Test 10 | Voxels.Test 11 | v4.8 12 | 512 13 | 14 | 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | false 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ..\packages\NUnit.3.13.3\lib\net45\nunit.framework.dll 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | PreserveNewest 57 | 58 | 59 | PreserveNewest 60 | 61 | 62 | PreserveNewest 63 | 64 | 65 | PreserveNewest 66 | 67 | 68 | PreserveNewest 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | {5f012250-ca19-4c6a-a3a0-7144dae5e8ae} 77 | Voxels 78 | 79 | 80 | 81 | 82 | PreserveNewest 83 | 84 | 85 | PreserveNewest 86 | 87 | 88 | 89 | 90 | 91 | 92 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /Voxels.Website/3x3x3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Voxels.Installer/Product.wxs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | NOT Installed 20 | (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /Voxels.Setup/Bundle.wxs: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | (VersionNT <> v6.0) OR (VersionNT = v6.0 AND ServicePackLevel >= 2) 21 | 22 | 23 | 24 | 25 | (VersionNT <> v6.1) OR (VersionNT = v6.1 AND ServicePackLevel >= 1) 26 | 27 | 28 | 29 | 31 | 32 | (VersionNT <> v6.3) OR (VersionNT = v6.3 AND NT603HALVER > v6.3.9600.16500) 33 | 34 | 35 | 36 | 42 | 43 | 44 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 71 | 77 | 78 | 79 | 80 | 95 | 101 | 102 | 103 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /Voxels.CommandLine/Voxels.CommandLine.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | {1E4D9AF1-41E1-4C81-9D9A-EF22F101E69F} 9 | Exe 10 | Voxels.CommandLine 11 | Voxels.CommandLine 12 | v4.8 13 | 512 14 | true 15 | 16 | 17 | 18 | 19 | 20 | AnyCPU 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | false 29 | 30 | 31 | AnyCPU 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE 36 | prompt 37 | 4 38 | false 39 | 40 | 41 | 42 | ..\packages\McMaster.Extensions.CommandLineUtils.4.0.2\lib\net45\McMaster.Extensions.CommandLineUtils.dll 43 | 44 | 45 | ..\packages\SkiaSharp.1.59.1\lib\net45\SkiaSharp.dll 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | PreserveNewest 61 | 62 | 63 | PreserveNewest 64 | 65 | 66 | PreserveNewest 67 | 68 | 69 | PreserveNewest 70 | 71 | 72 | PreserveNewest 73 | 74 | 75 | 76 | PreserveNewest 77 | 78 | 79 | PreserveNewest 80 | 81 | 82 | 83 | 84 | 85 | {F83EE85A-F1AA-49CA-9123-C009CDA79D21} 86 | NGif.SkiaSharp 87 | 88 | 89 | {5f012250-ca19-4c6a-a3a0-7144dae5e8ae} 90 | Voxels 91 | 92 | 93 | {5275868a-6c22-469c-8c12-c039898e305c} 94 | Voxels.SkiaSharp 95 | 96 | 97 | 98 | 99 | 100 | del libSkiaSharp.dll 101 | 102 | 103 | 104 | 105 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /Voxels.SkiaSharp/Renderer.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.IO; 4 | using System.Linq; 5 | 6 | namespace Voxels.SkiaSharp { 7 | public class RenderSettings { 8 | public int Size = 512; 9 | public float Pitch = -26f; 10 | public float Yaw = 45f; 11 | } 12 | 13 | public static class Renderer { 14 | static void RenderIntoBitmap(VoxelData voxelData, SKBitmap bitmap, RenderSettings renderSettings) { 15 | using (var canvas = new SKCanvas(bitmap)) { 16 | bitmap.Erase(SKColors.Transparent); 17 | RenderTriangles(voxelData, canvas, new MeshSettings { 18 | Yaw = renderSettings.Yaw, 19 | Pitch = renderSettings.Pitch, 20 | FakeLighting = true, 21 | FloorShadow = true, 22 | MeshType = MeshType.Triangles, 23 | }, renderSettings); 24 | } 25 | } 26 | 27 | public static byte[] RenderBitmap(VoxelData voxelData, RenderSettings renderSettings) { 28 | var size = renderSettings.Size; 29 | using (var bitmap = new SKBitmap(size, size, false)) { 30 | RenderIntoBitmap(voxelData, bitmap, renderSettings); 31 | return bitmap.Bytes; 32 | } 33 | } 34 | 35 | public static byte[] RenderPng(VoxelData voxelData, RenderSettings renderSettings) { 36 | var size = renderSettings.Size; 37 | using (var bitmap = new SKBitmap(size, size, false)) { 38 | RenderIntoBitmap(voxelData, bitmap, renderSettings); 39 | 40 | using (var image = SKImage.FromBitmap(bitmap)) { 41 | using (var data = image.Encode()) { 42 | var ms = new MemoryStream(); 43 | data.SaveTo(ms); 44 | return ms.ToArray(); 45 | } 46 | } 47 | } 48 | } 49 | 50 | public static byte[] RenderSvg(VoxelData voxelData, RenderSettings renderSettings) { 51 | var size = renderSettings.Size; 52 | var ms = new MemoryStream(); 53 | using (var skStream = new SKManagedWStream(ms)) { 54 | using (var writer = new SKXmlStreamWriter(skStream)) { 55 | using (var canvas = SKSvgCanvas.Create(SKRect.Create(0, 0, size, size), writer)) { 56 | RenderQuads(voxelData, size, canvas, new MeshSettings { 57 | Yaw = renderSettings.Yaw, 58 | Pitch = renderSettings.Pitch, 59 | FakeLighting = true, 60 | MeshType = MeshType.Quads, 61 | }, renderSettings); 62 | } 63 | } 64 | } 65 | return ms.ToArray(); 66 | } 67 | 68 | static SKMatrix44 GetMatrix(VoxelData voxelData, RenderSettings renderSettings) { 69 | var s = renderSettings.Size; 70 | var r = 1.61803398875f; 71 | var d = s / (r*voxelData.Size.MaxDimension); 72 | var tran = SKMatrix44.CreateTranslate(s*0.5f, s*0.5f, 0); 73 | var rotx = SKMatrix44.CreateRotationDegrees(1, 0, 0, renderSettings.Pitch); 74 | var roty = SKMatrix44.CreateRotationDegrees(0, 1, 0, renderSettings.Yaw); 75 | var matrix = SKMatrix44.CreateIdentity(); 76 | matrix.PreConcat(tran); 77 | matrix.PreConcat(rotx); 78 | matrix.PreConcat(roty); 79 | matrix.PreScale(d, -d, d); 80 | matrix.PreTranslate(-voxelData.Size.X*0.5f, -voxelData.Size.Z*0.5f, voxelData.Size.Y*0.5f); 81 | return matrix; 82 | } 83 | 84 | static void RenderTriangles(VoxelData voxelData, SKCanvas canvas, MeshSettings settings, RenderSettings renderSettings) { 85 | var matrix = GetMatrix(voxelData, renderSettings); 86 | settings.MeshType = MeshType.Triangles; 87 | var triangles = new MeshBuilder(voxelData, settings); 88 | 89 | using (var fill = new SKPaint() { IsAntialias = true, FilterQuality = SKFilterQuality.High }) { 90 | var vertices = triangles.Vertices 91 | .Select(v => matrix.MapScalars(v.X, v.Z, -v.Y, 1f)) 92 | .Select(v => new SKPoint(v[0], v[1])) 93 | .ToArray(); 94 | var colors = triangles.Colors; 95 | var occlusion = triangles.Occlusion; 96 | var indices = triangles.Faces; 97 | 98 | // Render triangles in batches since SkiaSharp DrawVertices indices are 16 bit which fails for large files 99 | var batchSize = 3*20000; // up to 20000 triangles per batch 100 | for (var i = 0; i < indices.Length; i += batchSize) { 101 | var batch = Enumerable.Range(i, Math.Min(batchSize, indices.Length - i)); 102 | var _vertices = batch.Select(j => vertices[indices[j]]).ToArray(); 103 | var _colors = batch.Select(j => AmbientOcclusion.CombineColorOcclusion(colors[indices[j]], occlusion[indices[j]])).Select(ToSKColor).ToArray(); 104 | var _indices = batch.Select(j => (ushort)(j-i)).ToArray(); 105 | canvas.DrawVertices(SKVertexMode.Triangles, _vertices, null, _colors, _indices, fill); 106 | } 107 | } 108 | } 109 | 110 | static void RenderQuads(VoxelData voxelData, int size, SKCanvas canvas, MeshSettings meshSettings, RenderSettings renderSettings) { 111 | var matrix = GetMatrix(voxelData, renderSettings); 112 | meshSettings.MeshType = MeshType.Quads; 113 | var quads = new MeshBuilder(voxelData, meshSettings); 114 | 115 | var vertices = quads.Vertices 116 | .Select(v => matrix.MapScalars(v.X, v.Z, -v.Y, 1f)) 117 | .Select(v => new SKPoint(v[0], v[1])) 118 | .ToArray(); 119 | var indices = quads.Faces; 120 | for (var i=0; i < indices.Length; i += 4) { 121 | using (var path = new SKPath()) { 122 | var quad = Enumerable.Range(0, 4) 123 | .Select(n => vertices[indices[i + n]]) 124 | .ToArray(); 125 | path.AddPoly(quad, close: true); 126 | 127 | var color = quads.Colors[quads.Faces[i]]; // Take 1st vertex color for face 128 | using (var fill = new SKPaint() { 129 | Color = ToSKColor(color), 130 | Style=SKPaintStyle.StrokeAndFill, 131 | StrokeJoin=SKStrokeJoin.Round, 132 | }) { 133 | canvas.DrawPath(path, fill); 134 | } 135 | } 136 | } 137 | } 138 | 139 | static SKColor ToSKColor(Color c) { 140 | return new SKColor(c.R, c.G, c.B, c.A); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /Voxels.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33530.505 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Voxels.CommandLine", "Voxels.CommandLine\Voxels.CommandLine.csproj", "{1E4D9AF1-41E1-4C81-9D9A-EF22F101E69F}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE} = {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE} 9 | EndProjectSection 10 | EndProject 11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Voxels.SkiaSharp", "Voxels.SkiaSharp\Voxels.SkiaSharp.csproj", "{5275868A-6C22-469C-8C12-C039898E305C}" 12 | EndProject 13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Voxels.Test", "Voxels.Test\Voxels.Test.csproj", "{44FD680F-9699-49D0-926C-E392B8CF521C}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Voxels.ShellExtensions", "Voxels.ShellExtensions\Voxels.ShellExtensions.csproj", "{F8A32354-DA2B-406C-AEBE-DCEFD85FD033}" 16 | EndProject 17 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Voxels.Installer", "Voxels.Installer\Voxels.Installer.wixproj", "{4CE76915-E1EA-46AF-9C22-737F7B9B0C27}" 18 | ProjectSection(ProjectDependencies) = postProject 19 | {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE} = {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE} 20 | {5275868A-6C22-469C-8C12-C039898E305C} = {5275868A-6C22-469C-8C12-C039898E305C} 21 | EndProjectSection 22 | EndProject 23 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Voxels.Setup", "Voxels.Setup\Voxels.Setup.wixproj", "{74833944-18A2-406D-AD28-63B36EB8795D}" 24 | ProjectSection(ProjectDependencies) = postProject 25 | {4CE76915-E1EA-46AF-9C22-737F7B9B0C27} = {4CE76915-E1EA-46AF-9C22-737F7B9B0C27} 26 | EndProjectSection 27 | EndProject 28 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Voxels.Core", "Voxels.Core\Voxels.Core.csproj", "{5F012250-CA19-4C6A-A3A0-7144DAE5E8AE}" 29 | EndProject 30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NGif.SkiaSharp", "NGif.SkiaSharp\NGif.SkiaSharp\NGif.SkiaSharp.csproj", "{F83EE85A-F1AA-49CA-9123-C009CDA79D21}" 31 | EndProject 32 | Global 33 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 34 | Debug|Any CPU = Debug|Any CPU 35 | Debug|x86 = Debug|x86 36 | Release|Any CPU = Release|Any CPU 37 | Release|x86 = Release|x86 38 | EndGlobalSection 39 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 40 | {1E4D9AF1-41E1-4C81-9D9A-EF22F101E69F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {1E4D9AF1-41E1-4C81-9D9A-EF22F101E69F}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {1E4D9AF1-41E1-4C81-9D9A-EF22F101E69F}.Debug|x86.ActiveCfg = Debug|Any CPU 43 | {1E4D9AF1-41E1-4C81-9D9A-EF22F101E69F}.Debug|x86.Build.0 = Debug|Any CPU 44 | {1E4D9AF1-41E1-4C81-9D9A-EF22F101E69F}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {1E4D9AF1-41E1-4C81-9D9A-EF22F101E69F}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {1E4D9AF1-41E1-4C81-9D9A-EF22F101E69F}.Release|x86.ActiveCfg = Release|Any CPU 47 | {1E4D9AF1-41E1-4C81-9D9A-EF22F101E69F}.Release|x86.Build.0 = Release|Any CPU 48 | {5275868A-6C22-469C-8C12-C039898E305C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 49 | {5275868A-6C22-469C-8C12-C039898E305C}.Debug|Any CPU.Build.0 = Debug|Any CPU 50 | {5275868A-6C22-469C-8C12-C039898E305C}.Debug|x86.ActiveCfg = Debug|Any CPU 51 | {5275868A-6C22-469C-8C12-C039898E305C}.Debug|x86.Build.0 = Debug|Any CPU 52 | {5275868A-6C22-469C-8C12-C039898E305C}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {5275868A-6C22-469C-8C12-C039898E305C}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {5275868A-6C22-469C-8C12-C039898E305C}.Release|x86.ActiveCfg = Release|Any CPU 55 | {5275868A-6C22-469C-8C12-C039898E305C}.Release|x86.Build.0 = Release|Any CPU 56 | {44FD680F-9699-49D0-926C-E392B8CF521C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 57 | {44FD680F-9699-49D0-926C-E392B8CF521C}.Debug|Any CPU.Build.0 = Debug|Any CPU 58 | {44FD680F-9699-49D0-926C-E392B8CF521C}.Debug|x86.ActiveCfg = Debug|Any CPU 59 | {44FD680F-9699-49D0-926C-E392B8CF521C}.Debug|x86.Build.0 = Debug|Any CPU 60 | {44FD680F-9699-49D0-926C-E392B8CF521C}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {44FD680F-9699-49D0-926C-E392B8CF521C}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {44FD680F-9699-49D0-926C-E392B8CF521C}.Release|x86.ActiveCfg = Release|Any CPU 63 | {44FD680F-9699-49D0-926C-E392B8CF521C}.Release|x86.Build.0 = Release|Any CPU 64 | {F8A32354-DA2B-406C-AEBE-DCEFD85FD033}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 65 | {F8A32354-DA2B-406C-AEBE-DCEFD85FD033}.Debug|Any CPU.Build.0 = Debug|Any CPU 66 | {F8A32354-DA2B-406C-AEBE-DCEFD85FD033}.Debug|x86.ActiveCfg = Debug|Any CPU 67 | {F8A32354-DA2B-406C-AEBE-DCEFD85FD033}.Debug|x86.Build.0 = Debug|Any CPU 68 | {F8A32354-DA2B-406C-AEBE-DCEFD85FD033}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {F8A32354-DA2B-406C-AEBE-DCEFD85FD033}.Release|Any CPU.Build.0 = Release|Any CPU 70 | {F8A32354-DA2B-406C-AEBE-DCEFD85FD033}.Release|x86.ActiveCfg = Release|Any CPU 71 | {F8A32354-DA2B-406C-AEBE-DCEFD85FD033}.Release|x86.Build.0 = Release|Any CPU 72 | {4CE76915-E1EA-46AF-9C22-737F7B9B0C27}.Debug|Any CPU.ActiveCfg = Debug|x86 73 | {4CE76915-E1EA-46AF-9C22-737F7B9B0C27}.Debug|x86.ActiveCfg = Debug|x86 74 | {4CE76915-E1EA-46AF-9C22-737F7B9B0C27}.Debug|x86.Build.0 = Debug|x86 75 | {4CE76915-E1EA-46AF-9C22-737F7B9B0C27}.Release|Any CPU.ActiveCfg = Release|x86 76 | {4CE76915-E1EA-46AF-9C22-737F7B9B0C27}.Release|Any CPU.Build.0 = Release|x86 77 | {4CE76915-E1EA-46AF-9C22-737F7B9B0C27}.Release|x86.ActiveCfg = Release|x86 78 | {4CE76915-E1EA-46AF-9C22-737F7B9B0C27}.Release|x86.Build.0 = Release|x86 79 | {74833944-18A2-406D-AD28-63B36EB8795D}.Debug|Any CPU.ActiveCfg = Debug|x86 80 | {74833944-18A2-406D-AD28-63B36EB8795D}.Debug|x86.ActiveCfg = Debug|x86 81 | {74833944-18A2-406D-AD28-63B36EB8795D}.Debug|x86.Build.0 = Debug|x86 82 | {74833944-18A2-406D-AD28-63B36EB8795D}.Release|Any CPU.ActiveCfg = Release|x86 83 | {74833944-18A2-406D-AD28-63B36EB8795D}.Release|Any CPU.Build.0 = Release|x86 84 | {74833944-18A2-406D-AD28-63B36EB8795D}.Release|x86.ActiveCfg = Release|x86 85 | {74833944-18A2-406D-AD28-63B36EB8795D}.Release|x86.Build.0 = Release|x86 86 | {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 87 | {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE}.Debug|Any CPU.Build.0 = Debug|Any CPU 88 | {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE}.Debug|x86.ActiveCfg = Debug|Any CPU 89 | {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE}.Debug|x86.Build.0 = Debug|Any CPU 90 | {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE}.Release|Any CPU.ActiveCfg = Release|Any CPU 91 | {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE}.Release|Any CPU.Build.0 = Release|Any CPU 92 | {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE}.Release|x86.ActiveCfg = Release|Any CPU 93 | {5F012250-CA19-4C6A-A3A0-7144DAE5E8AE}.Release|x86.Build.0 = Release|Any CPU 94 | {F83EE85A-F1AA-49CA-9123-C009CDA79D21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 95 | {F83EE85A-F1AA-49CA-9123-C009CDA79D21}.Debug|Any CPU.Build.0 = Debug|Any CPU 96 | {F83EE85A-F1AA-49CA-9123-C009CDA79D21}.Debug|x86.ActiveCfg = Debug|Any CPU 97 | {F83EE85A-F1AA-49CA-9123-C009CDA79D21}.Debug|x86.Build.0 = Debug|Any CPU 98 | {F83EE85A-F1AA-49CA-9123-C009CDA79D21}.Release|Any CPU.ActiveCfg = Release|Any CPU 99 | {F83EE85A-F1AA-49CA-9123-C009CDA79D21}.Release|Any CPU.Build.0 = Release|Any CPU 100 | {F83EE85A-F1AA-49CA-9123-C009CDA79D21}.Release|x86.ActiveCfg = Release|Any CPU 101 | {F83EE85A-F1AA-49CA-9123-C009CDA79D21}.Release|x86.Build.0 = Release|Any CPU 102 | EndGlobalSection 103 | GlobalSection(SolutionProperties) = preSolution 104 | HideSolutionNode = FALSE 105 | EndGlobalSection 106 | GlobalSection(ExtensibilityGlobals) = postSolution 107 | SolutionGuid = {E2EDB07E-8C5E-4BD4-994C-98B6465A3D0D} 108 | EndGlobalSection 109 | EndGlobal 110 | -------------------------------------------------------------------------------- /Voxels.CommandLine/Program.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.IO; 3 | using Voxels.SkiaSharp; 4 | using McMaster.Extensions.CommandLineUtils; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace Voxels.CommandLine { 10 | class Program { 11 | 12 | [Option(ShortName = "w", Description = "Size in pixels.")] 13 | public int Size { get; set; } = 512; 14 | 15 | [Option(ShortName = "y", Description = "The yaw in degrees.")] 16 | public float Yaw { get; set; } = 45f; 17 | 18 | [Option(ShortName = "x", Description = "The pitch in degrees.")] 19 | public float Pitch { get; set; } = -26f; 20 | 21 | [Option(Description = "Output a PNG file.")] 22 | public bool PNG { get; set; } 23 | 24 | [Option(Description = "Output an SVG file.")] 25 | public bool SVG { get; set; } 26 | 27 | [Option(Description = "Output an animated GIF file.")] 28 | public bool GIF { get; set; } 29 | 30 | [Option(Description = "Convert PNG file to VOX.")] 31 | public bool VOX { get; set; } 32 | 33 | [Option(Description = "Output a 3D Texture for Unity.", LongName = "3D")] 34 | public bool Texture3D { get; set; } 35 | 36 | [Option(Description = "The number of frames for the animated GIF.")] 37 | public int Frames { get; set; } = 30; 38 | 39 | [Option(Description = "The duration for the animated GIF in seconds.")] 40 | public float Duration { get; set; } = 2f; 41 | 42 | [Option(Description = "The number of camera orbits for the animated GIF (0=none, -1=clockwise.")] 43 | public int CameraOrbits { get; set; } = 1; 44 | 45 | [Option(Description = "Recurse into sub-directories to convert.")] 46 | public bool Recursive { get; set; } 47 | 48 | [Option(Description = "Output filename ({0} - path minus extension, {1} - extension).")] 49 | public string Output { get; set; } = "{0}.{1}"; 50 | 51 | [Argument(0, Description = "Filenames or directories to convert."), Required] 52 | public string[] Filenames { get; set; } 53 | 54 | public static int Main(string[] args) 55 | => CommandLineApplication.Execute(args); 56 | 57 | void OnExecute() { 58 | // Initialize SkiaSharp 59 | NativeLibrary.Initialize(); 60 | 61 | if (VOX) { 62 | var colorsUsed = new HashSet() { Color.Transparent }; 63 | ExtractColors(Filenames, colorsUsed); 64 | 65 | var palette = colorsUsed.ToArray(); 66 | if (palette.Length > 255) { 67 | Console.WriteLine($"Warning: More than 255 unique colors exist in the image(s) - truncating palette from {palette.Length} to 256 colors."); 68 | } 69 | Array.Resize(ref palette, 256); // Ensure array is exactly 256 colors long 70 | 71 | ConvertFiles(Filenames, palette); 72 | } 73 | else { 74 | // If none of PNG, SVG or GIF is specified, output PNG and SVG (previous default) 75 | if (!PNG && !SVG && !GIF && !Texture3D) { 76 | PNG = SVG = true; 77 | } 78 | 79 | var renderSettings = new RenderSettings() { 80 | Size = Size, 81 | Pitch = Pitch, 82 | Yaw = Yaw, 83 | }; 84 | RenderFiles(Filenames, renderSettings); 85 | } 86 | } 87 | 88 | void RenderFiles(string[] filenames, RenderSettings renderSettings) { 89 | foreach (var filename in filenames) { 90 | // Convert all files in directories 91 | if (Directory.Exists(filename)) { 92 | var directoryFilenames = Directory.GetFiles(filename); 93 | RenderFiles(directoryFilenames, renderSettings); 94 | if (Recursive) { 95 | var directoryNames = Directory.GetDirectories(filename); 96 | RenderFiles(directoryNames, renderSettings); 97 | } 98 | } 99 | else { 100 | if (GIF) { 101 | using (var stream = File.OpenRead(filename)) { 102 | // Support animation frames in MagicaVoxel 103 | if (Path.GetExtension(filename).ToLower() == ".vox") { 104 | var magicaVoxel = new MagicaVoxel(); 105 | if (magicaVoxel.Read(stream)) { 106 | var worldBounds = magicaVoxel.GetWorldAABB(0, Frames - 1); 107 | WriteOutput(filename, "gif", 108 | Animation.RenderGif(renderSettings, Frames, Duration, CameraOrbits, 109 | worldBounds, i => magicaVoxel.Flatten(worldBounds, i)) 110 | ); 111 | } 112 | } 113 | else { 114 | var voxelData = VoxelImport.Import(filename); 115 | var worldBounds = new BoundsXYZ(voxelData.Size); 116 | WriteOutput(filename, "gif", 117 | Animation.RenderGif(renderSettings, Frames, Duration, CameraOrbits, 118 | worldBounds, _ => voxelData) 119 | ); 120 | } 121 | } 122 | } 123 | else { 124 | var voxelData = VoxelImport.Import(filename); 125 | if (voxelData != null) { 126 | if (PNG) { 127 | WriteOutput(filename, "png", Renderer.RenderPng(voxelData, renderSettings)); 128 | } 129 | if (SVG) { 130 | WriteOutput(filename, "svg", Renderer.RenderSvg(voxelData, renderSettings)); 131 | } 132 | if (Texture3D) { 133 | Slicer.MakeSquare(voxelData.Size, out var rows, out var columns); 134 | 135 | WriteOutput(filename, $"({columns}x{rows}).png", Slicer.RenderTexture3D(voxelData, columns, rows)); 136 | } 137 | } 138 | } 139 | } 140 | } 141 | } 142 | 143 | void WriteOutput(string filename, string extension, byte[] bytes) { 144 | var outputFilename = string.Format(Output, Path.ChangeExtension(filename, null), extension); 145 | File.WriteAllBytes(outputFilename, bytes); 146 | } 147 | 148 | void ExtractColors(string[] filenames, HashSet colorsUsed) { 149 | foreach (var filename in filenames) { 150 | // Convert all files in directories 151 | if (Directory.Exists(filename)) { 152 | var directoryFilenames = Directory.GetFiles(filename); 153 | ExtractColors(directoryFilenames, colorsUsed); 154 | if (Recursive) { 155 | var directoryNames = Directory.GetDirectories(filename); 156 | ExtractColors(directoryNames, colorsUsed); 157 | } 158 | } 159 | else { 160 | ImageToVoxel.ExtractColors(filename, colorsUsed); 161 | } 162 | } 163 | } 164 | 165 | void ConvertFiles(string[] filenames, Color[] pallete) { 166 | foreach (var filename in filenames) { 167 | // Convert all files in directories 168 | if (Directory.Exists(filename)) { 169 | var directoryFilenames = Directory.GetFiles(filename); 170 | ConvertFiles(directoryFilenames, pallete); 171 | if (Recursive) { 172 | var directoryNames = Directory.GetDirectories(filename); 173 | ConvertFiles(directoryNames, pallete); 174 | } 175 | } 176 | else { 177 | var voxelData = ImageToVoxel.Import(filename, pallete); 178 | if (voxelData != null) { 179 | using (var stream = File.Create(Path.ChangeExtension(filename, ".vox"))) { 180 | var magicaVoxel = new MagicaVoxel((VoxelDataBytes)voxelData); 181 | magicaVoxel.Write(stream); 182 | } 183 | } 184 | } 185 | } 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /Voxels.Website/8x8x8.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /Voxels.Website/wizard.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | -------------------------------------------------------------------------------- /Voxels.Setup/License.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang2057\deflangfe1041\themelang2057\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;} 2 | {\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} 3 | {\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;} 4 | {\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} 5 | {\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} 6 | {\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f45\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f46\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} 7 | {\f48\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f49\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f50\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f51\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} 8 | {\f52\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f53\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f65\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}{\f66\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;} 9 | {\f68\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f69\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f70\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f71\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);} 10 | {\f72\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f73\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f65\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}{\f66\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;} 11 | {\f68\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f69\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f70\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f71\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);} 12 | {\f72\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f73\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f415\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f416\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} 13 | {\f418\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f419\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f420\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\f421\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);} 14 | {\f422\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f423\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} 15 | {\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} 16 | {\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} 17 | {\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} 18 | {\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} 19 | {\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} 20 | {\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;} 21 | {\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);} 22 | {\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} 23 | {\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} 24 | {\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} 25 | {\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} 26 | {\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} 27 | {\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} 28 | {\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} 29 | {\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} 30 | {\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;} 31 | {\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} 32 | {\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} 33 | {\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} 34 | {\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} 35 | {\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}} 36 | {\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; 37 | \red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa160\sl259\slmult1 38 | \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 39 | \fs22\lang2057\langfe1041\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp2057\langfenp1041 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* 40 | \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1 41 | \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang2057\langfe1041\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp2057\langfenp1041 \snext11 \ssemihidden \sunhideused 42 | Normal Table;}}{\*\rsidtbl \rsid14380325\rsid15563718\rsid16147929}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Adam Davidson} 43 | {\creatim\yr2023\mo8\dy8\hr10\min14}{\revtim\yr2023\mo8\dy8\hr15\min38}{\version3}{\edmins1}{\nofpages1}{\nofwords157}{\nofchars901}{\nofcharsws1056}{\vern37}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} 44 | \paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect 45 | \widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 46 | \dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot16147929 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 47 | \pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 48 | \pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang 49 | {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\tx0\tx959\tx1918\tx2877\tx3836\tx4795\tx5754\tx6713\tx7672\tx8631\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 50 | \fs22\lang2057\langfe1041\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp2057\langfenp1041 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\insrsid14380325 \hich\af2\dbch\af31505\loch\f2 COPYRIGHT AND PERMISSION NOTICE 51 | \par \hich\af2\dbch\af31505\loch\f2 52 | \par \hich\af2\dbch\af31505\loch\f2 Copyright (c) }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\insrsid16147929 \hich\af2\dbch\af31505\loch\f2 2023}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\insrsid14380325 \hich\af2\dbch\af31505\loch\f2 }{\rtlch\fcs1 53 | \af2\afs20 \ltrch\fcs0 \f2\fs20\insrsid16147929 \hich\af2\dbch\af31505\loch\f2 Adam Davidson (}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\insrsid16147929\charrsid16147929 \hich\af2\dbch\af31505\loch\f2 https://github.com/Arlorean}{\rtlch\fcs1 54 | \af2\afs20 \ltrch\fcs0 \f2\fs20\insrsid15563718 \hich\af2\dbch\af31505\loch\f2 /Voxels}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\insrsid16147929 \hich\af2\dbch\af31505\loch\f2 )}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\insrsid14380325 . 55 | \par \hich\af2\dbch\af31505\loch\f2 56 | \par \hich\af2\dbch\af31505\loch\f2 All rights reserved. 57 | \par \hich\af2\dbch\af31505\loch\f2 58 | \par \hich\af2\dbch\af31505\loch\f2 Permission to use, copy, modify, and distribute this software for any purpose 59 | \par \hich\af2\dbch\af31505\loch\f2 with or without fee is hereby granted, provided that the above copyright 60 | \par \hich\af2\dbch\af31505\loch\f2 notice and this permission notice appear in all copies. 61 | \par \hich\af2\dbch\af31505\loch\f2 62 | \par \hich\af2\dbch\af31505\loch\f2 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRA\hich\af2\dbch\af31505\loch\f2 NTY OF ANY KIND, EXPRESS OR 63 | \par \hich\af2\dbch\af31505\loch\f2 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64 | \par \hich\af2\dbch\af31505\loch\f2 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN 65 | \par \hich\af2\dbch\af31505\loch\f2 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 66 | \par \hich\af2\dbch\af31505\loch\f2 DAM\hich\af2\dbch\af31505\loch\f2 AGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 67 | \par \hich\af2\dbch\af31505\loch\f2 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 68 | \par \hich\af2\dbch\af31505\loch\f2 OR OTHER DEALINGS IN THE SOFTWARE. 69 | \par \hich\af2\dbch\af31505\loch\f2 70 | \par \hich\af2\dbch\af31505\loch\f2 Except as contained in this notice, the name of a copyright holder shall n\hich\af2\dbch\af31505\loch\f2 ot 71 | \par \hich\af2\dbch\af31505\loch\f2 be used in advertising or otherwise to promote the sale, use or other dealings 72 | \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\insrsid14380325 \hich\af2\dbch\af31505\loch\f2 in this Software without prior written authorization of the copyright holder.}{ 73 | \rtlch\fcs1 \af37 \ltrch\fcs0 \f37\lang9\langfe1041\langnp9\insrsid14380325 74 | \par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a 75 | 9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad 76 | 5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 77 | b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 78 | 0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 79 | a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f 80 | c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 81 | 0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 82 | a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 83 | 6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b 84 | 4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b 85 | 4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100b6f4679893070000c9200000160000007468656d652f7468656d652f 86 | 7468656d65312e786d6cec59cd8b1bc915bf07f23f347d97f5d5ad8fc1f2a24fcfda33b6b164873dd648a5eef2547789aad28cc56208de532e81c026e49085bd 87 | ed21842cecc22eb9e48f31d8249b3f22afaa5bdd5552c99e191c3061463074977eefd5afde7bf5de53d5ddcf5e26d4bbc05c1096f6fcfa9d9aefe174ce16248d 88 | 7afeb3d9a4d2f13d2151ba4094a5b8e76fb0f03fbbf7eb5fdd454732c609f6403e1547a8e7c752ae8eaa5531876124eeb0154ee1bb25e30992f0caa3ea82a34b 89 | d09bd06aa3566b55134452df4b51026a1f2f97648ebd9952e9dfdb2a1f53784da5500373caa74a35b6243476715e5708b11143cabd0b447b3eccb3609733fc52 90 | fa1e4542c2173dbfa6fffceabdbb5574940b517940d6909be8bf5c2e17589c37f49c3c3a2b260d823068f50bfd1a40e53e6edc1eb7c6ad429f06a0f91c569a71 91 | b175b61bc320c71aa0ecd1a17bd41e35eb16ded0dfdce3dc0fd5c7c26b50a63fd8c34f2643b0a285d7a00c1feee1c3417730b2f56b50866fede1dbb5fe28685b 92 | fa3528a6243ddf43d7c25673b85d6d0159327aec8477c360d26ee4ca4b144443115d6a8a254be5a1584bd00bc6270050408a24493db959e1259a43140f112567 93 | 9c7827248a21f056286502866b8ddaa4d684ffea13e827ed5174849121ad780113b137a4f87862cec94af6fc07a0d537206f7ffef9cdeb1fdfbcfee9cd575fbd 94 | 79fdf77c6eadca923b466964cafdf2dd1ffef3cd6fbd7ffff0ed2f5fff319b7a172f4cfcbbbffdeedd3ffef93ef5b0e2d2146ffff4fdbb1fbf7ffbe7dfffebaf 95 | 5f3bb4f7393a33e1339260e13dc297de5396c0021dfcf119bf9ec42c46c494e8a791402952b338f48f656ca11f6d10450edc00db767cce21d5b880f7d72f2cc2 96 | d398af2571687c182716f094313a60dc6985876a2ec3ccb3751ab927e76b13f714a10bd7dc43945a5e1eaf579063894be530c616cd2714a5124538c5d253dfb1 97 | 738c1dabfb8210cbaea764ce99604be97d41bc01224e93ccc899154da5d03149c02f1b1741f0b7659bd3e7de8051d7aa47f8c246c2de40d4417e86a965c6fb68 98 | 2d51e252394309350d7e8264ec2239ddf0b9891b0b099e8e3065de78818570c93ce6b05ec3e90f21cdb8dd7e4a37898de4929cbb749e20c64ce4889d0f6394ac 99 | 5cd829496313fbb938871045de13265df05366ef10f50e7e40e941773f27d872f787b3c133c8b026a53240d4376beef0e57dccacf89d6ee8126157aae9f3c44a 100 | b17d4e9cd131584756689f604cd1255a60ec3dfbdcc160c05696cd4bd20f62c82ac7d815580f901dabea3dc5027a25d5dcece7c91322ac909de2881de073bad9 101 | 493c1b9426881fd2fc08bc6eda7c0ca52e7105c0633a3f37818f08f480102f4ea33c16a0c308ee835a9fc4c82a60ea5db8e375c32dff5d658fc1be7c61d1b8c2 102 | be04197c6d1948eca6cc7b6d3343d49aa00c9819822ec3956e41c4727f29a28aab165b3be596f6a62ddd00dd91d5f42424fd6007b4d3fb84ffbbde073a8cb77f 103 | f9c6b10f3e4ebfe3566c25ab6b763a8792c9f14e7f7308b7dbd50c195f904fbfa919a175fa04431dd9cf58b73dcd6d4fe3ffdff73487f6f36d2773a8dfb8ed64 104 | 7ce8306e3b99fc70e5e3743265f3027d8d3af0c80e7af4b14f72f0d46749289dca0dc527421ffc08f83db398c0a092d3279eb838055cc5f0a8ca1c4c60e1228e 105 | b48cc799fc0d91f134462b381daafb4a492472d591f0564cc0a1911e76ea5678ba4e4ed9223becacd7d5c16656590592e5782d2cc6e1a04a66e856bb3cc02bd4 106 | 6bb6913e68dd1250b2d721614c6693683a48b4b783ca48fa58178ce620a157f65158741d2c3a4afdd6557b2c805ae115f8c1edc1cff49e1f06200242701e07cd 107 | f942f92973f5d6bbda991fd3d3878c69450034d8db08283ddd555c0f2e4fad2e0bb52b78da2261849b4d425b46377822869fc17974aad1abd0b8aeafbba54b2d 108 | 7aca147a3e08ad9246bbf33e1637f535c8ede6069a9a9982a6de65cf6f35430899395af5fc251c1ac363b282d811ea3717a211dcbccc25cf36fc4d32cb8a0b39 109 | 4222ce0cae934e960d122231f728497abe5a7ee1069aea1ca2b9d51b90103e59725d482b9f1a3970baed64bc5ce2b934dd6e8c284b67af90e1b35ce1fc568bdf 110 | 1cac24d91adc3d8d1797de195df3a708422c6cd795011744c0dd413db3e682c0655891c8caf8db294c79da356fa3740c65e388ae62945714339967709dca0b3a 111 | faadb081f196af190c6a98242f8467912ab0a651ad6a5a548d8cc3c1aafb6121653923699635d3ca2aaa6abab39835c3b60cecd8f26645de60b53531e434b3c2 112 | 67a97b37e576b7b96ea74f28aa0418bcb09fa3ea5ea12018d4cac92c6a8af17e1a56393b1fb56bc776811fa07695226164fdd656ed8edd8a1ae19c0e066f54f9 113 | 416e376a6168b9ed2bb5a5f5adb979b1cdce5e40f2184197bba6526857c2c92e47d0104d754f92a50dd8222f65be35e0c95b73d2f3bfac85fd60d80887955a27 114 | 1c57826650ab74c27eb3d20fc3667d1cd66ba341e31514161927f530bbb19fc00506dde4f7f67a7cefee3ed9ded1dc99b3a4caf4dd7c5513d777f7f5c6e1bb7b 115 | 8f40d2f9b2d598749bdd41abd26df627956034e854bac3d6a0326a0ddba3c9681876ba9357be77a1c141bf390c5ae34ea5551f0e2b41aba6e877ba9576d068f4 116 | 8376bf330efaaff23606569ea58fdc16605ecdebde7f010000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d65 117 | 2f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d36 118 | 3f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e 119 | 3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d985 120 | 0528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c020000130000000000000000000000 121 | 0000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000 122 | 000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c0000000000000000000000000019020000 123 | 7468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d0014000600080000002100b6f4679893070000c92000001600000000000000 124 | 000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b01000027000000 125 | 000000000000000000009d0a00007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000980b00000000} 126 | {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d 127 | 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 128 | 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 129 | 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} 130 | {\*\latentstyles\lsdstimax375\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; 131 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; 132 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; 133 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; 134 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; 135 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; 136 | \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; 137 | \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; 138 | \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; 139 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; 140 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; 141 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; 142 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; 143 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; 144 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; 145 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; 146 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; 147 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; 148 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; 149 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; 150 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; 151 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; 152 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; 153 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; 154 | \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; 155 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; 156 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; 157 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; 158 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1; 159 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid; 160 | \lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid; 161 | \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2; 162 | \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1; 163 | \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1; 164 | \lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1; 165 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; 166 | \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2; 167 | \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; 168 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; 169 | \lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; 170 | \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; 171 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; 172 | \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; 173 | \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; 174 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; 175 | \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; 176 | \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; 177 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; 178 | \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; 179 | \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; 180 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; 181 | \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; 182 | \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; 183 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; 184 | \lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; 185 | \lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; 186 | \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; 187 | \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; 188 | \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; 189 | \lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; 190 | \lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; 191 | \lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; 192 | \lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; 193 | \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; 194 | \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; 195 | \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; 196 | \lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; 197 | \lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; 198 | \lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; 199 | \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; 200 | \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; 201 | \lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; 202 | \lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; 203 | \lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; 204 | \lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; 205 | \lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; 206 | \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; 207 | \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention; 208 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hashtag;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Unresolved Mention;}}{\*\datastore 010500000200000018000000 209 | 4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 210 | d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 211 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 212 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 213 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 214 | fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 215 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 216 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 217 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 218 | ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e500000000000000000000000090f0 219 | ee015410d301feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 220 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 221 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 222 | 0000000000000000000000000000000000000000000000000105000000000000}} --------------------------------------------------------------------------------