//----------------------------------------------------------------------------------- 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 static byte[] packAOToDXT5A(float[] AoVals, int numXVerts) { byte[] inData = new byte[AoVals.Length * 4]; int c = 0; for (int x = 0; x < numXVerts; x++) { for (int z = 0; z < numXVerts; z++) { int dstIndex = 4 * (x * numXVerts + z); int srcIndex = (x + numXVerts * z); float k = AoVals[srcIndex] > 1 ? 1 : AoVals[srcIndex]; inData[dstIndex + 0] = 1; inData[dstIndex + 1] = 1; inData[dstIndex + 2] = 1; inData[dstIndex + 3] = (byte)(k * 255); } } //for (int i = 0; i < AoVals.Length; i++) //{ // float k = AoVals[i] > 1 ? 1 : AoVals[i]; // inData[c++] = 1; // inData[c++] = 1; // inData[c++] = 1; // inData[c++] = (byte)(k * 255); //} byte[] outDat = null; int outMemSize = 0; ExportTo360.toCompressedFormat(inData, numXVerts, numXVerts, sizeof(UInt32), BDXTFormat.cDXT5A, eDXTQuality.cDXTQualityBest, 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; } //swizzle this data inData = null; return(outDat); }
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; }
public unsafe bool export_XSD(string filename, ExportSettings expSettings, ref Export360.ExportResults results) { DateTime n = DateTime.Now; //update before we do anything TerrainGlobals.getEditor().getSimRep().updateForExport();// update(false);// headerToChunk(); results.terrainSimMemorySize = simDataToChunk(); bool exportOK = ExportTo360.safeECFFileWrite(filename, ".XSD"); TimeSpan ts = DateTime.Now - n; results.terrainSimTime = ts.TotalMinutes; return(exportOK); }
//----------------------------------------------------------------------------------- public bool export_XTH(string filename, ExportSettings expSettings, ref ExportResults results) { DateTime n = DateTime.Now; HeightsGen hg = new HeightsGen(); hg.computeHeightField(256, 256, true, BMathLib.unitZ, 8); headerToChunk(); heightFieldToChunk(hg, ref results); //turn our data into a ECF chunk heightFieldAlphaToChunk(ref results); bool exportOK = ExportTo360.safeECFFileWrite(filename, ".XTH"); hg.destroy(); TimeSpan ts = DateTime.Now - n; results.terrainGPUHeighfieldTime = ts.TotalMinutes; return(exportOK); }
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 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 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); }
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; }