public void SaveDataToFileCaches(int bitMask, VFTile tile, double[][] nData, float[][] hData, float[][] gData, RandomMapType[][] tData)
    {
        if (_voxelTileCachesFS == null)
        {
            return;
        }

        IntVector4 xzlh = new IntVector4(tile.tileX, tile.tileZ, tile.tileL, tile.tileH);

        if (_voxelTileCacheDescsList.ContainsKey(xzlh))
        {
            Debug.LogWarning("[VFDataRTGen]:Try to append a existing voxel tile to cache file." + xzlh);
            return;
        }
        try
        {
            _voxelTileCachesFS.Seek(0, SeekOrigin.End); //Append
            VFTerTileCacheDesc desc = VFTerTileCacheDesc.WriteDataToCache(_bw, bitMask, tile, nData, hData, gData, tData);
            _voxelTileCacheDescsList.Add(xzlh, desc);
        }
        catch (Exception e)
        {
            string strE = e.ToString();
            Debug.LogWarning("[VFDataRTGen]:Failed to append voxel tile to cache file" + xzlh + e);
            if (strE.Contains("IOException: Win32 IO returned 112."))
            {
                GameLog.HandleExceptionInThread(e);
            }
        }
    }
    public VFTerTileCacheDesc FillTileDataWithFileCache(IntVector4 xzlh, VFTile tile, double[][] nData, float[][] hData, float[][] gData, RandomMapType[][] tData)
    {
        VFTerTileCacheDesc desc = null;

        if (_voxelTileCacheDescsList.TryGetValue(xzlh, out desc))
        {
            try
            {
                desc.ReadDataFromCache(_br, tile, nData, hData, gData, tData);
            }
            catch
            {
                Debug.LogWarning("[VFDataRTGen]Error:Failed to read data from cache " + xzlh);
                return(null);
            }
        }
        return(desc);
    }
    public void PlantVegetation(VFTile terTile, double[][] tileNoiseBuf, float[][] tileHeightBuf, float[][] tileGradTanBuf,
                                List <TreeInfo> outlstTreeInfo, List <VoxelGrassInstance> outlstGrassInst, RandomMapType[][] tileMapType, int szCell)
    {
        int startX = terTile.tileX << VoxelTerrainConstants._shift;
        int startZ = terTile.tileZ << VoxelTerrainConstants._shift;
        int iScl   = 1 << terTile.tileL;

        for (int iz = 0; iz < VoxelTerrainConstants._numVoxelsPerAxis; iz += szCell)
        {
            int      idxZ        = iz + VoxelTerrainConstants._numVoxelsPrefix;
            double[] xNoiseBuf   = tileNoiseBuf[idxZ];
            float[]  xHeightBuf  = tileHeightBuf[idxZ];
            float[]  xGradTanBuf = tileGradTanBuf[idxZ];
            byte[][] xyVoxels    = terTile.terraVoxels[idxZ];
            for (int ix = 0; ix < VoxelTerrainConstants._numVoxelsPerAxis; ix += szCell)
            {
                int    idxX    = ix + VoxelTerrainConstants._numVoxelsPrefix;
                float  fy      = xHeightBuf[idxX];
                byte[] yVoxels = xyVoxels[idxX];
                byte   vType   = yVoxels[((int)fy) * VFVoxel.c_VTSize + 1];
                if (VFDataRTGen.IsNoPlantType(vType))
                {
                    continue;
                }

                curRegion = prms.RegionDescArrayValues[MapTypeToRegionId(tileMapType[iz][ix])];

                VoxelPaintXML.PlantDescArrayCLS veges0 = curRegion.trees;
                VoxelPaintXML.PlantDescArrayCLS veges1 = curRegion.grasses;
                VoxelPaintXML.PlantDescArrayCLS veges2 = curRegion.newgrasses;

                VoxelPaintXML.PlantHeightDesc treeHeight     = null;
                VoxelPaintXML.PlantHeightDesc grassHeight    = null;
                VoxelPaintXML.PlantHeightDesc newGrassHeight = null;

                VoxelPaintXML.PlantGradientDesc treeGradient     = null;
                VoxelPaintXML.PlantGradientDesc grassGradient    = null;
                VoxelPaintXML.PlantGradientDesc newGrassGradient = null;

                double noise256 = (xNoiseBuf[idxX] + 1) * 128;
                float  gradTan  = xGradTanBuf[idxX];

                //坡度大于60度草树皆不刷
                if (gradTan >= noVegeTan1)
                {
                    continue;
                }
                if (gradTan < noVegeTan0)
                {
                    if (veges0 != null)
                    {
                        //树的空间单位
                        if (0 == ix % veges0.cellSize && 0 == iz % veges0.cellSize)
                        {
                            bool bTree = false;
                            if (noise256 >= veges0.start || (noise256 > veges0.startFadeIn && myRand.NextDouble() <= (noise256 - veges0.startFadeIn) / (veges0.start - veges0.startFadeIn)))
                            {
                                bTree = true;
                            }

                            if (bTree)
                            {
                                for (int i = 0; i < veges0.PlantHeightDescValues.Length; i++)
                                {
                                    VoxelPaintXML.PlantHeightDesc heightDesc = veges0.PlantHeightDescValues [i];
                                    if (heightDesc.start <= fy && heightDesc.end > fy)
                                    {
                                        treeHeight = heightDesc;
                                    }
                                }
                                if (treeHeight != null)
                                {
                                    for (int i = 0; i < treeHeight.PlantGradientDescValues.Length; i++)
                                    {
                                        VoxelPaintXML.PlantGradientDesc GradientDesc = treeHeight.PlantGradientDescValues [i];
                                        if (GradientDesc.start <= gradTan && GradientDesc.end > gradTan)
                                        {
                                            treeGradient = GradientDesc;
                                        }
                                    }
                                    PlantAVegetation(startX, startZ, ix, iz, iScl, treeGradient.PlantDescArrayValues, tileHeightBuf, 5.0f, outlstTreeInfo);
                                }
                            }
                        }
                    }
                }


                //坡度大于45度不刷草药
                //if (gradTan >= noVegeTan0) continue;
                if (gradTan < noVegeTan3)
                {
                    if (veges1 != null)
                    {
                        //旧草的空间单位
                        if (0 == ix % veges1.cellSize && 0 == iz % veges1.cellSize)
                        {
                            if (noise256 >= veges1.start || (noise256 > veges1.startFadeIn && myRand.NextDouble() <= (noise256 - veges1.startFadeIn) / (veges1.start - veges1.startFadeIn)))
                            {
                                foreach (VoxelPaintXML.PlantHeightDesc heightDesc in veges1.PlantHeightDescValues)
                                {
                                    if (heightDesc.start <= fy && heightDesc.end > fy)
                                    {
                                        grassHeight = heightDesc;
                                    }
                                }
                                if (grassHeight != null)
                                {
                                    foreach (VoxelPaintXML.PlantGradientDesc GradientDesc in grassHeight.PlantGradientDescValues)
                                    {
                                        if (GradientDesc.start <= gradTan && GradientDesc.end > gradTan)
                                        {
                                            grassGradient = GradientDesc;
                                        }
                                    }
                                    if (grassGradient != null)
                                    {
                                        PlantAVegetation(startX, startZ, ix, iz, iScl, grassGradient.PlantDescArrayValues, tileHeightBuf, 1.7f, outlstTreeInfo);
                                    }
                                }
                            }
                        }
                    }
                }

                // legacy grass
                // new grass

                // greed>30 no new grass
                if (gradTan >= noVegeTan2)
                {
                    continue;
                }
                if (veges2 != null)
                {
                    //新草的空间单位
                    if (0 == ix % veges2.cellSize && 0 == iz % veges2.cellSize)
                    {
                        if (noise256 >= veges2.start || (noise256 > veges2.startFadeIn && myRand.NextDouble() <= (noise256 - veges2.startFadeIn) / (veges2.start - veges2.startFadeIn)))
                        {
                            foreach (VoxelPaintXML.PlantHeightDesc heightDesc in veges2.PlantHeightDescValues)
                            {
                                if (heightDesc.start <= fy && heightDesc.end > fy)
                                {
                                    newGrassHeight = heightDesc;
                                }
                            }
                            if (newGrassHeight != null)
                            {
                                foreach (VoxelPaintXML.PlantGradientDesc GradientDesc in newGrassHeight.PlantGradientDescValues)
                                {
                                    if (GradientDesc.start <= gradTan && GradientDesc.end > gradTan)
                                    {
                                        newGrassGradient = GradientDesc;
                                    }
                                }
                                if (newGrassGradient != null)
                                {
                                    float fDensity = ((float)noise256 - veges2.startFadeIn) / (veges0.start - veges0.startFadeIn);
                                    if (fDensity > 1.0f)
                                    {
                                        fDensity = 1.0f;
                                    }
                                    PlantANewGrass(startX, startZ, ix, iz, fDensity, newGrassGradient.PlantDescArrayValues, tileHeightBuf, outlstGrassInst);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    public void PlantGrass(VFTile terTile, double[][] tileNoiseBuf, float[][] tileHeightBuf, float[][] tileGradTanBuf,
                           List <VoxelGrassInstance> outlstGrassInst, RandomMapType[][] tileMapType, int szCell)
    {
        int startX = terTile.tileX << VoxelTerrainConstants._shift;
        int startZ = terTile.tileZ << VoxelTerrainConstants._shift;

        //int iScl = 1 << terTile.tileL;
        for (int iz = 0; iz < VoxelTerrainConstants._numVoxelsPerAxis; iz += szCell)
        {
            int      idxZ        = iz + VoxelTerrainConstants._numVoxelsPrefix;
            double[] xNoiseBuf   = tileNoiseBuf[idxZ];
            float[]  xHeightBuf  = tileHeightBuf[idxZ];
            float[]  xGradTanBuf = tileGradTanBuf[idxZ];
            byte[][] xyVoxels    = terTile.terraVoxels[idxZ];
            for (int ix = 0; ix < VoxelTerrainConstants._numVoxelsPerAxis; ix += szCell)
            {
                int    idxX    = ix + VoxelTerrainConstants._numVoxelsPrefix;
                float  fy      = xHeightBuf[idxX];
                byte[] yVoxels = xyVoxels[idxX];
                byte   vType   = yVoxels[((int)fy) * VFVoxel.c_VTSize + 1];
                if (VFDataRTGen.IsNoPlantType(vType))
                {
                    continue;
                }

                float gradTan = xGradTanBuf[idxX];
                //坡度大于60度草树皆不刷
                if (gradTan >= noVegeTan1)
                {
                    continue;
                }
                // greed>30 no new grass
                if (gradTan >= noVegeTan2)
                {
                    continue;
                }

                curRegion = prms.RegionDescArrayValues[MapTypeToRegionId(tileMapType[iz][ix])];
                VoxelPaintXML.PlantDescArrayCLS veges2 = curRegion.newgrasses;
                if (veges2 != null)
                {
                    //新草的空间单位
                    if (0 == ix % veges2.cellSize && 0 == iz % veges2.cellSize)
                    {
                        double noise256 = (xNoiseBuf[idxX] + 1) * 128;
                        if (noise256 >= veges2.start || (noise256 > veges2.startFadeIn && myRand.NextDouble() <= (noise256 - veges2.startFadeIn) / (veges2.start - veges2.startFadeIn)))
                        {
                            VoxelPaintXML.PlantHeightDesc   newGrassHeight   = null;
                            VoxelPaintXML.PlantGradientDesc newGrassGradient = null;
                            foreach (VoxelPaintXML.PlantHeightDesc heightDesc in veges2.PlantHeightDescValues)
                            {
                                if (heightDesc.start <= fy && heightDesc.end > fy)
                                {
                                    newGrassHeight = heightDesc;
                                }
                            }
                            if (newGrassHeight != null)
                            {
                                foreach (VoxelPaintXML.PlantGradientDesc GradientDesc in newGrassHeight.PlantGradientDescValues)
                                {
                                    if (GradientDesc.start <= gradTan && GradientDesc.end > gradTan)
                                    {
                                        newGrassGradient = GradientDesc;
                                    }
                                }
                                if (newGrassGradient != null)
                                {
                                    float fDensity = ((float)noise256 - veges2.startFadeIn) / (veges2.start - veges2.startFadeIn);                                     /// old : veges0
                                    if (fDensity > 1.0f)
                                    {
                                        fDensity = 1.0f;
                                    }
                                    PlantANewGrass(startX, startZ, ix, iz, fDensity, newGrassGradient.PlantDescArrayValues, tileHeightBuf, outlstGrassInst);
                                }
                            }
                        }
                    }
                }
            }
        }
    }