public byte GetVoxelType(float gradTan, float height, double noise, int idxRegion)
 {
     if (gradTan > 999)
     {
         Debug.LogError("gradTan:" + gradTan);
         gradTan = 999;
     }
     if (gradTan < 0)
     {
         Debug.LogError("gradTan:" + gradTan);
         gradTan = 0;
     }
     reqGradTan = gradTan;
     reqHeight  = height;
     reqNoise   = noise;
     //if(curRegion == prms.RegionDescArrayValues[idxRegion])
     //{
     //    if(curGradient.startTan <= reqGradTan && curGradient.endTan > reqGradTan)
     //    {
     //        return GetVoxelTypeFromCurGradient();
     //    }
     //    else
     //    {
     //        return GetVoxelTypeFromCurHeight();
     //    }
     //}
     //else
     //{
     curRegion = prms.RegionDescArrayValues[idxRegion];
     return(GetVoxelTypeFromCurRegion());
     //}
 }
    public byte GetVoxelType(float gradTan, float height, int posX, int posZ)
    {
        int  iCol     = 0;
        bool colMatch = true;   //default

        reqGradTan = gradTan;
        reqHeight  = height;
        reqNoise   = GetNoise(posX, posZ);

        if (curRegion.color != null)
        {
            int     u   = (int)(posX * terrainSectionsMapW / (float)VoxelTerrainConstants._worldSideLenX);
            int     v   = (int)(posZ * terrainSectionsMapW / (float)VoxelTerrainConstants._worldSideLenZ);
            Color32 col = terrainSectionsCols32[(v * terrainSectionsMapW + u)];
            iCol     = (col.a << 24) | (col.r << 16) | (col.g << 8) | (col.b);
            colMatch = Convert.ToInt32(curRegion.color, 16) == iCol;
        }
        if (colMatch)
        {
            if (curHeight.start <= reqHeight && curHeight.end > reqHeight)
            {
                if (curGradient.startTan <= reqGradTan && curGradient.endTan > reqGradTan)
                {
                    return(GetVoxelTypeFromCurGradient());
                }
                else
                {
                    return(GetVoxelTypeFromCurHeight());
                }
            }
            else
            {
                return(GetVoxelTypeFromCurRegion());
            }
        }
        foreach (VoxelPaintXML.RegionDescArrayCLS regionDesc in prms.RegionDescArrayValues)
        {
            if (Convert.ToInt32(regionDesc.color, 16) == iCol)
            {
                curRegion = regionDesc;
                return(GetVoxelTypeFromCurRegion());
            }
        }
        Debug.Log("Unrecognized region color------");
        return(defType);
    }
    public void LoadXMLInResources(string xmlPath, string regionMapFolder, SimplexNoise noise, System.Random rand)
    {
        TextAsset xmlResource = Resources.Load(xmlPath) as TextAsset;

        XmlSerializer serializer = new XmlSerializer(typeof(VoxelPaintXML.rootCLS));
        StringReader  reader     = new StringReader(xmlResource.text);

        if (null == reader)
        {
            return;
        }

        prms = (VoxelPaintXML.rootCLS)serializer.Deserialize(reader);
        reader.Close();
        Grad1000ToTanAndSetHeight();

        //SetPlantHeight();
        //SetTerrainTextureHeight();

        Texture2D terrainSectionsMap = Resources.Load(regionMapFolder + prms.regionsMap) as Texture2D;

        if (terrainSectionsMap != null)
        {
            terrainSectionsMapW = terrainSectionsMap.width;
            //terrainSectionsMapH = terrainSectionsMap.height;
            terrainSectionsCols32 = terrainSectionsMap.GetPixels32();
        }
        else
        {
            terrainSectionsCols32 = null;
            Debug.LogWarning("VoxelPaintXMLParser: No sectionmap found.");
        }
        curRegion   = prms.RegionDescArrayValues[0];
        curHeight   = curRegion.HeightDescArrayValues[0];
        curGradient = curHeight.GradientDescArrayValues[0];
        defType     = 3;
        myNoise     = noise;
        myRand      = rand;
    }
    // Load XML
#if UNITY_EDITOR
    public void LoadXMLAtPath(string xmlPath = "Assets/Editor/EditorAssets/paintVxMat.xml", string regionMapFolder = "Assets/Editor/EditorAssets/")
    {
        TextAsset    xmlResource = UnityEditor.AssetDatabase.LoadAssetAtPath(xmlPath, typeof(TextAsset)) as TextAsset;
        StringReader reader      = new StringReader(xmlResource.text);

        if (null == reader)
        {
            return;
        }

        XmlSerializer serializer = new XmlSerializer(typeof(VoxelPaintXML.rootCLS));

        prms = (VoxelPaintXML.rootCLS)serializer.Deserialize(reader);
        reader.Close();
        Grad1000ToTan();

        Texture2D terrainSectionsMap = UnityEditor.AssetDatabase.LoadAssetAtPath(regionMapFolder + prms.regionsMap, typeof(Texture2D)) as Texture2D;

        if (terrainSectionsMap != null)
        {
            terrainSectionsMapW = terrainSectionsMap.width;
            //terrainSectionsMapH = terrainSectionsMap.height;
            terrainSectionsCols32 = terrainSectionsMap.GetPixels32();
        }
        else
        {
            terrainSectionsCols32 = null;
            Debug.LogWarning("VoxelPaintXMLParser: No sectionmap found.");
        }
        curRegion   = prms.RegionDescArrayValues[0];
        curHeight   = curRegion.HeightDescArrayValues[0];
        curGradient = curHeight.GradientDescArrayValues[0];
        defType     = 3;
        myNoise     = new SimplexNoise();
        myRand      = new System.Random(0);
    }
    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);
                                }
                            }
                        }
                    }
                }
            }
        }
    }