public unsafe bool writeToFile(string filename) { if (File.Exists(filename)) { File.Delete(filename); } FileStream s = File.Open(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite); BinaryWriter f = new BinaryWriter(s); BinaryReader r = new BinaryReader(s); //open reading from our temp file.. mTempChunkFile.Position = 0; BinaryReader tbr = new BinaryReader(mTempChunkFile); //WRITE OUR HEADER mHeader = new ECFHeader(); mHeader.mHeaderMagic = cECFHeaderMagic; mHeader.mHeaderSize = (uint)sizeof(ECFHeader); //THIS IS JUST THE SIZE OF THIS HEADER f.Write(ExportTo360.StructToByteArray(mHeader)); ///////////////////////////////////////// //WRITE OUR CHUNK HEADERS (Dummies!) BECFChunkHeader[] headers = new BECFChunkHeader[mChunks.Count]; ushort padVal = 0; Int32 padVal32 = 0; BECFChunkHeader ch = new BECFChunkHeader(); for (int i = 0; i < mChunks.Count; i++) { headers[i].mID = mChunks[i].mID; headers[i].mOfs = (int)f.BaseStream.Position; headers[i].mSize = (int)mChunks[i].mLength; headers[i].mAdler32 = (int)mChunks[i].mHeaderAdler32;//THIS IS THE ADLER FOR THE ACTUAL CHUNK DATA WE REPRESENT (Post endiean converted!) headers[i].mFlags = 0; headers[i].mAlignmentLog2 = 2; headers[i].mPad0 = (short)padVal; //headers[i].endianSwap();//not yet.... f.Write(ExportTo360.StructToByteArray(headers[i])); } //////////////////////////////////////////////// //WRITE OUR CHUNK BLOCKS for (int i = 0; i < mChunks.Count; i++) { //CLM [03.13.07] ECF Changes //we need to ensure each chunk is aligned to the boundry defined by ch.mAlignmentLog2 //so check to see if our position pointer is a multiple of 4 (2^2) //if it's not, write the number of bytes required to MAKE it that multiple. long pos = f.BaseStream.Position; long modPos = pos & 3; if (modPos != 0) { long numBytesToWrite = 4 - modPos; byte[] b = new byte[numBytesToWrite]; f.Write(b); } long streampos = f.BaseStream.Length; f.Write(tbr.ReadBytes((int)mChunks[i].mLength)); //fill in our header data headers[i].mOfs = (int)streampos; //seek back to our header and update our position pointer //f.Seek(sizeof(ECFHeader) + (sizeof(BECFChunkHeader) * i) + sizeof(Int64), SeekOrigin.Begin); //f.Write(Xbox_EndianSwap.endSwapI32((int)streampos)); //f.Seek(0, SeekOrigin.End); } //REWRITE OUR HEADER WITH THE PROPER DATA //write our actual file length back to the header mHeader.mFileSize = (uint)f.BaseStream.Length; // totalheaderSize; mHeader.mNumChunks = (ushort)mChunks.Count; mHeader.mFlags = 0; // mFlags; mHeader.mID = cXTD_ECFFileID; mHeader.mChunkExtraDataSize = 0; mHeader.endianSwap(); //CLM we have to calculate the adler of the endianswapped data, then endian swap ourselves mHeader.mHeaderAdler32 = calcAdler32(ExportTo360.StructToByteArray(mHeader), (uint)(sizeof(Int32) * cECFAdler32DWORDsToSkip), (uint)(sizeof(ECFHeader) - sizeof(Int32) * cECFAdler32DWORDsToSkip)); mHeader.mHeaderAdler32 = (uint)Xbox_EndianSwap.endSwapI32((int)mHeader.mHeaderAdler32); f.Seek(0, SeekOrigin.Begin); f.Write(ExportTo360.StructToByteArray(mHeader)); // f.Seek(0, SeekOrigin.End); ///////////////////////////////////////// //WRITE OUR CHUNK HEADERS (Real!) for (int i = 0; i < mChunks.Count; i++) { headers[i].endianSwap(); f.Write(ExportTo360.StructToByteArray(headers[i])); } headers = null; f.Close(); f = null; s.Close(); s = null; tbr.Close(); tbr = null; clear(); return(true); }
public bool export_XTD(string filename, ExportSettings expSettings, ref ExportResults results) { DateTime start = DateTime.Now; //write the header for the entire XTD file XTDVisualHeader header = new XTDVisualHeader(); header.version = (int)eFileVersions.cXTDVersion; header.numXVerts = TerrainGlobals.getTerrain().getNumXVerts(); header.numXChunks = (int)(TerrainGlobals.getTerrain().getNumXVerts() / BTerrainQuadNode.cMaxWidth); header.tileScale = TerrainGlobals.getTerrain().getTileScale(); BBoundingBox simRepBB = SimGlobals.getSimMain().getBBoxForDecalObjects(); Vector3 visRepMin = TerrainGlobals.getTerrain().getQuadNodeRoot().getDesc().m_min - new Vector3(0, header.tileScale, 0); Vector3 visRepMax = TerrainGlobals.getTerrain().getQuadNodeRoot().getDesc().m_max + new Vector3(0, header.tileScale, 0); if (!CoreGlobals.mbLoadTerrainVisRep) { visRepMin = simRepBB.min; visRepMax = simRepBB.max; } header.worldMin = visRepMin; header.worldMax = visRepMax; header.endianSwap(); //write our header first. ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); binWriter.Write(ExportTo360.StructToByteArray(header)); ExportTo360.mECF.addChunk((int)eXTD_ChunkID.cXTD_XTDHeader, chunkHolder, (int)chunkHolder.mDataMemStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; header.endianSwap(); generateGridChunks(ref header); writeAtlasToMemory(ref results); writeAOData(ref results); writeAlpha(ref results); writeTessData(expSettings.RefineTerrain, expSettings.RefineEpsilon, expSettings.RefineMinorityBias, ref results); writeLightData(ref expSettings, ref results); bool exportOK = ExportTo360.safeECFFileWrite(filename, ".XTD"); TimeSpan ts = DateTime.Now - start; results.totalTime = ts.TotalMinutes; return(exportOK); }