Skip to content

Instantly share code, notes, and snippets.

@haxiomic
Last active August 29, 2015 14:20
Show Gist options
  • Save haxiomic/0a47f77b5cadc29e248c to your computer and use it in GitHub Desktop.
Save haxiomic/0a47f77b5cadc29e248c to your computer and use it in GitHub Desktop.
voxel flatten
function createSliceTexture(vox:Vox, axis:Int = 0, ?params:TextureParams, maxW:Null<Int> = 4096, POT:Bool = true):SliceTexture{
if(params == null) params = {};
var defaultParams = {
channelType: GL.RGBA,
dataType: GL.UNSIGNED_BYTE,
filter: GL.LINEAR,
wrapS: GL.CLAMP_TO_EDGE,
wrapT: GL.CLAMP_TO_EDGE,
unpackAlignment: TextureTools.defaultParams.unpackAlignment
};
//extend default params
for(f in Reflect.fields(defaultParams))
if(!Reflect.hasField(params, f))
Reflect.setField(params, f, Reflect.field(defaultParams, f));
//clamp
axis = Math.floor(Math.min(3, Math.max(0, axis)));
//determine how to fit slices to texture
if(maxW == null){
maxW = GL.getParameter(GL.MAX_TEXTURE_SIZE);
}else{
maxW = Math.floor(Math.min(maxW, GL.getParameter(GL.MAX_TEXTURE_SIZE)));
}
//fit width first then fit height
var nSlices:Int = 0;
var sliceW:Int = 0;
var sliceH:Int = 0;
switch axis{
case 0://xzy
nSlices = vox.size.x;
sliceW = vox.size.z;
sliceH = vox.size.y;
case 1://yxz
nSlices = vox.size.y;
sliceW = vox.size.x;
sliceH = vox.size.z;
case 2://zxy
nSlices = vox.size.z;
sliceW = vox.size.x;
sliceH = vox.size.y;
}
//how many slices can fit within maxW
//if remainder, what's the nearest ceiling POT?
var nCols:Int = Math.floor(maxW / sliceW);
var nRows:Int = Math.ceil(nSlices / nCols);
if(nRows <= 1) nCols = nSlices;
var width = nCols * sliceW;
var height = nRows * sliceH;
var textureWidth = POT ? MathTools.upperPowerOf2(width) : width;
var textureHeight = POT ? MathTools.upperPowerOf2(height) : height;
var texture = TextureTools.createTexture(textureWidth, textureHeight, params);
//generate texture
var nChannels:Int = switch params.channelType{
case GL.RGBA: 4;
case GL.RGB: 3;
case GL.ALPHA: 1;
case GL.LUMINANCE: 1;
case GL.LUMINANCE_ALPHA: 2;
default: 4;
}
var pixelData = new Array<Int>();
//write zeros
for(i in 0...textureWidth * textureHeight * nChannels){
pixelData[i] = 0;
}
inline function getIndex(x:Int, y:Int):Int{
return (y * textureWidth + x) * nChannels;
}
inline function setPixel(x:Int, y:Int, data:Array<Int>){
var i = getIndex(x, y);
var j = 0;
while(j < nChannels){
pixelData[i + j] = data[j];
j++;
}
}
var col:VoxReader.RGBA;
/*inline*/ function getColorArray(v:VoxReader.Voxel):Array<Int>{
col = vox.palette[v.colorIndex - 1];
//@!tmp quick hack to reduce alpha without editing the .vox
var reducedAlpha = Math.round(col.a * 0.1);
return [col.r, col.g, col.b, reducedAlpha];
}
var offsetX:Int, offsetY:Int, px:Int, py:Int, i:Int;
switch axis {
case 0: for(v in vox.voxels){
offsetX = (v.x % nCols) * sliceW;
offsetY = Math.floor(v.x / nCols) * sliceH;
px = v.z + offsetX;
py = v.y + offsetY;
setPixel(px, py, getColorArray(v));
}
case 1: for(v in vox.voxels){
offsetX = (v.y % nCols) * sliceW;
offsetY = Math.floor(v.y / nCols) * sliceH;
px = v.x + offsetX;
py = v.z + offsetY;
setPixel(px, py, getColorArray(v));
}
case 2: for(v in vox.voxels){
offsetX = (v.z % nCols) * sliceW;
offsetY = Math.floor(v.z / nCols) * sliceH;
px = v.x + offsetX;
py = v.y + offsetY;
setPixel(px, py, getColorArray(v));
}
}
//write data to texture
GL.bindTexture (GL.TEXTURE_2D, texture);
GL.texImage2D(GL.TEXTURE_2D, 0, params.channelType, textureWidth, textureHeight, 0, params.channelType, params.dataType, new Uint8Array(pixelData));
GL.bindTexture(GL.TEXTURE_2D, null);
var info = {
sliceW: sliceW,
sliceH: sliceH,
sliceD: nSlices,
nSlicesPerRow: nCols,
nSlices: nSlices,
textureW: textureWidth,
textureH: textureHeight
};
return {
texture: texture,
info: info
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment