private void eraseAllButton_Click(object sender, EventArgs e) { if (MessageBox.Show("This will erase ALL foliage on the map. Are you sure?", "Are you sure?", MessageBoxButtons.OKCancel) == DialogResult.OK) { FoliageManager.eraseAllFoliage(); } }
void SelectButton(FoliageBladeButton but) { if (mSelectedButton != null) { mSelectedButton.Invalidate(); } mSelectedButton = but; mSelectedButton.Invalidate(); if (paintSet.Checked) { TerrainGlobals.getEditor().setMode(BTerrainEditor.eEditorMode.cModeFoliageSet); } else if (paintErase.Checked) { TerrainGlobals.getEditor().setMode(BTerrainEditor.eEditorMode.cModeFoliageErase); } int selectedSetIndex = FoliageManager.giveIndexOfSet(mSelectedButton.mFullFileName); int selectedBladeIndex = mSelectedButton.mIndexInConatiningSet; FoliageManager.SelectedSetIndex = selectedSetIndex; FoliageManager.SelectedBladeIndex = selectedBladeIndex; TerrainGlobals.getEditor().newFoliageBrush(); CoreGlobals.getEditorMain().MainMode = BEditorMain.eMainMode.cTerrain; CoreGlobals.getEditorMain().mPhoenixScenarioEditor.HandleCommand("Foliage Paint"); }
void displayFoliageSet(string foliageSetName) { string fullFileName = CoreGlobals.getWorkPaths().mFoliagePath + "\\" + foliageSetName; FoliageSet fs = null; int setIndex = FoliageManager.newSet(fullFileName); fs = FoliageManager.giveSet(setIndex); //load our image for display if (!File.Exists(fullFileName + "_df.ddx")) { MessageBox.Show(fullFileName + "_df.ddx Not found for this foliage set. Please ensure it exists."); return; } Texture tex = TextureLoader.FromFile(BRenderDevice.getDevice(), fullFileName + "_df.tga"); Image img = Image.FromStream(TextureLoader.SaveToStream(ImageFileFormat.Bmp, tex)); tex.Dispose(); tex = null; Bitmap mainImage = new Bitmap(img); //now, split us into X sub images to display. int numsections = fs.mNumBlades; List <Image> images = splitImg(mainImage, numsections, fs);// splitImgHorizontally(mainImage, numsections); for (int i = 0; i < numsections; i++) { flowLayoutPanel1.Controls.Add(new FoliageBladeButton(images[i].Width, images[i].Height, images[i], fullFileName, i, this)); } }
private void removeFromMapToolStripMenuItem_Click(object sender, EventArgs e) { int index = FoliageManager.giveIndexOfSet(CoreGlobals.getWorkPaths().mFoliagePath + "\\" + foliageListBox.SelectedItem.ToString()); if (index != -1) { FoliageManager.eraseSetFromMap(index); } }
private void removeFromMaToolStripMenuItem_Click(object sender, EventArgs e) { int setindex = FoliageManager.giveIndexOfSet(CoreGlobals.getWorkPaths().mFoliagePath + "\\" + foliageListBox.SelectedItem.ToString()); if (setindex == -1 || mSelectedButton == null) { return; } FoliageManager.eraseBladeFromMap(setindex, mSelectedButton.mIndexInConatiningSet); }
public void exportFoliage(ref ExportResults results) { if (FoliageManager.getNumChunks() == 0) { return; } FoliageManager.removeUnusedSets(); //write our headers.. writeHeaderToChunk(); writeQNsToChunk(ref results); }
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 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; }
static void estimateTerrainMemory() { using (PerfSection p3 = new PerfSection("estimateTerrainMemory")) { int width = TerrainGlobals.getTerrain().getNumXVerts(); //CLM THESE ESTIMATES ARE VALID AS OF [07.24.07] ///XTD //positions & normals - each component is 32bit mMemoryUsageItems.Add(new memoryElement("Terrain Positions & Normals", (width * width * 8), eMainCatagory.eCat_Terrain)); //ALPHA - DXT5A mMemoryUsageItems.Add(new memoryElement("Terrain Alpha", ((width >> 2) * (width >> 2) * 8), eMainCatagory.eCat_Terrain)); //AO - DXT5A mMemoryUsageItems.Add(new memoryElement("Terrain AO", ((width >> 2) * (width >> 2) * 8), eMainCatagory.eCat_Terrain)); //TessData int nodeWidth = 16; int numXPatches = (int)(TerrainGlobals.getTerrain().getNumXVerts() / (float)nodeWidth); int tessMem = numXPatches * numXPatches; tessMem += (numXPatches * numXPatches * 2) * (sizeof(float) * 4); mMemoryUsageItems.Add(new memoryElement("Terrain Tessellation", tessMem, eMainCatagory.eCat_Terrain)); //light data - DXT1 if (LightManager.hasTerrainLightData()) { mMemoryUsageItems.Add(new memoryElement("Terrain Precomputed Lighting", ((width * width) >> 2), eMainCatagory.eCat_Terrain)); } //////XTT //texture alpha data int texAlphaMem = 0; BTerrainQuadNode[] nodes = TerrainGlobals.getTerrain().getQuadNodeLeafArray(); for (int i = 0; i < nodes.Length; i++) { int numAlignedSplatLayers = 4 * (((nodes[i].mLayerContainer.getNumSplatLayers() - 1) >> 2) + 1); int numAlignedDecalLayers = 4 * (((nodes[i].mLayerContainer.getNumDecalLayers() - 1) >> 2) + 1); texAlphaMem += numAlignedSplatLayers * ((64 * 64) >> 2); } mMemoryUsageItems.Add(new memoryElement("Terrain Texture Blends", texAlphaMem, eMainCatagory.eCat_Terrain)); //unique Albedo int uniqueTextureRes = 128; int uniqueWidth = (int)((width / BTerrainQuadNode.cMaxWidth) * uniqueTextureRes); int uniqueMemSize = (int)(uniqueWidth * uniqueWidth); if (BMathLib.isPow2(uniqueWidth)) { uniqueMemSize += (uniqueWidth >> 1) * (uniqueWidth >> 1); } mMemoryUsageItems.Add(new memoryElement("Terrain Unique Albedo Texture", (uniqueMemSize >> 1), eMainCatagory.eCat_Terrain)); //FOLIAGE int totalPhysicalMemory = 0; for (int qi = 0; qi < FoliageManager.getNumChunks(); qi++) { FoliageQNChunk chunk = FoliageManager.getChunk(qi); for (int setI = 0; setI < chunk.mSetsUsed.Count; setI++) { int numBlades = 0; 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++; totalPhysicalMemory += (fs.mNumVertsPerBlade + 1) * sizeof(int); } } } } } mMemoryUsageItems.Add(new memoryElement("Terrain Foliage", totalPhysicalMemory, eMainCatagory.eCat_Terrain)); //ROADS /////XTH mMemoryUsageItems.Add(new memoryElement("Terrain Decal Rep", 256 * 256 * sizeof(short) * 2, eMainCatagory.eCat_Terrain)); //CACHES //add in our 360 cache data int cacheMemCount = 0; const int numCachePages = 20; const int cachePageSize = 512; const int numMips = 2; bool albedoCache = true; bool normalCache = true; bool specCache = false; bool selfCache = false; bool envCache = false; for (int i = 0; i < TerrainGlobals.getTexturing().getActiveTextureCount(); i++) { BTerrainActiveTextureContainer ActTex = TerrainGlobals.getTexturing().getActiveTexture(i); String fname = ActTex.mFilename; String ext = ".ddx";// Path.GetExtension(fname); string sname = fname.Substring(0, fname.LastIndexOf("_df")) + "_em" + ext; selfCache |= File.Exists(sname); sname = fname.Substring(0, fname.LastIndexOf("_df")) + "_rm" + ext; envCache |= File.Exists(sname); sname = fname.Substring(0, fname.LastIndexOf("_df")) + "_sp" + ext; specCache |= File.Exists(sname); } for (int i = 0; i < TerrainGlobals.getTexturing().getActiveDecalCount(); i++) { BTerrainActiveDecalContainer ActTex = TerrainGlobals.getTexturing().getActiveDecal(i); String fname = ActTex.mFilename; String ext = ".ddx";// Path.GetExtension(fname); string sname = fname.Substring(0, fname.LastIndexOf("_df")) + "_em" + ext; selfCache |= File.Exists(sname); sname = fname.Substring(0, fname.LastIndexOf("_df")) + "_rm" + ext; envCache |= File.Exists(sname); sname = fname.Substring(0, fname.LastIndexOf("_df")) + "_sp" + ext; specCache |= File.Exists(sname); } if (albedoCache) { cacheMemCount += giveTextureCacheMemoryRequirement(numCachePages, cachePageSize, numMips, 0); //DXT1 * numCachePages (mip0 & mip1) } if (normalCache) { cacheMemCount += giveTextureCacheMemoryRequirement(numCachePages, cachePageSize, numMips, 1); } ; //DXN if (specCache) { cacheMemCount += giveTextureCacheMemoryRequirement(numCachePages, cachePageSize, numMips, 0); //DXT1 } if (envCache) { cacheMemCount += giveTextureCacheMemoryRequirement(numCachePages, cachePageSize, numMips, 0); //DXT1 } if (selfCache) { cacheMemCount += giveTextureCacheMemoryRequirement(numCachePages, cachePageSize, numMips, 1); //DXT5 } mMemoryUsageItems.Add(new memoryElement("Terrain Texture Cache", cacheMemCount, eMainCatagory.eCat_Terrain)); //ARTIST TERRAIN TEXTURES int totalMemTT = 0; for (int i = 0; i < TerrainGlobals.getTexturing().getActiveTextureCount(); i++) { totalMemTT += TerrainGlobals.getTexturing().getActiveTexture(i).m360MemoryFootprint; } for (int i = 0; i < TerrainGlobals.getTexturing().getActiveDecalCount(); i++) { totalMemTT += TerrainGlobals.getTexturing().getActiveDecal(i).m360MemoryFootprint; } mMemoryUsageItems.Add(new memoryElement("Terrain Artist Textures", totalMemTT, eMainCatagory.eCat_Terrain)); } }
void Awake() { instance = this; DontDestroyOnLoad(gameObject); }
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; }