├── 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 |
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 | 
11 |
12 | Here are some of [Mike Judge's mmmm](https://mikelovesrobots.github.io/mmmm/) collections file thumbnails:
13 | 
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 | 
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 |  | 
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 |
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 |
160 |
--------------------------------------------------------------------------------
/Voxels.Website/wizard.svg:
--------------------------------------------------------------------------------
1 |
2 |
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}}
--------------------------------------------------------------------------------