Added VOX export

master
bzt 2020-01-31 22:46:59 +01:00
parent c19ac61e8c
commit 80569a64c0
10 changed files with 126 additions and 13 deletions

View File

@ -8,7 +8,7 @@ See also the [GUI usage](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/usag
```
MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
./mtsedit [-h] [-v] [-l lang] [-d|-p|-P|-b|-B] [-r remapfile] [-m map] <.mts|.schematic> [out.mts]
./mtsedit [-h] [-v] [-l lang] [-d|-p|-P|-b|-B|-V] [-r remapfile] [-m map] <.mts|.schematic|.tmx|.gox|.vox|.qb> [out.mts]
./mtsedit [-G|-C|-T]
./mtsedit -g <block.png>
./mtsedit -t <blockimgs.csv> [blockid]
@ -25,6 +25,7 @@ MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
-g: generate slab and stairs from block image
-t: generate block images from texture data
-i: install Minetest mod
-V: output to VOX
out.mts: output to file
```
@ -39,10 +40,14 @@ This will print out mapping and each block as hex values layer by layer.
```
./mtsedit -d structure.mts
```
Also works with all the supported [input formats](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/import.md), for example:
```
./mtsedit -d structure.schem
```
### Generate Blueprint
### Generate BluePrint
Pretty much the same as dump, but instead of dumping the MTS to the console, it saves "structure_bp.png".
Pretty much the same as dump, but instead of dumping the structure to the console, it saves "structure_bp.png".
```
./mtsedit -b structure.mts
```
@ -91,6 +96,18 @@ tile, use the name "Air".
If you have used Minecraft NBT IDs in the input file, then remapping is unnecessary.
### Converting to VOX
Normally convertion creates only MTS files. But to support bidirectional workflows, MTSEdit can write VOX files too using `-V`.
```
./mtsedit -V structure.mts structure.vox
```
Note that VOX files will loose a lot of schematic's details (node names, rotation info, probabilities, force placement etc.), but
at least you will be able load the structure in Goxel and Magicavoxel. When saved, you can convert VOX (or GOX) files back to MTS:
```
./mtsedit structure.vox structure.mts
```
### Generate Preview
```

View File

@ -33,7 +33,7 @@ Sponge Schematic Files
----------------------
These are [Minecraft NBT](https://minecraft.gamepedia.com/Schematic_file_format) files too, used by WorldEdit. Typical extension
is `.schematic` too. Instead of Blocks and Data chunks, these have [BlockData](https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-2.md)
is `.schematic` too, or sometimes `.schem`. Instead of Blocks and Data chunks, these have [BlockData](https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-2.md)
and Palette chunks. Although BlockData is a byte array, it contains bigger than 255 values using some messed up "varint" encoding.
Limitations: rotation info are not imported at all.
@ -86,6 +86,9 @@ Used by [Magicavoxel](https://ephtracy.github.io). Typical extension is `.vox`.
the same limitations apply. They are not perticularly good for storing schematics, as nodes has to be matched by color some nodes
might be incorrectly identified.
To aid workflow in both ways, as an exception MTSEdit can convert to VOX files too. This is the only format that's written which
is not MTS.
Limitations: this format can't store nodes, nor rotation info, only colorized voxels. This is a voxel image format, not a true
schematic format.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -46,6 +46,7 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"remap numeric ids in input",
"replace block type mapping",
"install Minetest mod",
"output to VOX",
"output to file",
"Loading...",
"Memory allocation error",
@ -127,6 +128,7 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"bemeneti fájl numerikus azonostóinak lecserélése",
"lecseréli a palettát",
"Minetest mod telepítése",
"VOX lementése",
"kimenet lementése",
"Betöltés...",
"Memória foglalási hiba",
@ -208,6 +210,7 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"reasignar identificadores numéricos en la entrada",
"reemplazar el mapeo de tipo de bloque",
"instalar Minetest mod",
"salida a VOX archivo",
"salida a archivo",
"Cargando...",
"Error de asignación de memoria",
@ -289,6 +292,7 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"remapper les identifiants numériques en entrée",
"remplacer la correspondance de type de bloc",
"installer le mod Minetest",
"sortie dans un VOX fichier",
"sortie dans un fichier",
"Chargement...",
"Erreur d'allocation de mémoire",
@ -370,6 +374,7 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"Ordnen Sie numerische IDs in der Eingabe neu zu",
"Blocktypzuordnung ersetzen",
"installiere Minetest mod",
"speichern VOX Datei",
"speichern Datei",
"Wird geladen...",
"Speicherzuordnungsfehler",
@ -451,6 +456,7 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"mapuj identyfikatory numeryczne na wejściu",
"zastąpić mapowanie typów bloków",
"zainstaluj Minetest mod",
"wyjście do pliku VOX",
"wyjście do pliku",
"Ładuję...",
"Błąd przydziału pamięci",
@ -532,6 +538,7 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"переназначить числовые идентификаторы на входе",
"заменить отображение типа блока",
"установить мод Minetest",
"вывод в файл VOX",
"вывод в файл",
"Загрузка ...",
"Ошибка выделения памяти",
@ -613,6 +620,7 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"remapear IDs numéricos na entrada",
"substituir o mapeamento do tipo de bloco",
"instalar mod Minetest",
"saída para VOX arquivo",
"saída para arquivo",
"Carregando...",
"Erro de alocação de memória",
@ -694,6 +702,7 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"rimappa gli ID numerici nell'input",
"sostituire la mappatura del tipo di blocco",
"installa Minetest mod",
"output su VOX file",
"output su file",
"Caricamento in corso...",
"Errore di allocazione della memoria",

View File

@ -39,6 +39,7 @@ enum {
INF_REMAP,
INF_MAP,
INF_MOD,
INF_VOX,
INF_OUT,
LOADING,
ERR_MEM,

View File

@ -175,15 +175,15 @@ int main(int argc, char** argv, char** envp)
if(argc < 2) {
usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license\r\n\r\n"
"./mtsedit [-h] [-v] [-l lang] [-d|-p|-P|-b|-B] [-r remapfile] [-m map] <schematic> [out.mts]\r\n"
"./mtsedit [-h] [-v] [-l lang] [-d|-p|-P|-b|-B|-V] [-r remapfile] [-m map] <schematic> [out.mts]\r\n"
"./mtsedit [-G|-C|-T]\r\n"
"./mtsedit -g <block.png>\r\n"
"./mtsedit -t <blockimgs.csv> [blockid]\r\n"
"./mtsedit -i [Minetest mods dir]\r\n"
"\r\n -v: %s\r\n -l lang: %s\r\n -d: %s\r\n -p: %s\r\n -P: %s\r\n -b, -B: %s\r\n -r remapfile: %s\r\n"
" -m map: %s\r\n -g: %s\r\n -t: %s\r\n -i: %s\r\n out.mts: %s\r\n",
" -m map: %s\r\n -g: %s\r\n -t: %s\r\n -i: %s\r\n -V: %s\r\n out.mts: %s\r\n",
lang[INF_VERB], lang[INF_LANG], lang[INF_DUMP], lang[INF_PRE1], lang[INF_PRE2], lang[INF_BPRINT], lang[INF_REMAP],
lang[INF_MAP], lang[INF_GEN], lang[INF_BLK], lang[INF_MOD], lang[INF_OUT]);
lang[INF_MAP], lang[INF_GEN], lang[INF_BLK], lang[INF_MOD], lang[INF_VOX], lang[INF_OUT]);
exit(0);
}
for(i = j = 1; j < argc; j++) {
@ -199,6 +199,7 @@ usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
case 't': opt = 6; break;
case 'i': opt = 7; break;
case 'm': if(!opt) { opt = 8; } newmap = argv[++j]; i++; break;
case 'V': opt = 9; break;
case 'r': remapfile = argv[++j]; i++; break;
case 'l': j++; i++; break;
case 'G': gimppal(); return 0; break;
@ -236,7 +237,7 @@ usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
mts_x = mts_y = mts_z = 0;
if(i+1 < argc && argv[i+1] && !opt) opt = 8;
if(opt && (opt < 5 || opt == 8)) {
if(opt && (opt < 5 || opt >= 8)) {
blocks_parse();
readschem();
if(!mts_y || !mts_y || !mts_x)
@ -257,7 +258,7 @@ usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
} else
#endif
strncpy(mtsfile, argv[i+1], sizeof(mtsfile) - 1);
ret = mts_save();
ret = opt == 9 ? vox_save() : mts_save();
}
}
switch(opt) {

View File

@ -213,6 +213,7 @@ void m3d_load(unsigned char *data, unsigned int size);
void tmx_load(unsigned char *data, unsigned int size);
void gox_load(unsigned char *data, unsigned int size);
void vox_load(unsigned char *data, unsigned int size);
int vox_save();
void qb_load(unsigned char *data, unsigned int size);
/* mts.c */

View File

@ -588,8 +588,8 @@ void vox_load(unsigned char *data, unsigned int size)
pal[0] = 0;
} else
if(!memcmp(s, "XYZI", 4)) {
siz = *((uint32_t*)(s + 4)) / 4;
s += 12;
siz = (*((uint32_t*)(s + 4)) / 4) - 1;
s += 16;
for(i = 0; i < siz; i++, s += 4) {
if(s[0] < mi_x) mi_x = s[0];
if(s[0] > ma_x) ma_x = s[0];
@ -621,8 +621,8 @@ void vox_load(unsigned char *data, unsigned int size)
/* read in the layers (possibly from multiple chunks) */
for(s = data + 20; s < e; s++) {
if(!memcmp(s, "XYZI", 4)) {
siz = *((uint32_t*)(s + 4)) / 4;
s += 12;
siz = (*((uint32_t*)(s + 4)) / 4) - 1;
s += 16;
for(i = 0; i < siz; i++, s += 4) {
x = s[0] - mi_x;
z = s[1] - mi_z;
@ -643,6 +643,87 @@ void vox_load(unsigned char *data, unsigned int size)
status = lang[LOADED];
}
/**
* Save a Magicavoxel VOX file (this is an exception to support bidirectional workflows)
*/
int vox_save()
{
char outfile[MAXPATHLEN], *c;
unsigned short *tr, *tr2;
unsigned char hdr[12 + 1024];
int i, j, n = 0, x, y, z;
FILE *f;
status = lang[ERR_SAVE];
tr = (unsigned short*)malloc(numblocks * sizeof(unsigned short));
if(!tr) error(lang[ERR_MEM]);
memset(tr, 0, numblocks * sizeof(unsigned short));
tr2 = (unsigned short*)malloc(numblocks * sizeof(unsigned short));
if(!tr2) error(lang[ERR_MEM]);
memset(tr2, 0, numblocks * sizeof(unsigned short));
j = mts_getbounds(1, tr, tr2);
if(mix > max) { free(tr); free(tr2); return 1; }
for(y = miy; y <= may; y++)
for(z = miz; z <= maz; z++)
for(x = mix; x <= max; x++)
if(nodes[y][z][x].param0) n++;
/* get filename, buffer and open file */
strcpy(outfile, mtsfile);
c = strrchr(outfile, '.');
if(!c) c = &outfile[strlen(outfile)];
strcpy(c, ".vox");
f = fopen(outfile,"wb");
if(!f) return 1;
/* write header */
memcpy(hdr, "VOX ", 4);
*((uint32_t*)(hdr+4)) = 150;
memcpy(hdr + 8, "MAIN", 4);
*((uint32_t*)(hdr+12)) = 0;
*((uint32_t*)(hdr+16)) = 40 + n*4 + 1036;
memcpy(hdr + 20, "SIZE", 4);
*((uint32_t*)(hdr+24)) = 12;
*((uint32_t*)(hdr+28)) = 0;
*((uint32_t*)(hdr+32)) = max-mix+1;
*((uint32_t*)(hdr+36)) = may-miy+1;
*((uint32_t*)(hdr+40)) = maz-miz+1;
memcpy(hdr + 44, "XYZI", 4);
*((uint32_t*)(hdr+48)) = n*4 + 4;
*((uint32_t*)(hdr+52)) = 0;
*((uint32_t*)(hdr+56)) = n;
fwrite(hdr, 60, 1, f);
/* write data */
for(y = miy; y <= may; y++)
for(z = miz; z <= maz; z++)
for(x = mix; x <= max; x++)
if(nodes[y][z][x].param0) {
hdr[0] = x - mix;
hdr[1] = maz - z;
hdr[2] = y - miy;
hdr[3] = tr2[nodes[y][z][x].param0];
fwrite(hdr, 4, 1, f);
}
/* write palette */
memset(hdr, 0, sizeof(hdr));
memcpy(hdr, "RGBA", 4);
for(i = 0; i < j; i++)
memcpy(hdr + 8 + i * 4, &blocks[tr[i]].color, 4);
*((uint32_t*)(hdr+4)) = 1024;
*((uint32_t*)(hdr+8)) = 0;
fwrite(hdr, 12+1024, 1, f);
status = lang[SAVED];
fclose(f);
free(tr);
free(tr2);
return 0;
}
/**
* Load a Qubicle QB file
*/