//----------------------------------------------------------------------------------- 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; }
//----------------------------------------------------------------------------------- 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 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 int writeBuildable() { ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); BTerrainSimRep simRep = TerrainGlobals.getEditor().getSimRep(); // Write buildable bool[] landBuildable = simRep.getDataTiles().getSimLandBuildable(); int numTiles = simRep.getNumXTiles(); byte tru = 0xFF; byte fal = 0x00; for (int x = 0; x < numTiles; x++) { for (int z = 0; z < numTiles; z++) { int index = (x * numTiles + z); if (landBuildable[index]) { binWriter.Write(tru); } else { binWriter.Write(fal); } } } ExportTo360.mECF.addChunk((int)eXSD_ChunkID.cXSD_Buildable, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; return(landBuildable.Length * sizeof(byte)); }
//----------------------------------------- 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; }
public void writeAOData(ref ExportResults results) { //WRITE THE CHUNK ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); byte[] data = packAOToDXT5A(TerrainGlobals.getEditor().getAmbientOcclusionValues(), TerrainGlobals.getTerrain().getNumXVerts()); for (int i = 0; i < data.Length; i++) { binWriter.Write(data[i]); } results.terrainAOMemorySize = data.Length; data = null; ExportTo360.mECF.addChunk((int)eXTD_ChunkID.cXTD_AOChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; }
void writeAlpha(ref ExportResults results) { //WRITE THE CHUNK ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); #region DXT5Alpha byte[] dataAlpha = packAlphaToDXT5A(TerrainGlobals.getEditor().getAlphaValues(), TerrainGlobals.getTerrain().getNumXVerts()); for (int i = 0; i < dataAlpha.Length; i++) { binWriter.Write(dataAlpha[i]); } results.terrainAlphaMemorySize = dataAlpha.Length; dataAlpha = null; #endregion ExportTo360.mECF.addChunk((int)eXTD_ChunkID.cXTD_AlphaChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; }
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; }
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 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 generateGridChunks(ref XTDVisualHeader header) { //Create and write our flat terrain quadnode chunks BTerrainQuadNode[] mLeafNodes = TerrainGlobals.getTerrain().getQuadNodeLeafArray(); for (int i = 0; i < mLeafNodes.Length; i++) { int width = (int)BTerrainQuadNode.getMaxNodeWidth(); ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); XTDTerrainChunk gridNode = new XTDTerrainChunk(); int locX = mLeafNodes[i].getDesc().mMinXVert / width; int locZ = mLeafNodes[i].getDesc().mMinZVert / width; gridNode.gridLocX = locX; gridNode.gridLocZ = locZ; //calculate our chunk data gridNode.heightmapOnly = false; gridNode.maxVertStride = 64; //lets get our verts, normals, and ambOcclu int mnX = locX * width; int mnZ = locZ * width; BBoundingBox bb = new BBoundingBox(); bb.empty(); for (int z = 0; z < width + 1; z++) { for (int x = 0; x < width + 1; x++) { int xVal = (int)(mnX + x); int zVal = (int)(mnZ + z); Vector3 v = TerrainGlobals.getTerrain().getPos(xVal, zVal); bb.addPoint(v); } } gridNode.mMin = bb.min; gridNode.mMax = bb.max; //IF WE CONTAIN FOLIAGE! increase the size of our bounding boxes.. if (FoliageManager.isChunkUsed(mLeafNodes[i])) { BBoundingBox bbA = FoliageManager.giveMaxBBs(); gridNode.mMin += bbA.min; gridNode.mMax += bbA.max; } //expand our box a tad float scle = TerrainGlobals.getTerrain().getTileScale(); gridNode.mMin -= new Vector3(scle, scle, scle); gridNode.mMax += new Vector3(scle, scle, scle); //send the verts off to the compressor to be compressed properly into an image (using whatever technique) //be sure to assign a corolary ID so we can reference it later. writeChunk(gridNode, binWriter); //add this chunk to our main data stream ExportTo360.mECF.addChunk((int)eXTD_ChunkID.cXTD_TerrainChunk, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; } mLeafNodes = 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; } }
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)); }
private int writeTileType() { ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); BTerrainSimRep simRep = TerrainGlobals.getEditor().getSimRep(); // Write tile types int numTiles = simRep.getNumXTiles(); int obstructionArraySize = numTiles * numTiles; SimTerrainType.loadTerrainTileTypes(); int tileTypeArraySize = obstructionArraySize; byte[] tileTypeArray = new byte[tileTypeArraySize]; for (int x = 0; x < numTiles; x++) { for (int z = 0; z < numTiles; z++) { int index = (x * numTiles + z); //if we have a tile type override, use it int typeOverride = TerrainGlobals.getEditor().getSimRep().getDataTiles().getJaggedTileType(z, x); if (typeOverride > 0) { tileTypeArray[index] = (byte)typeOverride; } else { // Get each tile's dominant texture index int dominantTextureIndex = TerrainGlobals.getEditor().giveDominantTextureAtTile(x, z, simRep); tileTypeArray[index] = 0; if (dominantTextureIndex != -1) { byte numTypes = (byte)SimTerrainType.mTerrainTileTypes.mTypes.Count; string dominantTextureType = SimTerrainType.mTextureList[dominantTextureIndex].TileType; // Find the dominant texture's type for (byte typeIndex = 0; typeIndex < numTypes; typeIndex++) { if (SimTerrainType.mTerrainTileTypes.mTypes[typeIndex].Name == dominantTextureType) { tileTypeArray[index] = typeIndex; break; } } } } } } binWriter.Write(tileTypeArray); ExportTo360.mECF.addChunk((int)eXSD_ChunkID.cXSD_TileTypes, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; return(tileTypeArray.Length); }
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; }
private int writeObstructions() { ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); BTerrainSimRep simRep = TerrainGlobals.getEditor().getSimRep(); // Write obstructions bool[] landObstructions = simRep.getDataTiles().getSimLandObstructions(); int numTiles = simRep.getNumXTiles(); int obstructionArraySize = numTiles * numTiles; byte[] obstructionsFlags = new byte[obstructionArraySize]; bool[] alreadyDone = new bool[numTiles * numTiles]; for (int i = 0; i < numTiles * numTiles; i++) { alreadyDone[i] = false; } for (int x = 0; x < numTiles; x++) { for (int z = 0; z < numTiles; z++) { int index = (x * numTiles + z); bool obstructsLand = simRep.getDataTiles().isLandObstructedComposite(x, z); bool obstructsFlood = simRep.getDataTiles().isFloodObstructed(x, z); bool obstructsScarab = simRep.getDataTiles().isScarabObstructed(x, z); obstructionsFlags[index] = 0; if (obstructsLand && obstructsFlood && obstructsScarab) { obstructionsFlags[index] = (byte)BTerrainSimRep.eObstructionType.cObstrtuction_Land_Flood_Scarab; } else if (obstructsLand && obstructsFlood && !obstructsScarab) { obstructionsFlags[index] = (byte)BTerrainSimRep.eObstructionType.cObstrtuction_Land_Flood; } else if (obstructsLand && !obstructsFlood && obstructsScarab) { obstructionsFlags[index] = (byte)BTerrainSimRep.eObstructionType.cObstrtuction_Land_Scarab; } else if (obstructsLand && !obstructsFlood && !obstructsScarab) { obstructionsFlags[index] = (byte)BTerrainSimRep.eObstructionType.cObstrtuction_Land; } else if (!obstructsLand && obstructsFlood && obstructsScarab) { obstructionsFlags[index] = (byte)BTerrainSimRep.eObstructionType.cObstrtuction_Flood_Scarab; } else if (!obstructsLand && obstructsFlood && !obstructsScarab) { obstructionsFlags[index] = (byte)BTerrainSimRep.eObstructionType.cObstrtuction_Flood; } else if (!obstructsLand && !obstructsFlood && obstructsScarab) { obstructionsFlags[index] = (byte)BTerrainSimRep.eObstructionType.cObstrtuction_Scarab; } else if (!obstructsLand && !obstructsFlood && !obstructsScarab) { obstructionsFlags[index] = (byte)BTerrainSimRep.eObstructionType.cNoObstruction; } } } binWriter.Write(obstructionsFlags); ExportTo360.mECF.addChunk((int)eXSD_ChunkID.cXSD_Obstructions, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; return(obstructionsFlags.Length); }
private int simHeightsToChunk() { ECF.ECFChunkHolder chunkHolder = new ECF.ECFChunkHolder(); chunkHolder.mDataMemStream = new MemoryStream(); BinaryWriter binWriter = new BinaryWriter(chunkHolder.mDataMemStream); int width = (TerrainGlobals.getEditor().getSimRep().getNumXVerts() - 1) * cSimHeightResMultiplier + 1; //float[] heights = TerrainGlobals.getEditor().getSimRep().getHeightRep().get.getSimHeights(); //CLM : INFACT! Don't even consider doing this.... //our res is good enough.. //if (cSimHeightResMultiplier!=1) //{ // heights = new float[width * width]; // //CLM Generate a higher res Sim Heights rep // int xRes = 2048; // float[] gpuHeightRepArray = new float[xRes * xRes]; // TerrainGlobals.getEditor().getSimRep().genHeightGPU(xRes, ref gpuHeightRepArray); // float[] resPlusOne = ImageManipulation.resizeF32Img(gpuHeightRepArray, xRes, xRes, width - 1, width - 1, ImageManipulation.eFilterType.cFilter_Linear);//new float[xRes * xRes]; // for (int x = 0; x < width - 1; x++) // { // for (int z = 0; z < width - 1; z++) // { // heights[x * width + z] = resPlusOne[x * (width - 1) + z]; // } // } // //fill our edges with the previous height val. // for (int q = 0; q < width - 1; q++) // { // heights[(width - 1) * width + q] = heights[(width - 2) * width + q]; // heights[q * width + (width - 1)] = heights[q * width + (width - 2)]; // } // resPlusOne = null; //} //find our xbox specific terrain representation (close) float min = 9000; float max = -9000; float range = 0; findMaxsMinsRange(ref max, ref min, ref range); float adjustedMid = calcAdjustedMidValue(min); int numXBlocks = width / 8; if (width % 8 != 0) { numXBlocks++; } int newWidth = numXBlocks * 8; //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 srcIndex = i + k * width; int dstIndex = i + k * newWidth; tvals[dstIndex] = TerrainGlobals.getEditor().getSimRep().getHeightRep().getCompositeHeight(k, i);//heights[srcIndex]; // int v = (int)packPosTo32Bits(tvals[dstIndex], min, range); // unpackVisualToPos(v, ref tvals[dstIndex], ref adjustedMid, ref range); } } ////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]; } } } } //FileStream st = File.Open("outTT.raw", FileMode.OpenOrCreate, FileAccess.Write); //BinaryWriter ft = new BinaryWriter(st); //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)); //ft.Write(s); } //ft.Close(); //st.Close(); ExportTo360.mECF.addChunk((int)eXSD_ChunkID.cXSD_SimHeights, chunkHolder, binWriter.BaseStream.Length); binWriter.Close(); binWriter = null; chunkHolder.Close(); chunkHolder = null; //heights = null; return(tvals.Length * sizeof(ushort)); }
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; }