This program was made to optimize the meshes that are exported by MagicaVoxel (software made by Ephtracy), written in rust, it is the fastest and, thanks to some clever optimizations and tricks, it is also the best at compressing even if it is a lossless compression, which means that the quality of the mesh isn't traded with the speed of the execution of the program. If you tried to export a mesh using magicavoxel you would know that its mesh exporter is pretty inefficient and it is not ideal for gamedev. For this reason and also because I was unable to find a program such as this with the characteristics I had in mind, Voxel Optimizer was born. It is pretty similiar to an addon made for blender (Vox Cleaner V2 by Farhan) but it differs for many reasons:
- Completely free
- You don't need blender
- Low ram usage
- Low disk usage
- Easy to use
- multithreaded so that converting many models is blazingly fast
Before explaining how it works I wanted to say that this program works for windows and on linux and mac (mac is untested) throught wine but I also managed to get it working on Linux by compiling its source like so (from a default installation of Rustup > rustup default stable on Kubuntu ) :
sudo apt install rustup
rustup default stable
sudo apt-get install libatk1.0-dev libgdk-pixbuf2.0-dev
sudo apt-get install libgtk-3-dev
cargo build --profile finalrelease (or debug if you want debug)
(Copy src inside of /target/finalrelease (or debug) or Copy VoxelOptimizer inside of src)
cd /path/to/VoxelOptimizer
WAYLAND_DISPLAY=invalid ./VoxelOptimizer //WayLand doesn't support drag-and-drop apparently so force X11 works fine (actually winit doesn't support Wayland drag and drop https://github.com/rust-windowing/winit/issues/1881)
if you know a little bit of rust you can contribute to other major platforms such as Linux (making it wayland-compatible) and mac (just test it with wine or whatever for the 5 people that use macOS + magicavoxel and blender/godot/unity whatever).
Also while this program doesn't use much cpu the better the cpu the faster will be the processes, the cpu also has to support multithreading to a certain capacity (Most of the cpu's will do the job). Last but not least to run this program you need a minimal amount of ram but it has to be at least as big as the models you are compressing.
Watch this video: Optimize magicavoxel models with voxel optimizer for version 1.0 and this one: A new version of VoxelOptimizer is out!!! for version 2.0 or follow this instructions to get started.
download the latest release (release v2.0.0) and extract it in a folder or on your desktop, the important thing is that both the folder "src" and voxeloptimizer.exe are on the same directory (whether it is on the desktop or in another folder).
To run the program double click onto the executable and two windows will open.
You'll have something like this:
If you are on version 2.0 or above you can drag and drop every project file (.vox) you want to convert or use .ply files exported from magicavoxel itself. If you plan on using .vox files then you can export an obj with different materials depending on your settings.
If you are on version 1.0.1 to convert models to an optimized and superior form you first have to create the models in magicavoxel and export them using the second option (.ply) and then drag and drop every file you want to convert (you can and it's better if you do more than one at the time, tip: Control + A selects all the files in a folder) like so:
brave_VXoZnasjdW.mp4
The default options are the best if you care about output file size, however depending on your needs you might need to change some, so here is every setting and its explanation with pros and cons.
Starting from version 2.1.0 the program can also be used as a CLI, for it to work you must provide an export path (either by manually modifying options.txt by inserting "picked_path:/path/to/export/folder" or launching the GUI).
The usage of the CLI is as follows: ./VoxelOptimizer.exe /path/to/file.vox
This settings influence the algorithm used to optimize the models.
This setting changes the way the algorithm works while reducing the amount of vertices, to explain how it works here are some examples:
| Off | On |
|---|---|
| Without the option it would be divided like so: | With the option the green and blue part become united: |
![]() |
![]() |
| (3 cubes) | (2 overlapping cubes) |
Reccomended: ON
Pros:
- Reduces File Size
Cons:
- Slightly slower
- The cubes overlap generating too much overdraw (in some software this results in bad behaviour)
Behaviour when off:
This (8x8 square):
Becomes this on the texture map (8x8 square):
Behaviour when on:
This (8x8 square):
Becomes this on the texture map (1x1 square):
Reccomended: ON
Pros:
- Greatly reduces File Size
- Can use the next setting (pattern matching) at its fullest
Cons:
- Slightly slower
- Cannot manually modify the texture of the face since if you modify a pixel you modify all the face
If it is on each texture will be flipped, rotated (in every way possible) and then compared to each other if two are equal than both faces will share the same region on the texture map:
Recommended:ON
Pros:
- Greatly reduces File Size
Cons:
- Anything higher than 0 makes it way slower
- Cannot manually modify the texture of a face without modifying the texture of all the faces equal to that one.
This setting only works when you have materials (.vox files only), if there is glass then it generates more faces:
Reccomended: OFF
Pros:
- Glass has correct behaviour
Cons:
- Increased file size
- Slightly slower
This settings influence the way the mesh is exported
"precisions level" is the amount of digits after the dot in the output .obj file for each vt; in this image that number is 3: 
This is what happens if the digits precision is incorrect:
| 2 Digits precision | 3 Digits precision |
|---|---|
![]() |
![]() |
If the setting is off the program automatically detects the amount of digits otherwise you can specify it yourself.
By default:
| Width/Height | Digits after the dot | y* |
|---|---|---|
| 1 | 0 | 0 |
| 2 | 1 | 1 |
| 4 | 2 | 2 |
| 8 | 3 | 3 |
| 16 | 4 | 4 |
| 32 | 4 | 5 |
| 64 | 4 | 6 |
| 128 | 5 | 7 |
| 256 | 5 | 8 |
| 512 | 5 | 9 |
| 1024 | 6 | 10 |
| 2048 | 6 | 11 |
| 4096 <=x <=8192 | 6 | log₂(x) |
| 16384 <=x <=65536 | 7 | log₂(x) |
y*: Digits needed to write the full number without approximations (useful if you want the max precision without adding useless digits) **: The program works only with powers of 2 for textures
Reccomended: OFF
Pros if it is on:
- Manually set digits numbers
- more control
- Potentially more high quality
Pro if it is off:
- You don't have to manually set digits numbers
Defines the colour of the pixels not used but present in the texture map.
How to use it: If you have a small palette it can save a really small amount of disk space if you use as a background the same colour as one present in the palette.
Reccomended: OFF (doesn't really matter that much)/The same as the most used colour in the model
Based on the software you need to export to you may need to change the coordinate system, follow the table below:

Reccomended:
| Software | Y-UP | Right-handed |
|---|---|---|
| Blender | False | True |
| Unreal engine | False | False |
| Godot | True | True |
| Unity | True | False |
If you select it the model vertices will not have their position based on their magicavoxel position.
| off | on |
|---|---|
![]() |
![]() |
Pros:
- 2 meshes will have their positions relative one to the other when importing the mesh in other programs
Cons:
- Consumes a really tiny amount of disk space (especially if there are many small models created all over the place in magicavoxel)
If required by the software you need to export to then activate this setting.
If you notice weird lightning on the mesh then activate this setting.
Pros:
- The mesh is more accurate.
Cons:
- Consumes more disk space (6 bytes per face + 60 bytes to be exact).
If you enable this all models will have this texture 
correctly applied to each face.
If you enable this option three sliders will appear, the first represent a dilation of the final mesh on the X axis while the second one on the Y axis and the third one on the Z axis.
When writing to file vertices follow this format: "v X Y Z" when the size of the model is even (x: 2n, n∈ℝ), if it is odd (x: 2n+1, n∈ℝ) it follows this format: "v X.5 Y.5 Z.5" however when a custom scale is selected (for instance 0.1X, 0.1Y, 0.1Z) it becomes v X.x Y.y Z.z (increasing size on disk), however if and only if an odd integer number is selected then it always becomes "v X Y Z" thus decreasing size on disk
Pros:
- You can modify the Scale of the object before importing inside of other programs.
- You don't have to modify the scale for each mesh on an external program
- Might decrease Disk size
Cons:
- Might Increase Disk size
If it is not ON you might encounter meshes that appear to be correct but are way too big then what they need to be
The ply magicavoxel optimizes meshes when exporting such that a cube full inside is actually a cube empty inside but since you can't see it it doesn't matter except that it does if you have to compress it with this program.
Pros:
- Greatly reduces File Size
Cons:
- Slightly slower
Reccomended: ON
Some programs requires this setting to be on for the model to be displayed correctly because they need very precise UVs
| Off | On | Godot Setting |
|---|---|---|
![]() |
![]() |
![]() |
Pros:
- More Compatible or "Correct" meshes
Cons:
- Increases disk size because each Vt (see .obj documentation) holds 1 texture instead of being shared by 4 textures, increasing Vt count by at most a factor of 4
Reccomended: OFF (unless there are artifacts in your mesh)
These only matter when using .vox files
As the name sugggests it puts all the models in one big .obj, optimizing the output while doing so
If this is unselected the program will convert each nSHP (each model) utilizing threads (in parallel so it is faster). A new option will appear called detailed export name which chnges the name of the output by including the group the nSHP belongs to.
The output will be {FileName}{GroupName if detailed export name is enabled}{ObjName}_{CHUNK_ID}
Reccomended:ON
Pros:
- Smaller overall size
Cons:
- Increased RAM usage while optimizing
- Can't modify or use singular models because they are now all part of one
When you are working with magicavoxel you may change the visibility of objects or groups. With this option disabled the invisible objects aren't exported, in this way you can selectively choose which objects are exported.
This is useful when for example if you are building a big scene you might only want to export a small fraction of it.
Reccomended:OFF when MagicaVoxel scenes are huge
If all of these are ON this is what the .mtl looks like (Given a .vox project called GlassTest): 
and this is what the file structure looks like: 
If ON the program will attempt to use a smart algorithm for creating the emission map, creating a discrepancy between the albedo map and emission map.
If OFF and the material is emissive the colour on the emission map will be the same as in the albedo map (if not emissive it will be rgb[0,0,0] on the emission map)
WARNING: You might want to modify manually the emission map with another program (I'd suggest Slate, just download, extract, load _emit.png, click ctrl + A, go to image>adjustments>Hue/Saturation, modify, click ctrl + S) and the Alpha of the Albedo Map to make glass look more dense (You can do this as by changing The emission map but instead of hue/saturation you change opacity, for slate click the two checkbox and increase the slider).
Reccomended: Depends on your needs, overall only Transparency and Emission is fine
After the settings you should choose a directory where the output will be written to and then click the convert button. Once you are finished you are free to close the program. The program should notify you when it finishes, if it doesn't move the mouse or if too much time has passed retry but using the command prompt version of the software which you can find here: itch.io and if there is a panic message share the logs to me (davidevuffical@gmail.com).
To benchmark I'll use the .vox files that magicavoxel comes by default and I'll compare the .obj of magicavoxel with the .obj of my program
MV = magicavoxel, VO = voxeloptimizer
| Model Name | MV Export size | MV Export speed | VO Export Size | VO Export speed |
|---|---|---|---|---|
| 3x3x3 | 4.41kb | N/A | 2.8kb | 15ms |
| Lightsabers | 14.8kb | N/A | 6.5kb | 30ms |
| Castle+Chr_knight+Cars | 276.2kb | N/A | 102.6kb | 190ms |
| Doom | 632.1kb | N/A | 67.8kb | 213ms |
| Teapot | 2.82mb | About 3s | 1.27mb | 2.42s |
| Menger | 19.5mb | About 7s | 8.33mb | 15.8s |
VoxelOptimizer clearly beats Magicavoxel out of the water it is about two times as disk efficient (without accounting for the fact that they contain about 10x less faces) while unfortunately being slightly slower than Magicavoxel on large models, however being Multithreaded when there are multiple exports to do it means that exporting more models/projects is faster, VoxelOptimizer has also other advantages:
| MV | VO | |
|---|---|---|
| Converting multiple files at once | No | Yes |
| Exporting to one file | No | Yes |
| Exporting materials | No | Yes |
| Various coordinate systems | No | Yes |
| Normals | Yes | Yes |
| Customizability | No | Yes |
| Multithreaded for multipe models | No | Yes |
| Optimized for gamedev | No | Ye! |
In the benchmark folder of this repository you can find all of the data (.vox files, .ply files, my output, magicavoxel output).
I would be glad for any pull request, discussion, issues you have to make this program better.
License: you may modify and copy for private use the software but you cannot redistribute or sell it.
If you have any questions contact me at: davidevufficial@gmail.com














