Example #1
0
        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));
            }
        }
Example #2
0
        List <Image> splitImg(Bitmap mainImage, int numSegments, FoliageSet fs)
        {
            List <Image> images = new List <Image>();

            for (int i = 0; i < fs.mNumBlades; i++)
            {
                Vector2 min = new Vector2(float.MaxValue, float.MaxValue);
                Vector2 max = new Vector2(float.MinValue, float.MinValue);

                //get the UV bounds for this blade
                for (int k = 0; k < fs.mNumVertsPerBlade; k++)
                {
                    if (fs.mFoliageBlades[i].uvs[k].X < min.X)
                    {
                        min.X = fs.mFoliageBlades[i].uvs[k].X;
                    }
                    if (fs.mFoliageBlades[i].uvs[k].Y < min.Y)
                    {
                        min.Y = fs.mFoliageBlades[i].uvs[k].Y;
                    }

                    if (fs.mFoliageBlades[i].uvs[k].X > max.X)
                    {
                        max.X = fs.mFoliageBlades[i].uvs[k].X;
                    }
                    if (fs.mFoliageBlades[i].uvs[k].Y > max.Y)
                    {
                        max.Y = fs.mFoliageBlades[i].uvs[k].Y;
                    }
                }

                //convert it to integers
                Point     mnI  = new Point((int)(min.X * mainImage.Width), (int)(min.Y * mainImage.Height));
                Point     mxI  = new Point((int)(max.X * mainImage.Width), (int)(max.Y * mainImage.Height));
                int       w    = mxI.X - mnI.X;
                int       h    = mxI.Y - mnI.Y;
                Rectangle rect = new Rectangle(mnI.X, mnI.Y, w, h);
                images.Add(Copy(mainImage, rect));
            }
            return(images);
        }
Example #3
0
        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;
        }
Example #4
0
        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));
            }
        }