//----------------------------------------------------------------------------------- void heightFieldToChunk(HeightsGen hg, ref ExportResults results) { ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); binWriter.Write(Xbox_EndianSwap.endSwapI32((int)hg.mHeightFieldAttributes.mWidth)); binWriter.Write(Xbox_EndianSwap.endSwapI32((int)hg.mHeightFieldAttributes.mHeight)); binWriter.Write(Xbox_EndianSwap.endSwapF32(hg.mHeightFieldAttributes.mWorldMinY)); binWriter.Write(Xbox_EndianSwap.endSwapF32(hg.mHeightFieldAttributes.mWorldMaxY)); binWriter.Write(Xbox_EndianSwap.endSwapF32(hg.mHeightFieldAttributes.mWorldRangeY)); binWriter.Write(Xbox_EndianSwap.endSwapF32(hg.mHeightFieldAttributes.mBounds.min.X)); binWriter.Write(Xbox_EndianSwap.endSwapF32(hg.mHeightFieldAttributes.mBounds.min.Y)); binWriter.Write(Xbox_EndianSwap.endSwapF32(hg.mHeightFieldAttributes.mBounds.min.Z)); binWriter.Write(Xbox_EndianSwap.endSwapF32(hg.mHeightFieldAttributes.mBounds.max.X)); binWriter.Write(Xbox_EndianSwap.endSwapF32(hg.mHeightFieldAttributes.mBounds.max.Y)); binWriter.Write(Xbox_EndianSwap.endSwapF32(hg.mHeightFieldAttributes.mBounds.max.Z)); binWriteMatrix(binWriter, hg.mHeightFieldAttributes.mNormZToWorld); binWriteMatrix(binWriter, hg.mHeightFieldAttributes.mWorldToNormZ); binWriter.Write(Xbox_EndianSwap.endSwapI32(hg.mHeightFieldAttributes.mpTexelsHI.Length)); int memSize = hg.mHeightFieldAttributes.mpTexelsHI.Length * 2 * sizeof(short); binWriter.Write(Xbox_EndianSwap.endSwapI32(memSize)); //expect the texture as G16R16, NON FLOAT! Just 16 bits of short. int numShorts = hg.mHeightFieldAttributes.mpTexelsHI.Length * 2; short[] sArray = new short[numShorts]; for (int i = 0; i < hg.mHeightFieldAttributes.mpTexelsHI.Length; i++) { sArray[i * 2 + 0] = (short)Xbox_EndianSwap.endSwapI16((ushort)hg.mHeightFieldAttributes.mpTexelsHI[i]); sArray[i * 2 + 1] = (short)Xbox_EndianSwap.endSwapI16((ushort)hg.mHeightFieldAttributes.mpTexelsLO[i]); } //tileswap short[] tempbytearray = new short[sArray.Length]; sArray.CopyTo(tempbytearray, 0); ExportTo360.tileCopy(ref tempbytearray, tempbytearray, (int)hg.mHeightFieldAttributes.mWidth, (int)hg.mHeightFieldAttributes.mHeight, ExportTo360.eTileCopyFormats.cTCFMT_G16R16); // tempbytearray.CopyTo(sArray, 0); for (int i = 0; i < tempbytearray.Length; i++) { binWriter.Write(tempbytearray[i]); } ExportTo360.mECF.addChunk((int)eXTH_ChunkID.cXTH_TerrainHeightfield, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; results.terrainGPUHeighfieldMemory = memSize; }
public void endianSwap() { mHeaderMagic = (uint)Xbox_EndianSwap.endSwapI32((int)mHeaderMagic); mHeaderSize = (uint)Xbox_EndianSwap.endSwapI32((int)mHeaderSize); mHeaderAdler32 = (uint)Xbox_EndianSwap.endSwapI32((int)mHeaderAdler32); mFileSize = (uint)Xbox_EndianSwap.endSwapI32((int)mFileSize);// totalheaderSize; mNumChunks = (ushort)Xbox_EndianSwap.endSwapI16((ushort)mNumChunks); mFlags = (ushort)Xbox_EndianSwap.endSwapI16((ushort)mFlags); mID = (uint)Xbox_EndianSwap.endSwapI32((int)mID); mChunkExtraDataSize = 0; }
public void endianSwap() { mID = Xbox_EndianSwap.endSwapI64(mID); mOfs = Xbox_EndianSwap.endSwapI32(mOfs); mSize = Xbox_EndianSwap.endSwapI32(mSize); mAdler32 = Xbox_EndianSwap.endSwapI32(mAdler32); //public byte mFlags; //public byte mAlignmentLog2; //public Int16 mPad0; }
public void endianSwap() { version = Xbox_EndianSwap.endSwapI32(version); numXVerts = Xbox_EndianSwap.endSwapI32(numXVerts); numXChunks = Xbox_EndianSwap.endSwapI32(numXChunks); tileScale = Xbox_EndianSwap.endSwapF32(tileScale); worldMin.X = Xbox_EndianSwap.endSwapF32(worldMin.X); worldMin.Y = Xbox_EndianSwap.endSwapF32(worldMin.Y); worldMin.Z = Xbox_EndianSwap.endSwapF32(worldMin.Z); worldMax.X = Xbox_EndianSwap.endSwapF32(worldMax.X); worldMax.Y = Xbox_EndianSwap.endSwapF32(worldMax.Y); worldMax.Z = Xbox_EndianSwap.endSwapF32(worldMax.Z); }
//----------------------------------------------------------------------------------- void headerToChunk() { ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); int version = (int)eFileVersions.cXTHVersion; binWriter.Write(Xbox_EndianSwap.endSwapI32(version)); ExportTo360.mECF.addChunk((int)eXTH_ChunkID.cXTH_XTHHeader, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; }
public void endianSwap() { numZBlocks = Xbox_EndianSwap.endSwapI32(numZBlocks); numXBlocks = Xbox_EndianSwap.endSwapI32(numXBlocks); numXVerts = Xbox_EndianSwap.endSwapI32(numXVerts); tileScale = Xbox_EndianSwap.endSwapF32(tileScale); yAxis_hvMemSize = Xbox_EndianSwap.endSwapI32(yAxis_hvMemSize); yAxis_dcMemSize = Xbox_EndianSwap.endSwapI32(yAxis_dcMemSize); xAxis_hvMemSize = Xbox_EndianSwap.endSwapI32(xAxis_hvMemSize); zAxis_hvMemSize = Xbox_EndianSwap.endSwapI32(zAxis_hvMemSize); xzAxis_dcMemSize = Xbox_EndianSwap.endSwapI32(xzAxis_dcMemSize); yAxis_ranges = new Vector3(0, Xbox_EndianSwap.endSwapF32(yAxis_ranges.Y), Xbox_EndianSwap.endSwapF32(yAxis_ranges.Z)); xAxis_ranges = new Vector3(Xbox_EndianSwap.endSwapF32(xAxis_ranges.X), Xbox_EndianSwap.endSwapF32(xAxis_ranges.Y), Xbox_EndianSwap.endSwapF32(xAxis_ranges.Z)); zAxis_ranges = new Vector3(Xbox_EndianSwap.endSwapF32(zAxis_ranges.X), Xbox_EndianSwap.endSwapF32(zAxis_ranges.Y), Xbox_EndianSwap.endSwapF32(zAxis_ranges.Z)); xyBasis_hvMemSize = Xbox_EndianSwap.endSwapI32(xyBasis_hvMemSize); zwBasis_hvMemSize = Xbox_EndianSwap.endSwapI32(zwBasis_hvMemSize); }
public void writeHeaderToChunk() { ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); List <FoliageSet> validSets = new List <FoliageSet>(); for (int i = 0; i < FoliageManager.getNumSets(); i++) { if (FoliageManager.isSetUsed(FoliageManager.giveSet(i))) { validSets.Add(FoliageManager.giveSet(i)); } } binWriter.Write(Xbox_EndianSwap.endSwapI32(validSets.Count)); for (int i = 0; i < validSets.Count; i++) { string tName = validSets[i].mFullFileName; if (tName.Contains(".xml")) { tName = tName.Substring(0, tName.LastIndexOf(".xml")); } string fName = tName.Remove(0, CoreGlobals.getWorkPaths().mGameArtDirectory.Length + 1); char[] filename = new char[256]; fName.CopyTo(0, filename, 0, fName.Length); binWriter.Write(filename); ExportTo360.addTextureChannelDependencies(tName); if (File.Exists(Path.ChangeExtension(tName, ".xml"))) { ExportTo360.mDEP.addFileDependent(Path.ChangeExtension(tName, ".xml"), false); } } ExportTo360.mECF.addChunk((int)eXTT_ChunkID.cXTT_FoliageHeaderChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; }
//----------------------------------------- private unsafe void headerToChunk() { ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); int version = (int)eFileVersions.cXSDVersion; binWriter.Write(Xbox_EndianSwap.endSwapI32(version)); //sim terrain data stuff binWriter.Write(Xbox_EndianSwap.endSwapI32(TerrainGlobals.getEditor().getSimRep().getNumXTiles())); //simTileScale binWriter.Write(Xbox_EndianSwap.endSwapF32(TerrainGlobals.getEditor().getSimRep().getTileScale())); //simTileScale binWriter.Write(Xbox_EndianSwap.endSwapF32(TerrainGlobals.getEditor().getSimRep().getVisToSimScale())); //visToSimScale //round our sim-rep up to next multiple of 8 for XBOX360 memory effecient tiling int width = (TerrainGlobals.getEditor().getSimRep().getNumXVerts() - 1) * cSimHeightResMultiplier + 1; int numXBlocks = width / 8; if (width % 8 != 0) { numXBlocks++; } int newWidth = numXBlocks * 8; float heightTileScale = (TerrainGlobals.getEditor().getSimRep().getTileScale() / (float)cSimHeightResMultiplier); binWriter.Write(Xbox_EndianSwap.endSwapI32(width)); //numHeightVerts binWriter.Write(Xbox_EndianSwap.endSwapI32(newWidth)); //numHeightVertsCacheFeriently binWriter.Write(Xbox_EndianSwap.endSwapF32(heightTileScale)); //height tile scale binWriter.Write(Xbox_EndianSwap.endSwapI32(cSimHeightResMultiplier)); //DataToHeightMultiplier ExportTo360.mECF.addChunk((int)eXSD_ChunkID.cXSD_XSDHeader, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; }
//---------------------------------------------- //---------------------------------------------- //---------------------------------------------- //---------------------------------------------- //---------------------------------------------- //---------------------------------------------- private unsafe int writeChunk(XTDTerrainChunk chunk, BinaryWriter mem) { mem.Write(Xbox_EndianSwap.endSwapI32(chunk.gridLocX)); mem.Write(Xbox_EndianSwap.endSwapI32(chunk.gridLocZ)); mem.Write(Xbox_EndianSwap.endSwapI32(chunk.maxVertStride)); mem.Write(Xbox_EndianSwap.endSwapF32(chunk.mMin.X)); mem.Write(Xbox_EndianSwap.endSwapF32(chunk.mMin.Y)); mem.Write(Xbox_EndianSwap.endSwapF32(chunk.mMin.Z)); mem.Write(Xbox_EndianSwap.endSwapF32(chunk.mMax.X)); mem.Write(Xbox_EndianSwap.endSwapF32(chunk.mMax.Y)); mem.Write(Xbox_EndianSwap.endSwapF32(chunk.mMax.Z)); bool canCastShadows = true; if (chunk.mMax.Y - chunk.mMin.Y < 2) { canCastShadows = false; } mem.Write(canCastShadows); return(0); }
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); }
void heightFieldAlphaToChunk(ref ExportResults results) { //i think for visual reasons, the resolution of this alpha data needs to match //the density of the terrain alpha.. BTerrainSimRep simRep = TerrainGlobals.getEditor().getSimRep(); int width = TerrainGlobals.getTerrain().getNumXVerts(); int height = TerrainGlobals.getTerrain().getNumXVerts(); if (width < 256 || height < 256) { return; //don't write for small maps.. } byte[] AlphaVals = TerrainGlobals.getEditor().getAlphaValues(); DXT3_1111 img = new DXT3_1111(width, height); //walk through all the terrain alpha values, for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int index = x * width + y; bool visible = AlphaVals[index] > 0;// if it's invisible, so are we. //walk through the sim rep. If it's passable, we're visible. float normalizedX = x / (float)width; float normalizedZ = y / (float)height; bool obstructsLand = simRep.getDataTiles().isLandObstructedComposite(normalizedX, normalizedZ); visible |= !obstructsLand; img.setValue(x, y, visible); } } ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); int packedWidth = width >> 2; binWriter.Write(Xbox_EndianSwap.endSwapI32(packedWidth)); binWriter.Write(Xbox_EndianSwap.endSwapI32(height)); int numBlocks = img.getNumBlocks(); //numXBlocks-1 + numXBlocks * numYBlocks int texelMemSize = numBlocks * sizeof(Int64);// (((width >> 4) - 1) + (width >> 4) * ((height >> 2) - 1)) * sizeof(Int64); binWriter.Write(Xbox_EndianSwap.endSwapI32(texelMemSize)); for (int i = 0; i < numBlocks; i++) { binWriter.Write(img.getBlock(i)); } ExportTo360.mECF.addChunk((int)eXTH_ChunkID.cXTH_TerrainHeightfieldAlpha, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; results.terrainGPUHeighfieldMemory += texelMemSize; img = null; }
public void exportRoads(ref ExportResults results) { DateTime n = DateTime.Now; //for each road, for (int roadIndex = 0; roadIndex < RoadManager.giveNumRoads(); roadIndex++) { List <RoadTriangle> triList = new List <RoadTriangle>(); Road rd = RoadManager.giveRoad(roadIndex); if (rd.getNumControlPoints() == 0) //don't export roads w/o points on the map { continue; } //Step 1, generate polygon lists//////////////////////////////////////////////////// for (int rcpIndex = 0; rcpIndex < rd.getNumControlPoints(); rcpIndex++) { roadControlPoint rcp = rd.getPoint(rcpIndex); int numTris = (int)(rcp.mVerts.Count / 3); for (int triIndex = 0; triIndex < numTris; triIndex++) { RoadTriangle rt = new RoadTriangle(); rt.mVerts[0] = new RoadVert(); rt.mVerts[0].mPos = new Vector3(rcp.mVerts[triIndex * 3 + 0].x, rcp.mVerts[triIndex * 3 + 0].y, rcp.mVerts[triIndex * 3 + 0].z); rt.mVerts[0].mUv0 = new Vector2(rcp.mVerts[triIndex * 3 + 0].u0, rcp.mVerts[triIndex * 3 + 0].v0); rt.mVerts[1] = new RoadVert(); rt.mVerts[1].mPos = new Vector3(rcp.mVerts[triIndex * 3 + 1].x, rcp.mVerts[triIndex * 3 + 1].y, rcp.mVerts[triIndex * 3 + 1].z); rt.mVerts[1].mUv0 = new Vector2(rcp.mVerts[triIndex * 3 + 1].u0, rcp.mVerts[triIndex * 3 + 1].v0); rt.mVerts[2] = new RoadVert(); rt.mVerts[2].mPos = new Vector3(rcp.mVerts[triIndex * 3 + 2].x, rcp.mVerts[triIndex * 3 + 2].y, rcp.mVerts[triIndex * 3 + 2].z); rt.mVerts[2].mUv0 = new Vector2(rcp.mVerts[triIndex * 3 + 2].u0, rcp.mVerts[triIndex * 3 + 2].v0); triList.Add(rt); } } //now add our triStrip segments (into triLists) for (int segIndex = 0; segIndex < rd.getNumRoadSegments(); segIndex++) { roadSegment rs = rd.getRoadSegment(segIndex); int numTris = rs.mNumVerts - 2; int vertIndex = rs.mStartVertInParentSegment + 2; for (int i = 0; i < numTris; i++) { RoadTriangle rt = new RoadTriangle(); rt.mVerts[0] = new RoadVert(); rt.mVerts[0].mPos = new Vector3(rd.mVerts[vertIndex - 2].x, rd.mVerts[vertIndex - 2].y, rd.mVerts[vertIndex - 2].z); rt.mVerts[0].mUv0 = new Vector2(rd.mVerts[vertIndex - 2].u0, rd.mVerts[vertIndex - 2].v0); rt.mVerts[1] = new RoadVert(); rt.mVerts[1].mPos = new Vector3(rd.mVerts[vertIndex - 1].x, rd.mVerts[vertIndex - 1].y, rd.mVerts[vertIndex - 1].z); rt.mVerts[1].mUv0 = new Vector2(rd.mVerts[vertIndex - 1].u0, rd.mVerts[vertIndex - 1].v0); rt.mVerts[2] = new RoadVert(); rt.mVerts[2].mPos = new Vector3(rd.mVerts[vertIndex].x, rd.mVerts[vertIndex].y, rd.mVerts[vertIndex].z); rt.mVerts[2].mUv0 = new Vector2(rd.mVerts[vertIndex].u0, rd.mVerts[vertIndex].v0); triList.Add(rt); vertIndex++; } } //Step 2, split Polygons//////////////////////////////////////////////////// int width = (int)(BTerrainQuadNode.cMaxWidth); int numPlanes = (int)(TerrainGlobals.getTerrain().getNumXVerts() / width); //Split along XPlane for (int planeIndex = 0; planeIndex < numPlanes; planeIndex++) { Plane pl = Plane.FromPointNormal(new Vector3(planeIndex * width * TerrainGlobals.getTerrain().getTileScale(), 0, 0), BMathLib.unitX); splitPolyListAgainstPlane(pl, triList); } //split along ZPlane for (int planeIndex = 0; planeIndex < numPlanes; planeIndex++) { Plane pl = Plane.FromPointNormal(new Vector3(0, 0, planeIndex * width * TerrainGlobals.getTerrain().getTileScale()), BMathLib.unitZ); splitPolyListAgainstPlane(pl, triList); } //Step 3, add polies to qn.///////////////////////////////////////////////// List <RoadQN> roadQNs = new List <RoadQN>(); int numQNs = (int)(TerrainGlobals.getTerrain().getNumXVerts() / width); int qnWidth = (int)(width * TerrainGlobals.getTerrain().getTileScale()); for (int qnX = 0; qnX < numQNs; qnX++) { for (int qnZ = 0; qnZ < numQNs; qnZ++) { float x = qnX * qnWidth; float z = qnZ * qnWidth; RoadQN rqn = new RoadQN(); for (int triIndex = 0; triIndex < triList.Count; triIndex++) { if (triContainedInBox(triList[triIndex], x, z, x + qnWidth, z + qnWidth)) { triList[triIndex].ensureWinding(); rqn.mTris.Add(triList[triIndex]); rqn.mOwnerQNIndex = qnX * numQNs + qnZ; } } if (rqn.mTris.Count != 0) { roadQNs.Add(rqn); } } } //Step 4, write road chunk to disk.///////////////////////////////////////////// ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); //Filename string fName = CoreGlobals.getWorkPaths().mRoadsPath + "\\" + rd.getRoadTextureName(); fName = fName.Remove(0, CoreGlobals.getWorkPaths().mGameArtDirectory.Length + 1); char[] filename = new char[32]; fName.CopyTo(0, filename, 0, fName.Length); binWriter.Write(filename); ExportTo360.addTextureChannelDependencies(CoreGlobals.getWorkPaths().mRoadsPath + "\\" + rd.getRoadTextureName()); float zero = 0; int totalMemory = 0; //write our chunks binWriter.Write(Xbox_EndianSwap.endSwapI32(roadQNs.Count)); for (int qnI = 0; qnI < roadQNs.Count; qnI++) { binWriter.Write(Xbox_EndianSwap.endSwapI32(roadQNs[qnI].mOwnerQNIndex)); binWriter.Write(Xbox_EndianSwap.endSwapI32(roadQNs[qnI].mTris.Count)); int memSize = roadQNs[qnI].mTris.Count * (3 * (sizeof(short) * 6)); binWriter.Write(Xbox_EndianSwap.endSwapI32(memSize)); List <float> vList = new List <float>(); for (int c = 0; c < roadQNs[qnI].mTris.Count; c++) { for (int i = 0; i < 3; i++) { vList.Add(roadQNs[qnI].mTris[c].mVerts[i].mPos.X); vList.Add(roadQNs[qnI].mTris[c].mVerts[i].mPos.Y); vList.Add(roadQNs[qnI].mTris[c].mVerts[i].mPos.Z); vList.Add(zero); //padd; vList.Add(roadQNs[qnI].mTris[c].mVerts[i].mUv0.X); vList.Add(roadQNs[qnI].mTris[c].mVerts[i].mUv0.Y); } } float16[] sList = BMathLib.Float32To16Array(vList.ToArray()); for (int c = 0; c < vList.Count; c++) { ushort s = ((ushort)sList[c].getInternalDat()); binWriter.Write(Xbox_EndianSwap.endSwapI16(s)); } totalMemory += memSize; } ExportTo360.mECF.addChunk((int)eXTT_ChunkID.cXTT_RoadsChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; roadQNs.Clear(); triList.Clear(); TimeSpan ts = DateTime.Now - n; results.terrainRoadTime = ts.TotalMinutes; results.terrainRoadMemory = totalMemory; } }
public void buildAOFiles(string inputFilename, int numSections) { float [] AOVals = null; for (int i = 0; i < numSections; i++) { //work\scenario\development\coltTest\coltTest.AO0, .AO1, .AO2...., .AON string outFileName = Path.ChangeExtension(inputFilename, ".AO" + i); FileStream sr = File.Open(outFileName, FileMode.Open, FileAccess.Read); BinaryReader fr = new BinaryReader(sr); int majik = fr.ReadInt32(); if (majik != cMajik) { AOVals = null; sr.Close(); sr = null; fr.Close(); fr = null; return; } int numSectionsT = fr.ReadInt32(); Debug.Assert(numSectionsT == numSections); int mySecetion = fr.ReadInt32(); int numSamples = fr.ReadInt32(); int startSampleCount = fr.ReadInt32(); int endSampleCount = fr.ReadInt32(); int width = fr.ReadInt32(); int height = fr.ReadInt32(); if (AOVals == null) { AOVals = new float[width * height]; } for (int x = 0; x < width * height; x++) { AOVals[x] += fr.ReadSingle(); Debug.Assert(AOVals[x] > 1); } sr.Close(); sr = null; fr.Close(); fr = null; } //now that we have our AO data read from file and accumulated, open our XTD and write over the previous AO Values. //first we have to get the file pointer offset from reading the file... int AOOffset = 0; int AOHeaderAdlerOffset = 0; ECFReader ecfR = new ECFReader(); string XTDName = Path.ChangeExtension(inputFilename, ".XTD"); if (!ecfR.openForRead(XTDName)) { return; } int numXVerts = 0; for (uint i = 0; i < ecfR.getNumChunks(); i++) { ECF.BECFChunkHeader chunkHeader = ecfR.getChunkHeader(i); eXTD_ChunkID id = (eXTD_ChunkID)chunkHeader.mID; switch (id) { case eXTD_ChunkID.cXTD_XTDHeader: int version = Xbox_EndianSwap.endSwapI32(ecfR.readInt32()); numXVerts = Xbox_EndianSwap.endSwapI32(ecfR.readInt32()); break; case eXTD_ChunkID.cXTD_AOChunk: AOHeaderAdlerOffset = (int)(i * ECF.BECFChunkHeader.giveSize() + ECF.ECFHeader.giveSize()); AOHeaderAdlerOffset += sizeof(Int64) * 2; AOOffset = chunkHeader.mOfs; break; } } ecfR.close(); ecfR = null; //now that we have our offset into the file, open it for write //generate our data byte[] data = XTDExporter.packAOToDXT5A(AOVals, numXVerts); FileStream s = File.Open(XTDName, FileMode.Open, FileAccess.ReadWrite); BinaryWriter f = new BinaryWriter(s); //reset the ADLER32 for this chunk.. f.Seek(AOHeaderAdlerOffset, SeekOrigin.Begin); uint adler32 = (uint)Xbox_EndianSwap.endSwapI32((int)ECF.calcAdler32(data, 0, (uint)data.Length)); f.Write(adler32); f.Seek(AOOffset, SeekOrigin.Begin); for (int i = 0; i < data.Length; i++) { f.Write(data[i]); } data = null; f.Close(); f = null; s.Close(); s = null; //DONE! }
private int writeFlightHeights() { TerrainGlobals.getEditor().getSimRep().getFlightRep().recalculateHeights(); ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); int width = (int)TerrainGlobals.getEditor().getSimRep().getFlightRep().getNumXPoints(); int numXBlocks = width / 8; if (width % 8 != 0) { numXBlocks++; } int newWidth = numXBlocks * 8; //write our header information. float heightTileScale = TerrainGlobals.getEditor().getSimRep().getFlightRep().getTileScale(); binWriter.Write(Xbox_EndianSwap.endSwapI32(width)); //numHeightVerts binWriter.Write(Xbox_EndianSwap.endSwapI32(newWidth)); //numHeightVertsCacheFeriently binWriter.Write(Xbox_EndianSwap.endSwapF32(heightTileScale)); //height tile scale //swizzle our data to be more cache friendly.. //first, padd our data to the next multiple of 8 float[] tvals = new float[newWidth * newWidth]; for (int i = 0; i < width; i++) { for (int k = 0; k < width; k++) { int dstIndex = i + k * newWidth; tvals[dstIndex] = TerrainGlobals.getEditor().getSimRep().getFlightRep().getCompositeHeight(k, i);// heights[srcIndex]; } } ////now swizzle the bastard. int blockSize = 8; float[] kvals = new float[newWidth * newWidth]; int dstIndx = 0; for (int x = 0; x < numXBlocks; x++) { for (int z = 0; z < numXBlocks; z++) { int blockIndex = x + z * numXBlocks; //swizzle create this block for (int i = 0; i < blockSize; i++) { for (int j = 0; j < blockSize; j++) { int k = (z * blockSize) + j; // (blockSize - 1 - j); int l = (x * blockSize) + i; // (blockSize - 1 - i); int srcIndx = k * newWidth + l; //int dstIndx = i * blockSize + j; kvals[dstIndx++] = tvals[srcIndx]; } } } } //convert to float16 & write to disk. float16[] sList = BMathLib.Float32To16Array(kvals); for (int c = 0; c < sList.Length; c++) { ushort s = ((ushort)sList[c].getInternalDat()); binWriter.Write(Xbox_EndianSwap.endSwapI16(s)); } ExportTo360.mECF.addChunk((int)eXSD_ChunkID.cXSD_FlightHeights, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; return(tvals.Length * sizeof(ushort)); }
public void writeAtlasToMemory(ref ExportResults results) { int len = TerrainGlobals.getTerrain().getNumZVerts() * TerrainGlobals.getTerrain().getNumXVerts(); ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); #region 32bit pos Vector3 min = new Vector3(9000, 9000, 9000); Vector3 max = new Vector3(-9000, -9000, -9000); Vector3 range = new Vector3(0, 0, 0); findMaxsMinsRange(ref max, ref min, ref range); Vector3 adjustedMidValue = calcAdjustedMidValue(min); //write our mins & ranges (shoudl use XTDAtlasVisual here..) binWriter.Write(Xbox_EndianSwap.endSwapF32(adjustedMidValue.X)); binWriter.Write(Xbox_EndianSwap.endSwapF32(adjustedMidValue.Y)); binWriter.Write(Xbox_EndianSwap.endSwapF32(adjustedMidValue.Z)); binWriter.Write(0); //padd to allow 360 to read XMVECTOR from disk binWriter.Write(Xbox_EndianSwap.endSwapF32(range.X)); binWriter.Write(Xbox_EndianSwap.endSwapF32(range.Y)); binWriter.Write(Xbox_EndianSwap.endSwapF32(range.Z)); binWriter.Write(0); //padd to allow 360 to read XMVECTOR from disk //CLM i'm trying this out... long currLen = binWriter.BaseStream.Position; binWriter.BaseStream.SetLength(currLen + ((sizeof(int) * len) * 2)); //make sure we swizzle it... Vector3[] detail = TerrainGlobals.getEditor().getDetailPoints(); Int32[] tmpArray = new Int32[len]; for (int i = 0; i < len; i++) { tmpArray[i] = (int)packPosTo32Bits(detail[i], min, range); } ExportTo360.tileCopy(ref tmpArray, tmpArray, TerrainGlobals.getTerrain().getNumXVerts(), TerrainGlobals.getTerrain().getNumZVerts()); for (int i = 0; i < len; i++) { binWriter.Write(Xbox_EndianSwap.endSwapI32((int)tmpArray[i]));//(int)packPosTo32Bits(expData.mTerrainPoints[i],min,range))); } #endregion #region 32bit normal Vector3[] normals = TerrainGlobals.getEditor().getNormals(); for (int i = 0; i < len; i++) { tmpArray[i] = (int)packNormTo32Bits(normals[i]); } ExportTo360.tileCopy(ref tmpArray, tmpArray, TerrainGlobals.getTerrain().getNumXVerts(), TerrainGlobals.getTerrain().getNumZVerts()); for (int i = 0; i < len; i++) { binWriter.Write(Xbox_EndianSwap.endSwapI32((int)tmpArray[i]));//(int)packPosTo32Bits(expData.mTerrainPoints[i],min,range))); } #endregion tmpArray = null; ExportTo360.mECF.addChunk((int)eXTD_ChunkID.cXTD_AtlasChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; results.terrainPositionMemorySize = len * sizeof(UInt32); results.terrainNormalsMemorySize = len * sizeof(UInt32); normals = null; detail = null; }
private void writeLightData(ref ExportSettings settings, ref ExportResults results) { if (!LightManager.hasTerrainLightData()) { return; } DateTime n = DateTime.Now; int width = TerrainGlobals.getTerrain().getNumXVerts(); int height = TerrainGlobals.getTerrain().getNumZVerts(); Vector3 [] lht = new Vector3[width * height]; //CLM this needs to be changed for batch exporting! LightManager.rasterTerrainLightsToExportGrid(lht); //convert our data to a DXT1 texture! //CLM this is swapped all to shit... WTF!? byte[] inData = new byte[width * height * 4]; int c = 0; //for (int i = 0; i < lht.Length; i++) for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { //as an encoding step, divide by our overbright (2) //now convert back to srgb int i = x * width + y; Vector3 v = lht[i]; v.X = (float)Math.Sqrt(BMathLib.Clamp((float)(v.X * 0.5), 0, 1)); v.Y = (float)Math.Sqrt(BMathLib.Clamp((float)(v.Y * 0.5), 0, 1)); v.Z = (float)Math.Sqrt(BMathLib.Clamp((float)(v.Z * 0.5), 0, 1)); inData[c++] = (byte)(BMathLib.Clamp(v.Z * 255 + 0.5f, 0, 255)); inData[c++] = (byte)(BMathLib.Clamp(v.Y * 255 + 0.5f, 0, 255)); inData[c++] = (byte)(BMathLib.Clamp(v.X * 255 + 0.5f, 0, 255)); inData[c++] = 0; } } byte[] outDat = null; int outMemSize = 0; ExportTo360.toCompressedFormat(inData, width, height, sizeof(UInt32), BDXTFormat.cDXT1, settings.ExportTextureCompressionQuality, ref outDat, ref outMemSize); //endianswap this data... int count = outMemSize; for (int i = 0; i < count - 1; i += 2) { byte a = outDat[i]; outDat[i] = outDat[i + 1]; outDat[i + 1] = a; } //tileswap byte[] tempbytearray = new byte[outDat.Length]; outDat.CopyTo(tempbytearray, 0); ExportTo360.tileCopy(ref tempbytearray, tempbytearray, (int)width, (int)height, (int)ExportTo360.eTileCopyFormats.cTCFMT_DXT1); tempbytearray.CopyTo(outDat, 0); tempbytearray = null; //WRITE THE CHUNK ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); //just write the DXT1 texture binWriter.Write(Xbox_EndianSwap.endSwapI32(outMemSize)); binWriter.Write(outDat); ExportTo360.mECF.addChunk((int)eXTD_ChunkID.cXTD_LightingChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; results.terrainLightingMemorySize = outMemSize; TimeSpan ts = DateTime.Now - n; results.terrainLightingTime = ts.TotalMinutes; lht = null; inData = null; outDat = null; }
public void writeQNsToChunk(ref ExportResults results) { DateTime n = DateTime.Now; int totalMemory = 0; int width = TerrainGlobals.getTerrain().getNumXVerts(); for (int qi = 0; qi < FoliageManager.getNumChunks(); qi++) { FoliageQNChunk chunk = FoliageManager.getChunk(qi); List <int> setIndexes = new List <int>(); List <int> setPolyCounts = new List <int>(); int totalPhysicalMemory = 0; List <int> indMemSizes = new List <int>(); List <int> bladeIBs = new List <int>(); for (int setI = 0; setI < chunk.mSetsUsed.Count; setI++) { int numBlades = 0; int startIndex = bladeIBs.Count; FoliageSet fs = FoliageManager.giveSet(chunk.mSetsUsed[setI]); //walk through the main grid for our current chunk //pack the data into proper inds.. for (int x = 0; x < BTerrainQuadNode.cMaxWidth; x++) { for (int z = 0; z < BTerrainQuadNode.cMaxWidth; z++) { int index = (x + chunk.mOwnerNodeDesc.mMinXVert) + width * (z + chunk.mOwnerNodeDesc.mMinZVert); FoliageVertData fvd = FoliageManager.mVertData.GetValue(index); if (fvd.compare(FoliageManager.cEmptyVertData)) { continue; } if (FoliageManager.giveIndexOfSet(fvd.mFoliageSetName) == FoliageManager.giveIndexOfSet(chunk.mSetsUsed[setI])) { numBlades++; //our local blade index is transposed on the 360 int localIndex = x * FoliageManager.cNumXBladesPerChunk + z; int bladeIndex = fvd.mFoliageSetBladeIndex << 16; for (short t = 0; t < fs.mNumVertsPerBlade; t++) { int packedID = bladeIndex | (0xFFFF & (localIndex * fs.mNumVertsPerBlade) + t); bladeIBs.Add(packedID); } bladeIBs.Add(0xFFFF); //360 specific tag to stop a strip. } } } int numVerts = bladeIBs.Count - startIndex; if (numVerts == 0) { continue; } setIndexes.Add(FoliageManager.giveIndexOfSet(chunk.mSetsUsed[setI])); setPolyCounts.Add(numBlades * (fs.mNumVertsPerBlade + 1) - 2); indMemSizes.Add(numVerts * sizeof(int)); totalPhysicalMemory += indMemSizes[indMemSizes.Count - 1]; } //now write this chunk.. ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); //our chunk index is transposed in the game int minQNX = (int)(chunk.mOwnerNodeDesc.mMinXVert / BTerrainQuadNode.cMaxWidth); int minQNZ = (int)(chunk.mOwnerNodeDesc.mMinZVert / BTerrainQuadNode.cMaxHeight); int numXChunks = (int)(TerrainGlobals.getTerrain().getNumXVerts() / BTerrainQuadNode.cMaxWidth); int transposedOwnerIndex = minQNX * numXChunks + minQNZ; binWriter.Write(Xbox_EndianSwap.endSwapI32(transposedOwnerIndex));//chunk.mOwnerQNIndex)); binWriter.Write(Xbox_EndianSwap.endSwapI32(setIndexes.Count)); int numSets = setIndexes.Count; for (int i = 0; i < numSets; i++) { binWriter.Write(Xbox_EndianSwap.endSwapI32(setIndexes[i])); } for (int i = 0; i < numSets; i++) { binWriter.Write(Xbox_EndianSwap.endSwapI32(setPolyCounts[i])); } binWriter.Write(Xbox_EndianSwap.endSwapI32(totalPhysicalMemory)); totalMemory += totalPhysicalMemory; for (int i = 0; i < numSets; i++) { binWriter.Write(Xbox_EndianSwap.endSwapI32(indMemSizes[i])); } for (int i = 0; i < bladeIBs.Count; i++) { binWriter.Write(Xbox_EndianSwap.endSwapI32(bladeIBs[i])); } ExportTo360.mECF.addChunk((int)eXTT_ChunkID.cXTT_FoliageQNChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; } TimeSpan ts = DateTime.Now - n; results.terrainFoliageTime = ts.TotalMinutes; results.terrainFoliageMemory = totalMemory; }
private void writeTessData(bool refineTerrain, float eLOD, float minorityBias, ref ExportResults results) { ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); //write the 'header' int nodeWidth = 16; int numXPatches = (int)(TerrainGlobals.getTerrain().getNumXVerts() / (float)nodeWidth); int numZPatches = (int)(TerrainGlobals.getTerrain().getNumXVerts() / (float)nodeWidth); int numXChunks = (int)(TerrainGlobals.getTerrain().getNumXVerts() / (float)BTerrainQuadNode.getMaxNodeDepth()); int numPatches = numXPatches * numZPatches; binWriter.Write(Xbox_EndianSwap.endSwapI32(numXPatches)); binWriter.Write(Xbox_EndianSwap.endSwapI32(numZPatches)); //do this for each patch byte[] tDat = new byte[numPatches]; Vector4[] bbDat = new Vector4[numPatches * 2]; //CLM - instead of writing floating point values (and taking up more memory) //write indexes into our discrete step array if (refineTerrain) { ErrorMetricRefine refiner = null; refiner = new ErrorMetricRefine(); refiner.init(TerrainGlobals.getTerrain().getNumXVerts(), TerrainGlobals.getTerrain().getNumZVerts()); refiner.refine(eLOD);//, nodeWidth + 1); markOverrideTessellations(refiner); for (int x = 0; x < numXPatches; x++) { for (int z = 0; z < numZPatches; z++) { int xMinVert = x * nodeWidth; int zMinVert = z * nodeWidth; tDat[x + z * numXPatches] = giveMaxTesselation(ref refiner, xMinVert, zMinVert, nodeWidth, minorityBias); } } refiner.destroy(); refiner = null; smoothTessNeighbors(tDat, numXPatches, numZPatches); } else { for (int i = 0; i < numPatches; i++) { tDat[i] = 0; } } //write to the disk for (int i = 0; i < tDat.Length; i++) { binWriter.Write(tDat[i]); } //generate and write our bounding boxes for (int x = 0; x < numXPatches; x++) { for (int z = 0; z < numZPatches; z++) { Vector4 min = new Vector4(9000, 9000, 9000, 0); Vector4 max = new Vector4(-9000, -9000, -9000, 0); for (int i = 0; i < nodeWidth + 1; i++) { for (int j = 0; j < nodeWidth + 1; j++) { int xVal = x * nodeWidth + i; int zVal = z * nodeWidth + j; if (xVal >= TerrainGlobals.getTerrain().getNumXVerts() || zVal >= TerrainGlobals.getTerrain().getNumXVerts()) { continue; } long kIndex = xVal + TerrainGlobals.getTerrain().getNumXVerts() * zVal; Vector3 v = TerrainGlobals.getTerrain().getPos(xVal, zVal); if (v.X < min.X) { min.X = v.X; } if (v.Y < min.Y) { min.Y = v.Y; } if (v.Z < min.Z) { min.Z = v.Z; } if (v.X > max.X) { max.X = v.X; } if (v.Y > max.Y) { max.Y = v.Y; } if (v.Z > max.Z) { max.Z = v.Z; } } } //NOTE: THE GAME EXPECTS THIS DATA IN NON-SWIZZLED FORM int q = x + z * numZPatches; q *= 2; bbDat[q] = min; bbDat[q + 1] = max; } } for (int i = 0; i < bbDat.Length; i++) { binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].X)); binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].Y)); binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].Z)); binWriter.Write(Xbox_EndianSwap.endSwapF32(bbDat[i].W)); } ExportTo360.mECF.addChunk((int)eXTD_ChunkID.cXTD_TessChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; results.terrainTessValuesMemorySize = tDat.Length + (bbDat.Length * sizeof(float) * 4); tDat = null; bbDat = null; }