package com.vitco.importer; import com.vitco.util.file.FileIn; import com.vitco.util.file.RandomAccessFileIn; import java.awt.*; import java.io.File; import java.io.IOException; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; /** * Kv6 importer */ public class Kv6Importer extends AbstractImporter { // constructor public Kv6Importer(File file, String name) throws IOException { super(file, name); } // --------- @Override protected boolean read(FileIn fileIn, RandomAccessFileIn raf) throws IOException { // check that this is a valid file (header correct) if (fileIn.readIntRev() != 0x6c78764b) { return false; } // read the dimensions int sx = fileIn.readIntRev(); int sy = fileIn.readIntRev(); int sz = fileIn.readIntRev(); if (sx == 0 || sy == 0 || sz == 0) { return false; } // read center int cx = Math.round(fileIn.readFloatRev()); int cy = Math.round(fileIn.readFloatRev()); int cz = Math.round(fileIn.readFloatRev()); // read the amount of voxel that have a visible side long count = fileIn.readIntRev(); // voxel info list (we don't know yet where they are in the world) ArrayList<int[]> voxel = new ArrayList<int[]>(); // read the colors and some other data for (int c = 0; c < count; c++) { // treat as unsigned byte int b = fileIn.readByteUnsigned(); int g = fileIn.readByteUnsigned(); int r = fileIn.readByteUnsigned(); fileIn.readByteUnsigned(); //int l = fileIn.readByteUnsigned(); Color color = new Color(r, g, b); // ----------- int zpos = fileIn.readShortRevUnsigned(); int visfaces = fileIn.readByteUnsigned(); fileIn.readByteUnsigned(); //int lightDir = fileIn.readByteUnsigned(); // System.out.println( // r + " " + g + " " + b + " (" + lightDir + ") @ " + // (ByteHelper.isBitSet((byte) visfaces, 0) ? "1" : "0") + // (ByteHelper.isBitSet((byte) visfaces, 1) ? "1" : "0") + // (ByteHelper.isBitSet((byte) visfaces, 2) ? "1" : "0") + // (ByteHelper.isBitSet((byte) visfaces, 3) ? "1" : "0") + // (ByteHelper.isBitSet((byte) visfaces, 4) ? "1" : "0") + // (ByteHelper.isBitSet((byte) visfaces, 5) ? "1" : "0") + // (ByteHelper.isBitSet((byte) visfaces, 6) ? "1" : "0") + // (ByteHelper.isBitSet((byte) visfaces, 7) ? "1" : "0") // ); voxel.add(new int[]{zpos, color.getRGB(), visfaces}); } int sumxoffset = 0; int sumxyoffset = 0; // read the xoffset for (int x = 0; x < sx; x++) { int xoff = fileIn.readIntRev(); // System.out.println(xoff); sumxoffset += xoff; } // read the xyoffset Integer lastZ = null; int c = 0; int invisibleVoxel = 0; ArrayList<int[]> addedVoxelList = new ArrayList<int[]>(); for (int x = 0; x < sx; x++) { for (int y = 0; y < sy; y++) { int xyoff = fileIn.readShortRevUnsigned(); sumxyoffset += xyoff; // create list first, order it and then check which voxel are missing (testing) for (int newC = c + xyoff; c < newC; c++) { int[] vox = voxel.remove(0); // alternative "voxel.get(c)" addedVoxelList.add(vox); // System.out.println("A:" + x + " " + y + " " + vox[0]); addVoxel(x - cx, vox[0] - cz, -y + cy, vox[1]); // some files don't count invisible voxel, so we need to track them // for the sanity check if (vox[2] == 0) { invisibleVoxel++; } } Collections.sort(addedVoxelList, new Comparator<int[]>() { @Override public int compare(int[] o1, int[] o2) { return (int)Math.signum(o1[0] - o2[0]); } }); for (int[] vox : addedVoxelList) { // fill in voxels "in between" BigInteger bigInteger = BigInteger.valueOf(vox[2]); if (lastZ != null && !bigInteger.testBit(4)) { for (int i = lastZ + 1; i < vox[0]; i++) { // System.out.println("E:" + x + " " + y + " " + i); addVoxel(x - cx, i - cz, -y + cy, vox[1]); } } if (!bigInteger.testBit(5)) { lastZ = vox[0]; } else { lastZ = null; } } lastZ = null; addedVoxelList.clear(); } } return sumxoffset == sumxyoffset || sumxoffset == (sumxyoffset - invisibleVoxel); } }