/// <summary> /// Constructor. Creates a data structure out of the XFile given in the memory block. /// </summary> /// <param name="buffer"></param> public XFileParser(byte[] buffer) { this.buffer = buffer; majorVersion = minorVersion = 0; isBinaryFormat = false; binaryNumCount = 0; p = end = -1; lineNumber = 0; scene = null; // vector to store uncompressed file for INFLATE'd X files byte[] uncompressed; // set up memory pointers p = 0; end = buffer.Length; string header = Encoding.Default.GetString(buffer, 0, 16); // check header if (header.Substring(0, 4) != "xof ") throw new Exception("Header mismatch, file is not an XFile."); // read version. It comes in a four byte format such as "0302" majorVersion = uint.Parse(header.Substring(4, 2)); minorVersion = uint.Parse(header.Substring(6, 2)); bool compressed = false; // txt - pure ASCII text format if (header.Substring(8, 4) == "txt ") { isBinaryFormat = false; }// bin - Binary format else if (header.Substring(8, 4) == "bin ") { isBinaryFormat = true; } // tzip - Inflate compressed text format else if (header.Substring(8, 4) == "tzip") { isBinaryFormat = false; compressed = true; } // bzip - Inflate compressed binary format else if (header.Substring(8, 4) == "bzip") { isBinaryFormat = true; compressed = true; } else ThrowException(string.Format("Unsupported xfile format '{0}'", header.Substring(8, 4))); // float size binaryFloatSize = uint.Parse(header.Substring(12, 4)); if (binaryFloatSize != 32 && binaryFloatSize != 64) ThrowException(string.Format("Unknown float size {0} specified in xfile header.", binaryFloatSize)); // The x format specifies size in bits, but we work in bytes binaryFloatSize /= 8; p += 16; // If this is a compressed X file, apply the inflate algorithm to it if (compressed) { //throw (new Exception("Assimp was built without compressed X support")); MemoryStream stream = new MemoryStream(buffer); stream.Position += 16; stream.Position += 6; long p1 = stream.Position; uint estOut = 0; while (p1 + 3 < end) { ushort ofs = BitConverter.ToUInt16(buffer, (int)p1); p1 += 2; if (ofs >= MSZIP_BLOCK) { throw (new Exception("X: Invalid offset to next MSZIP compressed block")); } ushort magic = BitConverter.ToUInt16(buffer, (int)p1); p1 += 2; if (magic != MSZIP_MAGIC) { throw (new Exception("X: Unsupported compressed format, expected MSZIP header")); } p1 += ofs; estOut += MSZIP_BLOCK; } uncompressed = new byte[estOut + 1]; int uncompressedEnd = 0; while (p + 3 < end) { ushort ofs = BitConverter.ToUInt16(buffer, (int)p); p += 4; if (p + ofs > end + 2) { throw (new Exception("X: Unexpected EOF in compressed chunk")); } stream.Position = p; DeflateStream uncomp = new DeflateStream(stream, CompressionMode.Decompress); int readLnegth = uncomp.Read(uncompressed, 0, (int)MSZIP_BLOCK); uncompressedEnd += readLnegth; p += ofs; } this.buffer = uncompressed; this.end = uncompressedEnd; this.p = 0; } else { // start reading here ReadUntilEndOfLine(); } scene = new Scene(); ParseFile(); // filter the imported hierarchy for some degenerated cases if (scene.RootNode != null) { FilterHierarchy(scene.RootNode); } }
/// <summary> /// Constructs the return data structure out of the imported data. /// </summary> /// <param name="scene">The scene to construct the return data in.</param> /// <param name="sdata">The imported data in the internal temporary representation.</param> protected void CreateDataRepresentationFromImport(AssimpSharp.Scene scene, Scene data) { // Read the global materials first so that meshes referring to them can find them later ConvertMaterials(scene, data.GlobalMaterial); // copy nodes, extracting meshes and materials on the way scene.RootNode = CreateNodes(scene, null, data.RootNode); // extract animations CreateAnimations(scene, data); // read the global meshes that were stored outside of any node if (data.GlobalMeshes.Count > 0) { // create a root node to hold them if there isn't any, yet if (scene.RootNode == null) { scene.RootNode = new AssimpSharp.Node(); scene.RootNode.Name = "$dummy_node"; } // convert all global meshes and store them in the root node. // If there was one before, the global meshes now suddenly have its transformation matrix... // Don't know what to do there, I don't want to insert another node under the present root node // just to avoid this. CreateMeshes(scene, scene.RootNode, data.GlobalMeshes); } if (scene.RootNode == null) { throw (new DeadlyImportError("No root node")); } // Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly var convertProcess = new MakeLeftHandedProcess(); convertProcess.Execute(scene); var flipper = new FlipWindingOrderProcess(); flipper.Execute(scene); // finally: create a dummy material if not material was imported if (scene.Materials.Count == 0) { var mat = new aiMaterial(); mat.ShadingMode = ShadingMode.Gouraud; mat.ColorEmissive = new Color4(0, 0, 0, 1); mat.ColorSpecular = new Color4(0, 0, 0, 1); mat.ColorDiffuse = new Color4(0.5f, 0.5f, 0.5f, 1); mat.Shininess = 1.401298e-45f; scene.Materials.Add(mat); } }