A spritestack model is a ZIP file with two obligatory entries:
{
"fileType": "SpriteStackModelProject",
"title": "Whatever"
}
{
"formatVersion": 2,
"fileType": "SpriteStackModel",
"parts": [
{
"name": "Name of a part",
"data": [-3902, 0, -2, 2, -62, 0, -2, 2, -62, 0, -2, 2, -62, 0, -2, 2, -141218, 0],
"hidden": false
}
],
"size": [64, 64, 64],
"palette": [0, 2236468, 4532284, 6699313, 9393723, 14643494, 14262374, 15647642, 16777215, 16511542, 10085712, 6995504, 3642478, 4942127, 5393188, 3292217, 4145012, 3170434, 5992161, 6527999, 6278628, 13360124, 10202551, 8683143, 6908522, 5854802, 7750282, 11285042, 14243683, 14121914, 9410378, 9072432]
}
Currently only 64x64x64 size is supported. Even if your model is smaller put it within 64x64x64 space.
SpriteStack model is a set of equally sized cube spaces (parts) filled with voxels.
Data is an array of palette color indexes of each voxel.
0 means that the space is empty 1 means the palette index 0 2 means the palette index 1 ...
To safe space repeated indexes are folded using negative number to represent how many time the next value should be repeated
Let's decipher one array:
[-100, 0, 2, 3, 2, -7, 8]
Means:
100 x 0, 2, 3, 2, 7 x 8
sizeX, sizeY, sizeZ is a cube (model) size
Array (cube) index to 3D coordinates
function to3D(index) {
let x, y, z;
z = floor(index / (sizeX * sizeY));
index -= (z * sizeX * sizeY);
y = floor(index / sizeX);
x = index % sizeX;
return { x, y, z }
}
3D coordinates to array (cube) index
function to1D(x, y, z) {
return (z * sizeX * sizeY) + (y * sizeX) + x;
}
RGB to Number
function rgbToInt(r, g, b) {
return b + g * 256 + r * 65536;
}
Number to RGB
function intToRGB(color) {
return {
r: floor(color / 65536),
g: floor(color / 256) % 256,
b: color % 256
}
}
For anyone needing this boring conversion, here is a ready JS function that receives a SpriteStack model (the exported JSON) and returns an array of voxels (position and color):
Positions are centered on origin, so, for example, a 64x64x64 box ranges from -32 to 31.