// buffer offset util protected int GetNextBlock(out ChunkInd dataChunk, BinaryReader reader, FileFlags flags) { bool swap = false; bool varies = false; if ((flags & FileFlags.EndianSwap) == FileFlags.EndianSwap) { swap = true; } if ((flags & FileFlags.BitsVaries) == FileFlags.BitsVaries) { varies = true; } if (swap) { throw new NotImplementedException(); } dataChunk = new ChunkInd(); if (IntPtr.Size == 8) { if (varies) { ChunkPtr4 c = new ChunkPtr4(reader); dataChunk = new ChunkInd(ref c); } else { ChunkPtr8 c = new ChunkPtr8(reader); dataChunk = new ChunkInd(ref c); } } else { if (varies) { throw new NotImplementedException(); } else { ChunkPtr4 c = new ChunkPtr4(reader); dataChunk = new ChunkInd(ref c); } } if (dataChunk.Length < 0) { return(-1); } return(dataChunk.Length + ChunkUtils.GetOffset(flags)); }
protected void ResolvePointersChunk(ChunkInd dataChunk, FileVerboseMode verboseMode) { Dna fileDna = (_fileDna != null) ? _fileDna : _memoryDna; Dna.StructDecl oldStruct = fileDna.GetStruct(dataChunk.DnaNR); int oldLen = oldStruct.Type.Length; byte[] cur = FindLibPointer(dataChunk.OldPtr); using (MemoryStream stream = new MemoryStream(cur, false)) { using (BinaryReader reader = new BinaryReader(stream)) { for (int block = 0; block < dataChunk.NR; block++) { long streamPosition = stream.Position; ResolvePointersStructRecursive(reader, dataChunk.DnaNR, verboseMode, 1); System.Diagnostics.Debug.Assert(stream.Position == streamPosition + oldLen); } } } }
protected override void ReadChunks() { bool brokenDna = (Flags & FileFlags.BrokenDna) != 0; _dataStart = SizeOfBlenderHeader; long chunkPtr = _dataStart; Stream stream = ChunkReader.BaseStream; stream.Position = chunkPtr; ChunkInd chunk = GetNextBlock(ChunkReader); while (chunk.Code != DnaID.Dna) { long chunkDataOffset = chunkPtr + ChunkUtils.GetChunkSize(Flags); if (!brokenDna || chunk.Code != DnaID.QuantizedBvh) { // One behind if (chunk.Code == DnaID.Sdna) { break; } byte[] chunkData; if (chunk.StructIndex >= 0) { _chunks.Add(chunk); chunkData = ReadChunkData(chunk, chunkDataOffset); switch (chunk.Code) { case DnaID.CollisionObject: CollisionObjects.Add(chunkData); break; case DnaID.Constraint: Constraints.Add(chunkData); break; case DnaID.DynamicsWorld: DynamicsWorldInfo.Add(chunkData); break; case DnaID.MultiBody: MultiBodies.Add(chunkData); break; case DnaID.SoftBody: case DnaID.TriangleInfoMap: throw new NotImplementedException(); case DnaID.QuantizedBvh: Bvhs.Add(chunkData); break; case DnaID.RigidBody: RigidBodies.Add(chunkData); break; case DnaID.Shape: CollisionShapes.Add(chunkData); break; } } else { #if DEBUG Console.WriteLine("unknown chunk " + chunk.Code); #endif chunkData = new byte[chunk.Length]; ChunkReader.Read(chunkData, 0, chunk.Length); } LibPointers.Add(chunk.OldPtr, chunkData); } else { #if DEBUG Console.WriteLine("skipping B3_QUANTIZED_BVH_CODE due to broken DNA"); #endif } chunkPtr = chunkDataOffset + chunk.Length; stream.Position = chunkPtr; chunk = GetNextBlock(ChunkReader); if (chunk.Length < 0) { break; } } }
protected byte[] ReadStruct(BinaryReader head, ChunkInd dataChunk) { bool ignoreEndianFlag = false; if ((_flags & FileFlags.EndianSwap) == FileFlags.EndianSwap) { //swap(head, dataChunk, ignoreEndianFlag); } if (!_fileDna.FlagEqual(dataChunk.DnaNR)) { // Ouch! need to rebuild the struct Dna.StructDecl oldStruct = _fileDna.GetStruct(dataChunk.DnaNR); if ((_flags & FileFlags.BrokenDna) != 0) { if (oldStruct.Type.Name.Equals("btQuantizedBvhNodeData") && oldStruct.Type.Length == 28) { throw new NotImplementedException(); } if (oldStruct.Type.Name.Equals("btShortIntIndexData")) { throw new NotImplementedException(); } } // Don't try to convert Link block data, just memcpy it. Other data can be converted. if (oldStruct.Type.Name.Equals("Link")) { //Console.WriteLine("Link found"); } else { int reverseOld = _memoryDna.GetReverseType(oldStruct.Type.Name); if (reverseOld != -1) { Dna.StructDecl curStruct = _memoryDna.GetStruct(reverseOld); byte[] structAlloc = new byte[dataChunk.NR * curStruct.Type.Length]; AddDataBlock(structAlloc); using (MemoryStream stream = new MemoryStream(structAlloc)) { using (BinaryWriter writer = new BinaryWriter(stream)) { long headerPtr = head.BaseStream.Position; for (int block = 0; block < dataChunk.NR; block++) { head.BaseStream.Position = headerPtr; ParseStruct(writer, head, oldStruct, curStruct, true); headerPtr += oldStruct.Type.Length; //_libPointers.Add(old, cur); } } } return structAlloc; } } } else { #if DEBUG_EQUAL_STRUCTS #endif } byte[] dataAlloc = new byte[dataChunk.Length]; head.Read(dataAlloc, 0, dataAlloc.Length); return dataAlloc; }
protected void ParseInternal(FileVerboseMode verboseMode, byte[] memDna) { if ((_flags & FileFlags.OK) != FileFlags.OK) { return; } ChunkInd dna = new ChunkInd(); dna.OldPtr = 0; MemoryStream memory = new MemoryStream(_fileBuffer, false); BinaryReader reader = new BinaryReader(memory); int i = 0; while (memory.Position < memory.Length) { // looking for the data's starting position // and the start of SDNA decls byte[] code = reader.ReadBytes(4); string codes = ASCIIEncoding.ASCII.GetString(code); if (_dataStart == 0 && codes.Equals("REND")) { _dataStart = memory.Position; } if (codes.Equals("DNA1")) { // read the DNA1 block and extract SDNA reader.BaseStream.Position = i; if (GetNextBlock(out dna, reader, _flags) > 0) { string sdnaname = ASCIIEncoding.ASCII.GetString(reader.ReadBytes(8)); if (sdnaname.Equals("SDNANAME")) { dna.OldPtr = i + ChunkUtils.GetOffset(_flags); } else { dna.OldPtr = 0; } } else { dna.OldPtr = 0; } } else if (codes.Equals("SDNA")) { // Some Bullet files are missing the DNA1 block // In Blender it's DNA1 + ChunkUtils::getOffset() + SDNA + NAME // In Bullet tests its SDNA + NAME dna.OldPtr = i; dna.Length = (int)memory.Length - i; // Also no REND block, so exit now. if (_version == 276) { break; } } if (_dataStart != 0 && dna.OldPtr != 0) { break; } i++; memory.Position = i; } if (dna.OldPtr == 0 || dna.Length == 0) { //Console.WriteLine("Failed to find DNA1+SDNA pair"); _flags &= ~FileFlags.OK; reader.Dispose(); memory.Dispose(); return; } _fileDna = new Dna(); // _fileDna.Init will convert part of DNA file endianness to current CPU endianness if necessary memory.Position = dna.OldPtr; _fileDna.Init(reader, (_flags & FileFlags.EndianSwap) != 0); if (_version == 276) { for (i = 0; i < _fileDna.NumNames; i++) { if (_fileDna.GetName(i).Equals("int")) { _flags |= FileFlags.BrokenDna; } } if ((_flags & FileFlags.BrokenDna) == FileFlags.BrokenDna) { //Console.WriteLine("warning: fixing some broken DNA version"); } } //if ((verboseMode & FileVerboseMode.DumpDnaTypeDefinitions) == FileVerboseMode.DumpDnaTypeDefinitions) // _fileDna.DumpTypeDefinitions(); _memoryDna = new Dna(); using (MemoryStream memory2 = new MemoryStream(memDna, false)) { using (BinaryReader reader2 = new BinaryReader(memory2)) { _memoryDna.Init(reader2, !BitConverter.IsLittleEndian); } } if (_memoryDna.NumNames != _fileDna.NumNames) { _flags |= FileFlags.VersionVaries; //Console.WriteLine ("Warning, file DNA is different than built in, performance is reduced. Best to re-export file with a matching version/platform"); } if (_memoryDna.LessThan(_fileDna)) { //Console.WriteLine ("Warning, file DNA is newer than built in."); } _fileDna.InitCmpFlags(_memoryDna); ParseData(); ResolvePointers(verboseMode); UpdateOldPointers(); reader.Dispose(); memory.Dispose(); }
// buffer offset util protected int GetNextBlock(out ChunkInd dataChunk, BinaryReader reader, FileFlags flags) { bool swap = false; bool varies = false; if ((flags & FileFlags.EndianSwap) == FileFlags.EndianSwap) swap = true; if ((flags & FileFlags.BitsVaries) == FileFlags.BitsVaries) varies = true; if (swap) { throw new NotImplementedException(); } dataChunk = new ChunkInd(); if (IntPtr.Size == 8) { if (varies) { ChunkPtr4 c = new ChunkPtr4(reader); dataChunk = new ChunkInd(ref c); } else { ChunkPtr8 c = new ChunkPtr8(reader); dataChunk = new ChunkInd(ref c); } } else { if (varies) { throw new NotImplementedException(); } else { ChunkPtr4 c = new ChunkPtr4(reader); dataChunk = new ChunkInd(ref c); } } if (dataChunk.Length < 0) return -1; return dataChunk.Length + ChunkUtils.GetOffset(flags); }
protected byte[] ReadChunkData(ChunkInd dataChunk, long chunkDataOffset) { //bool ignoreEndianFlag = false; if ((Flags & FileFlags.EndianSwap) != 0) { //swap(head, dataChunk, ignoreEndianFlag); } if (StructChanged(dataChunk.StructIndex)) { // Ouch! need to rebuild the struct Dna.StructDecl oldStruct = _fileDna.GetStruct(dataChunk.StructIndex); if ((Flags & FileFlags.BrokenDna) != 0) { if (oldStruct.Type.Name.Equals("btQuantizedBvhNodeData") && oldStruct.Type.Length == 28) { throw new NotImplementedException(); } if (oldStruct.Type.Name.Equals("btShortIntIndexData")) { throw new NotImplementedException(); } } // Don't try to convert Link block data, just memcpy it. Other data can be converted. if (oldStruct.Type.Name.Equals("Link")) { //Console.WriteLine("Link found"); } else { Dna.StructDecl curStruct = _memoryDna.GetStruct(oldStruct.Type.Name); if (curStruct != null) { byte[] structAlloc = new byte[dataChunk.NumBlocks * curStruct.Type.Length]; AddDataBlock(structAlloc); using (var stream = new MemoryStream(structAlloc)) { using (var writer = new BinaryWriter(stream)) { long structOffset = chunkDataOffset; for (int block = 0; block < dataChunk.NumBlocks; block++) { ParseStruct(writer, curStruct, oldStruct, structOffset); structOffset += oldStruct.Type.Length; } } } return structAlloc; } } } else { #if DEBUG_EQUAL_STRUCTS #endif } byte[] dataAlloc = new byte[dataChunk.Length]; ChunkReader.Read(dataAlloc, 0, dataChunk.Length); return dataAlloc; }
protected byte[] ReadStruct(BinaryReader head, ChunkInd dataChunk) { bool ignoreEndianFlag = false; if ((_flags & FileFlags.EndianSwap) == FileFlags.EndianSwap) { //swap(head, dataChunk, ignoreEndianFlag); } if (!_fileDna.FlagEqual(dataChunk.DnaNR)) { // Ouch! need to rebuild the struct Dna.StructDecl oldStruct = _fileDna.GetStruct(dataChunk.DnaNR); if ((_flags & FileFlags.BrokenDna) != 0) { if (oldStruct.Type.Name.Equals("btQuantizedBvhNodeData") && oldStruct.Type.Length == 28) { throw new NotImplementedException(); } if (oldStruct.Type.Name.Equals("btShortIntIndexData")) { throw new NotImplementedException(); } } // Don't try to convert Link block data, just memcpy it. Other data can be converted. if (oldStruct.Type.Name.Equals("Link")) { //Console.WriteLine("Link found"); } else { int reverseOld = _memoryDna.GetReverseType(oldStruct.Type.Name); if (reverseOld != -1) { Dna.StructDecl curStruct = _memoryDna.GetStruct(reverseOld); byte[] structAlloc = new byte[dataChunk.NR * curStruct.Type.Length]; AddDataBlock(structAlloc); using (MemoryStream stream = new MemoryStream(structAlloc)) { using (BinaryWriter writer = new BinaryWriter(stream)) { long headerPtr = head.BaseStream.Position; for (int block = 0; block < dataChunk.NR; block++) { head.BaseStream.Position = headerPtr; ParseStruct(writer, head, oldStruct, curStruct, true); headerPtr += oldStruct.Type.Length; //_libPointers.Add(old, cur); } } } return(structAlloc); } } } else { #if DEBUG_EQUAL_STRUCTS #endif } byte[] dataAlloc = new byte[dataChunk.Length]; head.Read(dataAlloc, 0, dataAlloc.Length); return(dataAlloc); }
protected byte[] ReadChunkData(ChunkInd dataChunk, long chunkDataOffset) { //bool ignoreEndianFlag = false; if ((Flags & FileFlags.EndianSwap) != 0) { //swap(head, dataChunk, ignoreEndianFlag); } if (StructChanged(dataChunk.StructIndex)) { // Ouch! need to rebuild the struct Dna.StructDecl oldStruct = _fileDna.GetStruct(dataChunk.StructIndex); if ((Flags & FileFlags.BrokenDna) != 0) { if (oldStruct.Type.Name.Equals("btQuantizedBvhNodeData") && oldStruct.Type.Length == 28) { throw new NotImplementedException(); } if (oldStruct.Type.Name.Equals("btShortIntIndexData")) { throw new NotImplementedException(); } } // Don't try to convert Link block data, just memcpy it. Other data can be converted. if (oldStruct.Type.Name.Equals("Link")) { //Console.WriteLine("Link found"); } else { Dna.StructDecl curStruct = _memoryDna.GetStruct(oldStruct.Type.Name); if (curStruct != null) { byte[] structAlloc = new byte[dataChunk.NumBlocks * curStruct.Type.Length]; AddDataBlock(structAlloc); using (var stream = new MemoryStream(structAlloc)) { using (var writer = new BinaryWriter(stream)) { long structOffset = chunkDataOffset; for (int block = 0; block < dataChunk.NumBlocks; block++) { ParseStruct(writer, curStruct, oldStruct, structOffset); structOffset += oldStruct.Type.Length; } } } return(structAlloc); } } } else { #if DEBUG_EQUAL_STRUCTS #endif } byte[] dataAlloc = new byte[dataChunk.Length]; ChunkReader.Read(dataAlloc, 0, dataChunk.Length); return(dataAlloc); }