/** * Dump FBX to standard output. * * @param file the file to dump. */ public static void dumpFile(FbxFile file) { dumpFile(file, System.out); }
public static FbxId getObjectId(FbxElement el) { if (el.propertiesTypes.length == 2 && el.propertiesTypes[0] == 'S' && el.propertiesTypes[1] == 'S') { return new StringFbxId((String) el.properties.get(0)); } else if (el.propertiesTypes.length == 3 && el.propertiesTypes[0] == 'L' && el.propertiesTypes[1] == 'S' && el.propertiesTypes[2] == 'S') { return new LongFbxId((Long) el.properties.get(0)); } else { return null; } } }
/** * Dump FBX to the given output stream. * * @param file the file to dump. * @param out the output stream where to output. */ public static void dumpFile(FbxFile file, OutputStream out) { Map<FbxId, FbxElement> uidToObjectMap = createUidToObjectMap(file); PrintStream ps = new PrintStream(out); for (FbxElement rootElement : file.rootElements) { dumpElement(rootElement, ps, 0, uidToObjectMap); } }
private static FbxElement readFBXElement(ByteBuffer byteBuffer) throws IOException { long endOffset = getUInt(byteBuffer); if(endOffset == 0) return null; long propCount = getUInt(byteBuffer); getUInt(byteBuffer); // Properties length unused FbxElement element = new FbxElement((int) propCount); element.id = new String(getBytes(byteBuffer, getUByte(byteBuffer))); for(int i = 0; i < propCount; ++i) { char dataType = readDataType(byteBuffer); element.properties.add(readData(byteBuffer, dataType)); element.propertiesTypes[i] = dataType; } if(byteBuffer.position() < endOffset) { while(byteBuffer.position() < (endOffset - BLOCK_SENTINEL_LENGTH)) element.children.add(readFBXElement(byteBuffer)); if(!Arrays.equals(BLOCK_SENTINEL_DATA, getBytes(byteBuffer, BLOCK_SENTINEL_LENGTH))) throw new IOException("Failed to read block sentinel, expected 13 zero bytes"); } if(byteBuffer.position() != endOffset) throw new IOException("Data length not equal to expected"); return element; }
public static FbxFile readFBX(InputStream stream) throws IOException { FbxFile fbxFile = new FbxFile(); // Read file to byte buffer so we can know current position in file ByteBuffer byteBuffer = readToByteBuffer(stream); try { stream.close(); } catch(IOException e) { } // Check majic header byte[] majic = getBytes(byteBuffer, HEAD_MAGIC.length); if(!Arrays.equals(HEAD_MAGIC, majic)) throw new IOException("Either ASCII FBX or corrupt file. " + "Only binary FBX files are supported"); // Read version fbxFile.version = getUInt(byteBuffer); // Read root elements while(true) { FbxElement e = readFBXElement(byteBuffer); if(e == null) break; fbxFile.rootElements.add(e); } return fbxFile; }
return byteBuffer.getLong(); case 'R': return getBytes(byteBuffer, (int) getUInt(byteBuffer)); case 'S': return new String(getBytes(byteBuffer, (int) getUInt(byteBuffer))); case 'f': return readArray(byteBuffer, 'f', 4); case 'i': return readArray(byteBuffer, 'i', 4); case 'd': return readArray(byteBuffer, 'd', 8); case 'l': return readArray(byteBuffer, 'l', 8); case 'b': return readArray(byteBuffer, 'b', 1); case 'c': return readArray(byteBuffer, 'c', 1);
protected static void dumpElement(FbxElement el, PrintStream ps, int indent, Map<FbxId, FbxElement> uidToObjectMap) { String indentStr = indent(indent * 4); String textId = el.id; Object property = el.properties.get(i); char propertyType = el.propertiesTypes[i]; dumpProperty(el.id, propertyType, property, ps, uidToObjectMap); if (i != el.properties.size() - 1) { ps.print(", "); ps.println(" {"); for (FbxElement childElement : el.children) { dumpElement(childElement, ps, indent + 1, uidToObjectMap);
private static Object readArray(ByteBuffer byteBuffer, char type, int bytes) throws IOException { int count = (int) getUInt(byteBuffer); int encoding = (int) getUInt(byteBuffer); int length = (int) getUInt(byteBuffer); byte[] data = getBytes(byteBuffer, length); if(encoding == 1) data = inflate(data); if(data.length != count * bytes) throw new IOException("Wrong data lenght. Expected: " + count * bytes + ", got: " + data.length);
private void loadData(InputStream stream) throws IOException { FbxFile scene = FbxReader.readFBX(stream); FbxDump.dumpFile(scene); // TODO: Load FBX object templates for (FbxElement e : scene.rootElements) { if (e.id.equals("FBXHeaderExtension")) { loadHeader(e); } else if (e.id.equals("GlobalSettings")) { loadGlobalSettings(e); } else if (e.id.equals("Objects")) { loadObjects(e); } else if (e.id.equals("Connections")) { connectObjects(e); } } }
@Override public void fromElement(FbxElement element) { super.fromElement(element); for (FbxElement child : element.getFbxProperties()) { String propName = (String) child.properties.get(0); if (propName.equals("LocalStop")) { long durationLong = (Long)child.properties.get(4); duration = (float) (durationLong * FbxAnimUtil.SECONDS_PER_UNIT); } } }
@Override public void fromElement(FbxElement element) { super.fromElement(element); if(!getSubclassName().equals("")) { return; } FbxElement shadingModelEl = element.getChildById("ShadingModel"); if (shadingModelEl != null) { shadingModel = (String) shadingModelEl.properties.get(0); if (!shadingModel.equals("")) { if (!shadingModel.equalsIgnoreCase("phong") && !shadingModel.equalsIgnoreCase("lambert")) { logger.log(Level.WARNING, "FBX material uses unknown shading model: {0}. " + "Material may display incorrectly.", shadingModel); } } } for (FbxElement child : element.getFbxProperties()) { properties.setPropertyFromElement(child); } }
protected void fromElement(FbxElement element) { id = FbxId.getObjectId(element); String nameAndClass; if (element.propertiesTypes.length == 3) { nameAndClass = (String) element.properties.get(1); subclassName = (String) element.properties.get(2); } else if (element.propertiesTypes.length == 2) { nameAndClass = (String) element.properties.get(0); subclassName = (String) element.properties.get(1); } else { throw new UnsupportedOperationException("This is not an FBX object: " + element.id); } int splitter = nameAndClass.indexOf("\u0000\u0001"); if (splitter != -1) { name = nameAndClass.substring(0, splitter); className = nameAndClass.substring(splitter + 2); } else { name = nameAndClass; className = null; } }
values.add(1, values.get(0)); FbxElement dummyProp = new FbxElement(types.length); dummyProp.children = prop.children; dummyProp.id = prop.id;
private void loadScene(InputStream stream) throws IOException { logger.log(Level.FINE, "Loading scene {0}", sceneFilename); long startTime = System.currentTimeMillis(); FbxFile scene = FbxReader.readFBX(stream); for(FbxElement e : scene.rootElements) { // Is it possible for elements to be in wrong order? switch(e.id) { case "GlobalSettings": loadGlobalSettings(e); break; case "Objects": loadObjects(e); break; case "Connections": loadConnections(e); break; } } long estimatedTime = System.currentTimeMillis() - startTime; logger.log(Level.FINE, "Loading done in {0} ms", estimatedTime); }
public static FbxId create(Object obj) { if (obj instanceof Long) { return new LongFbxId((Long)obj); } else if (obj instanceof String) { return new StringFbxId((String)obj); } else { throw new UnsupportedOperationException("Unsupported ID object type: " + obj.getClass()); } }
@Override public void fromElement(FbxElement element) { super.fromElement(element); for (FbxElement prop : element.getFbxProperties()) { String propName = (String) prop.properties.get(0); String propType = (String) prop.properties.get(1); if (propType.equals("Number")) { float propValue = ((Double) prop.properties.get(4)).floatValue(); propertyToDefaultMap.put(propName, propValue); } } }
/** * Creates a map between object UIDs and the objects themselves. * * @param file The file to create the mappings for. * @return The UID to object map. */ private static Map<FbxId, FbxElement> createUidToObjectMap(FbxFile file) { Map<FbxId, FbxElement> uidToObjectMap = new HashMap<FbxId, FbxElement>(); for (FbxElement rootElement : file.rootElements) { if (rootElement.id.equals("Objects")) { for (FbxElement fbxObj : rootElement.children) { FbxId uid = FbxId.getObjectId(fbxObj); if (uid != null) { uidToObjectMap.put(uid, fbxObj); } else { logger.log(Level.WARNING, "Cannot determine ID for object: {0}", fbxObj); } } } } return uidToObjectMap; }
private void loadGlobalSettings(FbxElement element) { for(FbxElement e2 : element.getFbxProperties()) { String propName = (String) e2.properties.get(0); switch(propName) { case "UnitScaleFactor": this.unitSize = ((Double) e2.properties.get(4)).floatValue(); break; case "CustomFrameRate": float framerate = ((Double) e2.properties.get(4)).floatValue(); if(framerate != -1) this.animFrameRate = framerate; break; case "UpAxisSign": this.yAxis = ((Integer) e2.properties.get(4)).intValue(); break; case "FrontAxisSign": this.zAxis = ((Integer) e2.properties.get(4)).intValue(); break; case "CoordAxisSign": this.xAxis = ((Integer) e2.properties.get(4)).intValue(); break; } } }
public FbxAnimNode(SceneLoader scene, FbxElement element) { super(scene, element); if(type.equals("")) { Double x = null, y = null, z = null; for(FbxElement e2 : element.getFbxProperties()) { String propName = (String) e2.properties.get(0); switch(propName) { case "d|X": x = (Double) e2.properties.get(4); break; case "d|Y": y = (Double) e2.properties.get(4); break; case "d|Z": z = (Double) e2.properties.get(4); break; } } // Load only T R S curve nodes if(x != null && y != null && z != null) value = new Vector3f(x.floatValue(), y.floatValue(), z.floatValue()); } }
@Override public void fromElement(FbxElement element) { super.fromElement(element); if (getSubclassName().equals("")) { for (FbxElement e : element.children) { if (e.id.equals("Type")) { type = (String) e.properties.get(0); } /*else if (e.id.equals("FileName")) { filename = (String) e.properties.get(0); }*/ } for (FbxElement prop : element.getFbxProperties()) { String propName = (String) prop.properties.get(0); if (propName.equals("AlphaSource")) { // ??? } else if (propName.equals("UVSet")) { uvSet = (String) prop.properties.get(4); } else if (propName.equals("WrapModeU")) { wrapModeU = (Integer) prop.properties.get(4); } else if (propName.equals("WrapModeV")) { wrapModeV = (Integer) prop.properties.get(4); } } } }