package com.vitco.export; import com.vitco.core.data.Data; import com.vitco.core.data.container.Voxel; import com.vitco.layout.content.console.ConsoleInterface; import com.vitco.settings.DynamicSettings; import com.vitco.util.components.progressbar.ProgressDialog; import com.vitco.util.file.FileOut; import com.vitco.util.misc.ByteHelper; import java.io.File; import java.io.IOException; /** * Exporter into *.qb (Qubicle 1.0) */ public class QbExporter extends AbstractExporter { // constructor public QbExporter(File exportTo, Data data, ProgressDialog dialog, ConsoleInterface console) throws IOException { super(exportTo, data, dialog, console); } // decide whether to use weighted center or origin (default) private boolean useCompression = true; public void setUseCompression(boolean flag) { useCompression = flag; } private boolean useBoxAsMatrix = false; public void setUseBoxAsMatrix(boolean useBoxAsMatrix) { this.useBoxAsMatrix = useBoxAsMatrix; } private boolean useOriginAsZero = true; public void setUseOriginAsZero(boolean useOriginAsZero) { this.useOriginAsZero = useOriginAsZero; } private boolean useVisMaskEncoding = true; public void setUseVisMaskEncoding(boolean useVisMaskEncoding) { this.useVisMaskEncoding = useVisMaskEncoding; } private boolean useRightHandedZAxisOrientation = true; public void setUseRightHandedZAxisOrientation(boolean useRightHandedZAxisOrientation) { this.useRightHandedZAxisOrientation = useRightHandedZAxisOrientation; } private static final int CODE_FLAG = 2; private static final int NEXT_SLICE_FLAG = 6; private static final int TRANSPARENT_VOXEL = 0x00000000; // write the file @Override protected boolean writeFile() throws IOException { // version fileOut.writeIntRev(257); // color format fileOut.writeIntRev(0); // z axis orientation fileOut.writeIntRev(this.useRightHandedZAxisOrientation ? 1 : 0); int ax1 = this.useRightHandedZAxisOrientation ? 0 : 2; int ax2 = this.useRightHandedZAxisOrientation ? 2 : 0; // compressed fileOut.writeIntRev(this.useCompression ? 1 : 0); // vis mask encoding fileOut.writeIntRev(this.useVisMaskEncoding ? 1 : 0); Integer[] layers = data.getLayers(); // num matrices fileOut.writeIntRev(layers.length); for (int i = layers.length - 1; i >= 0; i--) { Integer layerId = layers[i]; // write layer name String layerName = data.getLayerName(layerId); fileOut.writeByte((byte) layerName.length()); fileOut.writeASCIIString(layerName); int[][] meta = get_meta(layerId); int[] min = meta[0]; int[] max = meta[1]; int[] size = meta[2]; // write size fileOut.writeIntRev(size[ax1]); fileOut.writeIntRev(size[1]); fileOut.writeIntRev(size[ax2]); // write minimum fileOut.writeIntRev(this.useOriginAsZero ? min[ax1] : 0); fileOut.writeIntRev(this.useOriginAsZero ? -max[1] : 0); fileOut.writeIntRev(this.useOriginAsZero ? min[ax2] : 0); int currentColor = TRANSPARENT_VOXEL; int count = 0; for (int c1 = min[ax2]; c1 <= max[ax2]; c1++) { for (int y = max[1]; y >= min[1]; y--) { for (int c2 = min[ax1]; c2 <= max[ax1]; c2++) { int x = this.useRightHandedZAxisOrientation ? c2 : c1; int z = this.useRightHandedZAxisOrientation ? c1 : c2; Voxel voxel = data.searchVoxel(new int[]{x, y, z}, layerId); int newColor; if (voxel == null) { newColor = TRANSPARENT_VOXEL; } else { byte visible = 1; if (this.useVisMaskEncoding) { if (data.searchVoxel(new int[]{x - 1, y, z}, layerId) == null) { visible = ByteHelper.setBit(visible, this.useRightHandedZAxisOrientation ? 5 : 1); } if (data.searchVoxel(new int[]{x + 1, y, z}, layerId) == null) { visible = ByteHelper.setBit(visible, this.useRightHandedZAxisOrientation ? 6 : 2); } if (data.searchVoxel(new int[]{x, y + 1, z}, layerId) == null) { visible = ByteHelper.setBit(visible, 3); } if (data.searchVoxel(new int[]{x, y - 1, z}, layerId) == null) { visible = ByteHelper.setBit(visible, 4); } if (data.searchVoxel(new int[]{x, y, z - 1}, layerId) == null) { visible = ByteHelper.setBit(visible, this.useRightHandedZAxisOrientation ? 2 : 5); } if (data.searchVoxel(new int[]{x, y, z + 1}, layerId) == null) { visible = ByteHelper.setBit(visible, this.useRightHandedZAxisOrientation ? 1 : 6); } } newColor = voxel.getColor().getRGB(); newColor = ((this.useVisMaskEncoding ? visible : 0xFF) << 24) | (newColor & 0x000000FF) << 16 | (newColor & 0x0000FF00) | (newColor & 0x00FF0000) >> 16; } if (this.useCompression) { if (newColor != currentColor) { this.writeColor(fileOut, count, currentColor); count = 0; } currentColor = newColor; count++; } else { fileOut.writeIntRev(newColor); } } } if (this.useCompression) { this.writeColor(fileOut, count, currentColor); count = 0; fileOut.writeIntRev(NEXT_SLICE_FLAG); } } } // success return true; } private int[][] get_meta(int layerId) { int[] min, max, size; if (!useBoxAsMatrix) { // determine actual size by using the voxels min = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE}; max = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE}; size = new int[]{0, 0, 0}; boolean hasVoxel = false; for (Voxel voxel : data.getLayerVoxels(layerId)) { min[0] = Math.min(voxel.x, min[0]); min[1] = Math.min(voxel.y, min[1]); min[2] = Math.min(voxel.z, min[2]); max[0] = Math.max(voxel.x, max[0]); max[1] = Math.max(voxel.y, max[1]); max[2] = Math.max(voxel.z, max[2]); hasVoxel = true; } if (hasVoxel) { size = new int[]{max[0] - min[0] + 1, max[1] - min[1] + 1, max[2] - min[2] + 1}; } } else { // use the bounding box as size min = new int[] { DynamicSettings.VOXEL_PLANE_RANGE_X_NEG + 1, -DynamicSettings.VOXEL_PLANE_SIZE_Y + 1, DynamicSettings.VOXEL_PLANE_RANGE_Z_NEG + 1 }; // System.out.println(min[0] + ", " + min[1] + ", " + min[2]); max = new int[] { DynamicSettings.VOXEL_PLANE_RANGE_X_POS - 1, 0, DynamicSettings.VOXEL_PLANE_RANGE_Z_POS - 1 }; // System.out.println(max[0] + ", " + max[1] + ", " + max[2]); size = new int[]{max[0] - min[0] + 1, max[1] - min[1] + 1, max[2] - min[2] + 1}; // System.out.println(size[0] + ", " + size[1] + ", " + size[2]); } return new int[][] { min, max, size }; } // Helper to write color information private void writeColor(FileOut fileOut, int count, int currentColor) throws IOException { if (count == 1) { fileOut.writeIntRev(currentColor); } else if (count == 2) { fileOut.writeIntRev(currentColor); fileOut.writeIntRev(currentColor); } else if (count == 3) { fileOut.writeIntRev(currentColor); fileOut.writeIntRev(currentColor); fileOut.writeIntRev(currentColor); } else if (count > 3) { fileOut.writeIntRev(CODE_FLAG); fileOut.writeIntRev(count); fileOut.writeIntRev(currentColor); } } }