Added VOX export
parent
c19ac61e8c
commit
80569a64c0
|
@ -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
|
||||
|
||||
```
|
||||
|
|
|
@ -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.
|
@ -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",
|
||||
|
|
|
@ -39,6 +39,7 @@ enum {
|
|||
INF_REMAP,
|
||||
INF_MAP,
|
||||
INF_MOD,
|
||||
INF_VOX,
|
||||
INF_OUT,
|
||||
LOADING,
|
||||
ERR_MEM,
|
||||
|
|
11
src/main.c
11
src/main.c
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue