Closed acs closed 4 years ago
Related to this one: https://github.com/juntosdesdecasa/mcthings/issues/100
Maybe we should extend:
https://gitlab.com/bztsrc/mtsedit/blob/master/docs/batch.md
so it exports Schematic format. And that's all!
Add a
-S: output to Schematic
It is implemented in C language, like GNOME :)
vox has several importers at:
https://github.com/Zarbuz/FileToVox
So the writting of vox files is well covered here.
And probably also the reading if they have good tests. It is implemented in C# and here we have the reader and writer:
https://github.com/Zarbuz/FileToVox/tree/master/SchematicToVoxCore/Vox
In this tool, it seems all the formats are comnverted to Schematics and the Schematics is converted to Vox. In McThings, my guess is that we will use also Schematics format as the common one. Why? Becase it has solid tools to process it (NBTtools) and the format is simple and flexible and complete.
The writing to vox format seems to be pretty easy:
https://gitlab.com/bztsrc/mtsedit/-/commit/80569a64c0c91080699f46fd9a1302b14b1847b2
and it uses the Y, X, Z order as in schematics.
it is writing a header, the data and the palette. If it is so easy to do, probably we can just implement it from scratch and later, create a library with support for reading and writing VOX files like the NBT library.
The process for a guy doing the same for Three.js: https://luciopaiva.com/magicavoxel-threejs-howto/
VOX uses RIFF format, and in Python there is a module built-in for reading this kind of data:
https://docs.python.org/3.8/library/chunk.html
Great!
So we can do a clean job reading and writing VOX files.
So my conclusion is that VOX format is so easy to read and write that:
So we have a plan!
The name of the first library was vox-io. Not bad. I will use voxpy probably.
https://github.com/RichysHub/MagicaVoxel-VOX-importer Blender importer for VOX format implemented in Python. A good reference.
And also in https://github.com/jpaver/opengametools they have a reader and writter implemented in C++ based on a vox parser C++ library.
Some experiences supporting the new format:
https://github.com/RichysHub/MagicaVoxel-VOX-importer/issues/6
A very useful command to see the structure of the vox file:
(venv) strings vxs.vox
VOX
MAIN
SIZE
XYZI
nTRN
nGRP
nTRN-
-1 -1 2nSHP
LAYR
_name
LAYR
_name
LAYR
_name
LAYR
_name
LAYR
_name
LAYR
_name
LAYR
_name
LAYR
_name
RGBA
MATL
_type
_diffuse
_weight
_rough
_spec
_spec_p
_ior
_att
-0.5
_flux
_ldr
0MATL
....
The proposed reading process for chunks in python lib:
«Usually an IFF-type file consists of one or more chunks. The proposed usage of the Chunk class defined here is to instantiate an instance at the start of each chunk and read from the instance until it reaches the end, after which a new instance can be instantiated. At the end of the file, creating a new instance will fail with an EOFError exception.»
Let's try to follow it! Start a new chunk given the position of the chunk on the file.
A nice example doing just that here: https://www.programcreek.com/python/example/93077/chunk.Chunk
The key is to create Chunk with the file positioned correctly for reading the next chunk. Part of:
https://github.com/pyblish/pyblish-win/blob/master/lib/Python27/Lib/wave.py
And indeed this is a pretty interesing project: https://pyblish.com/ «Pyblish is what enables our artists to focus more on the artistic barrier of raising quality instead of the technical one whilst maintaining a pipeline that raises the bar for both.»
Ok, let's try to describe at high level the format in the current version of the file (vox-extension) using the strings command output.
So if we want to load 1 model and only the cubes, our focus must be the Model Chunk:
5. Chunk id 'SIZE' : model size
-------------------------------------------------------------------------------
# Bytes | Type | Value
-------------------------------------------------------------------------------
4 | int | size x
4 | int | size y
4 | int | size z : gravity direction
-------------------------------------------------------------------------------
6. Chunk id 'XYZI' : model voxels
-------------------------------------------------------------------------------
# Bytes | Type | Value
-------------------------------------------------------------------------------
4 | int | numVoxels (N)
4 x N | int | (x, y, z, colorIndex) : 1 byte for each component
-------------------------------------------------------------------------------
and the palette
7. Chunk id 'RGBA' : palette
-------------------------------------------------------------------------------
# Bytes | Type | Value
-------------------------------------------------------------------------------
4 x 256 | int | (R, G, B, A) : 1 byte for each component
| * <NOTICE>
| * color [0-254] are mapped to palette index [1-255], e.g :
|
| for ( int i = 0; i <= 254; i++ ) {
| palette[i + 1] = ReadRGBA();
| }
-------------------------------------------------------------------------------
In the first iteration the goal is to support the last version of the format, but probably, it is easy to support older formats.
Great, it seems it is going to be easy and clean to support VOX format. The code is taking shape at:
https://github.com/acs/mcthings/blob/99-vox2schematics/mcthings/vox.py
Great, it is a bit tricky to use the chunk python lib to read the vox file, but once I know how to do it, it will be much maintainable having the Chunk concept supported in the logic. 2h aprox to have a first working version.
Ok, now we can read the blocks and the colors from a MagicaVoxel file. Cool! Now it is time to map it to Minecraft. And this is a tough problem because we don't have all colors in Minecraft. Using wool we can replicate partially the colors.
https://www.stuffaboutcode.com/p/minecraft-api-reference.html
Data Values of blocks: WOOL: 0: White 1: Orange 2: Magenta 3: Light Blue 4: Yellow 5: Lime 6: Pink 7: Grey 8: Light grey 9: Cyan 10: Purple 11: Blue 12: Brown 13: Green 14: Red 15: Black
So we need to map the RGBA colors to this ones. The best thing is to have a Minecraft palette in MagicaVoxel to create the models using them. In this case, let's do a hack:
ee 00 00 is 14.
Ok, here we go:
from
Colors from 15 to 0:
we need to create a magicavoxel palette with them (we need the hex codes for them).
COLORS = [
"White",
"Orange",
"Magenta",
"Light Blue",
"Yellow",
"Lime",
"Pink",
"Grey",
"Light grey",
"Cyan",
"Purple",
"Blue",
"Brown",
"Green",
"Red",
"Black"
]
https://gaming.stackexchange.com/questions/47212/what-are-the-color-values-for-dyed-wool
• White - FFe4e4e4 • Orange - FFea7e35 • Magenta - FFbe49c9 • Light Blue - FF6387d2 • Yellow - FFc2b51c • Lime Green - FF39ba2e • Pink - FFd98199 • Dark Gray - FF414141 • Light Gray - FFa0a7a7 • Cyan - FF267191 • Purple - FF7e34bf • Blue - FF253193 • Brown - FF56331c • Green - FF364b18 • Red - FF9e2b27 • Black - FF181414
So our next step is to create a palette in MagicaVoxel with this colors.
But before working at the color detail, let's check all is working with some models in vox format.
One of our goals is to support the loading of:
https://github.com/mikelovesrobots/mmmm
And maybe this is the old version format. The goal is to support it also. So let's work on that.
Let's play with this one wich is 8 (z) x 4 (x) x 11 (y): 332 blocks. alien_engi1a
It has 4 colors: blue, black, gray and light gray. So an accurate job could be done!
It is a 6 years old model, and I love to support this old models!!! Let's do it :100:
The old format is simpler:
(venv) strings alien_engi1a.vox
VOX
MAIN
SIZE
XYZI
RGBA
To check the correct loading of the palette we can do it in MV. For each palette there are 32 * 8 = 256 colors.
And we can check the colors in MV:
To check the full palette:
In this palette the first color is (index 1): ffffff . The index 2: ffffcc. index 3: ffff99.
and the last color is index 255 is 111111. The 249 is aaaaaa (256 can not be selected and it is not part of the palette). So the palette goes from 0 to 254 (at least in the old version).
¿Is that the default one? I think so (but in the file, index 1 is 000000, and the colors are in different order: ffff99 is 99ffff.
Let's check that we are reading the palette correctly (I am pretty sure there are no issues with the blocks).
The results are promising.
As expected we need to fix the colors. But we are in the right path!
Ok, before putting all focus in the colors transformation, let's try to conversion to Schematic. This is something already available in McThings, so just testing the plumbing.
The goal is to generate the Voxelers logo as a Schematic.
Loaded from a Schematic. For some reason we are exporting 24 blocks instead of 6. We need to review it, but it is working in the dev branch for vox support.
The problem is "x-axis" that must be 1 and it is 4. I will recheck it.
So the problem is the self.position. If we use init_pos and end_pos for schematic extraction, it will work. But why self.position is not init_pos? Let's review.
It is working nicely. Why? Let's take a look to MV:
The position of z is +3, x +1 and y +0- So the blocks go from z:0, 2 x:0, 3 y:0,1 (3 x 4 x 2 = 24). So the schematic is perfect. In order to avoid the offset, we need to create in MV without offset.
And using this vox model we get in the schematic:
2020-06-29 05:51:12,466 Schematic: Exporting blocks: 6
And we get the right number of blocks (3 empty blocks, and 3 red blocks)
Ok, time to create our Minecraft wool palette for MV.
https://gaming.stackexchange.com/questions/47212/what-are-the-color-values-for-dyed-wool
• White - e4e4e4
• Orange - ea7e35
• Magenta - be49c9
• Light Blue - 6387d2
• Yellow - c2b51c
• Lime Green - 39ba2e
• Pink - d98199
• Dark Gray - 414141
• Light Gray - a0a7a7
• Cyan - 267191
• Purple - 7e34bf
• Blue - 253193
• Brown - 56331c
• Green - 364b18
• Red - 9e2b27
• Black - 181414
Mostly we have it! It is flipped but this should be easy to fix.
Ok, just pending:
In order to fix the flip issue, the best approach is to implement the flip operation in mcthings: https://github.com/Voxelers/mcthings/issues/112
But we have not a flip issue. It is just to look to the wall from the right side (the same side we use in MV).
But, is it the same for the alien robot? No
And we have the same issue when going through vox->obj->binvox->schematic
The problem is that in general x grows in this direction >--->---> but in MC it grows in <----<-----< (and the same for z). So we need to flip.
Much better now with the flip operation implemented.
Ok, let's play with colors and then review code, improve tests, prepare demos and implement the command line tool and disseminate.
Let's try to reproduce the alien colors in Minecraft. For doing it:
This is a general workflow to be done each time you want to have valid colors inside Minecraft.
Also, we can add more colors using other blocks in Minecraft:
But first, let's check if flip_z is needed also. And let's do it by default when loading VOX data for both use cases. Let's play with the model veh_ambulance.vox:
Ok, it seems there are no flipping issues in z-axis. Let's try to recreate the ambulance colors.
For doing it, let's use the MC palette y MV.
To the left the original one, to the right using the MC wool colors:
and the result in MC:
The dark gray wool is getting red wool for some reason. But the rest of the colors are ok. Bug found: the grey in this region is not the MC one, but the empty one without color!
Ok, just pending:
vox2schematic:
In the first version that's all. In new version we can add an optional map from MV colors to MC blocks/wool colors.
The tool will work from memory version of the models, so it must be pretty fast. Test it with the 400 models from Mike.
Goals:
Ok, let's create the tool: vox2schematic. At some point it could be also interesting the schematic2vox, but I think it is less interesting.
Ok, right now we are collecting the data in build_schematic_nbt from the data in the renderer. But this information is available in memory also, because we are using the Minecraft format for the memory schemas. So we need to have at least a method build_schematic_nbt_from_memory that uses the data in memory and that does not try to collect the data from the renderer.
But we are pretty close to have the feature implemented.
Ok, the script is working:
(venv) bin/vox2schematic.py ~/devel/mmmm/vox/obj_house6.vox -o tests/schematics/obj_house6.schematic
It is slow, but increase the performace should be easy to reach a reasonable performance.
For example, with this house with 78336 blocks, it has not finished yet after 5 minutes. So let's implement the first improvement.
Fixed the performance issue:
(venv) bin/vox2schematic.py ~/devel/mmmm/vox/obj_house6.vox -o tests/schematics/obj_house6.schematic
2020-07-02 19:12:20,855 Vox input file: /home/adelcastillo/devel/mmmm/vox/obj_house6.vox
2020-07-02 19:12:20,855 Schematic output file: tests/schematics/obj_house6.schematic
2020-07-02 19:12:22,006 Schematic: Exporting blocks: 78336
2020-07-02 19:12:22,053 Creating the memory cache with positions
2020-07-02 19:12:22,119 Done memory cache with positions
2020-07-02 19:12:22,552 Schematic export finished in 0.55 secs
and the schematic result is ...
5 minutes investment colouring the house:
and the result in Minecraft:
(venv) bin/vox2schematic.py ~/devel/voxels/MagicaVoxel-0.99.5.1-win64/export/obj_house6-mc.vox -o tests/schematics/obj_house6-mc.schematic
....
voxel_color = self.palette[voxel.color_index]
IndexError: list index out of range
Found a bug. Let's fix it! The format of the file is different, We need to improve our parser. The problem is that for some reason during colouring two models were created. Right now, only one model is supported. Fixed.
And the result house:
The main issue with this house is that it is for giants. So it is not at the right dimension for MC. So we need to work in MV at a smaller scale so the creations are natural inside the MC world. But this can be done. But it is a new way to create inside MV: for Minecraft. And also, the models are filled, so the house is a thick block.
So this kind of models are not useful in Minecraft to interact with them. So the question is .... is it better to create in MV that inside MC directly? My guess is that yes, but we need to improve the MC blocks can be used inside MV, and there are things that will be done better inside MC.
Ok, so next steps:
Tool included in 0.51.1 and working.
Next step is to put focus in the tests!!
About the tool, we need to capture the exceptions if the format is not the expected one: only one model for legacy and current format.
Hay muchos conversores de otros formatos a VOX (https://github.com/Eisenwave/voxel-io y otros proyectos), así que todos ellos los podríamos llevar a Minecraft.
More repos with models to test the conversor: https://www.mediafire.com/folder/a0znmricqxlkz/Free_Voxels
Should we add the multi model support? Probably not in the first iteration: it is complex to have useful results with complete scenes ... but it is pretty alignet with McThings. The scene could be broken in schematics and added individually.
Probably if we can not convert a color to the right Minecraft one, it is better to leave the block as a grey one (or stone or a fixed block).
Ok, next steps:
Using an improved version of the automatic coloring based on the above proposal the results are:
This tool must be used to import voxels and meshes into McThings (schematics format).
https://github.com/ephtracy/voxel-model/blob/master/MagicaVoxel-file-format-vox.txt https://github.com/ephtracy/voxel-model/blob/master/MagicaVoxel-file-format-vox-extension.txt
The primary goal is to import from vox format fo schematic. For that: