//TODO split old settings add new settings for just this.
            public static void ApplyRandomLandFeatures(TerraMap _tMap, Action _onComplete, Progress.OnUpdate _onUpdate)
            {
                var prog = new Progress();

                prog.SetOnUpdate(_onUpdate);
                var tMesh    = _tMap.TMesh;
                var settings = _tMap.settings;

                //Land morphing

                prog.Update(0, "Conifying", true);
                TerraMesh.Modify.Conify(tMesh, settings.ConifyStrength, _onUpdate);
                prog.Update(1, "Conifying", true);

                prog.Update(0, "Applying Global Slope", true);
                var gSlpDir = settings.GlobalSlopeDir == Vector2.zero
                    ? new Vector2((float)(settings.m_Rnd.NextDouble() - 0.5f),
                                  (float)(settings.m_Rnd.NextDouble() - 0.5f))
                    : settings.GlobalSlopeDir;

                TerraMesh.Modify.SlopeGlobal(tMesh, gSlpDir, settings.GlobalSlopeMag);
                prog.Update(1, "Applying Global Slope", true);

                prog.Update(0, "Adding Hills / Blobs", true);
                var meshBnd = tMesh.bounds;
                var rectXY  = new Rect(meshBnd.min.x, meshBnd.min.y, meshBnd.size.x, meshBnd.size.y);

                for (var hIdx = 0; hIdx < settings.HillRndCnt.Count; ++hIdx)
                {
                    prog.Update((float)hIdx / settings.HillRndCnt.Count, "Adding hills / blobs");
                    for (var hCnt = 0; hCnt < settings.HillRndCnt[hIdx]; ++hCnt)
                    {
                        TerraMesh.Modify.Blob(tMesh, settings.HillRndStr[hIdx], settings.HillRndRad[hIdx],
                                              Settings.RndVec2(rectXY, settings.m_Rnd));
                    }
                }

                prog.Update(1, "Adding Hills / Blobs", true);


                //Calculate water flux
                prog.Update(0, "Making Rivers", true);
                ApplyWaterFlux(_tMap, _onUpdate);
                prog.Update(1, "Making Rivers", true);

                //Erosion
                prog.Update(0, "Eroding", true);
                TerraMesh.Modify.Erode(tMesh, settings.MaxErosionRate,
                                       _tMap.WaterFlux.Select(_node => _node.Flux).ToArray());
                prog.Update(1, "Eroding", true);

                //Calculate Water Level
                prog.Update(0, "Setting Sea Level", true);
                SetSeaLevelByLandRatio(_tMap, settings.LandWaterRatio);
                prog.Update(1, "Setting Sea Level", true);



                PlaceRivers(_tMap, settings.m_WaterwayThresh);
            }
            public static void PlaceRivers(TerraMap _tMap, float _fluxThresh)
            {
                var wwList = new List <WaterNode>(_tMap.WaterFlux);

                //Prune ocean sites
                var sitePositions = _tMap.TMesh.GetAllSitePositions(); //TODO

                wwList.RemoveAll(_wn => sitePositions[_wn.SiteIdx].z < _tMap.WaterSurfaceZ);
                wwList.Sort((_a, _b) => _b.Flux.CompareTo(_a.Flux));

                //Calc flux cutoff


                var fluxCutoff = _fluxThresh * _tMap.WaterFluxSpan + _tMap.WaterFluxMin;

                var riverSites = new List <int>();

                for (var idx = 0; idx < wwList.Count; ++idx)
                {
                    var wn = wwList[idx];
                    if (wn.Flux < fluxCutoff)
                    {
                        break;
                    }
                    riverSites.Add(wn.SiteIdx);
                }

                _tMap.RiverSites = riverSites.ToArray();
            }
            ///Calculate sea level based on land water ratio
            public static void SetSeaLevelByLandRatio2(TerraMap _tMap, float _landToWaterRatio)
            {
                var tMesh      = _tMap.TMesh;
                var landPctTgt = _landToWaterRatio;

                if (landPctTgt <= 0 || landPctTgt >= 1)
                {
                    landPctTgt = 0.5f;
                }

                var zMin = tMesh.bounds.min.z;
                var zMax = tMesh.bounds.max.z;

                var vertices = _tMap.TMesh.Vertices;


                //Start Find
                var zCheck   = zMin + (zMax - zMin) / 2f;
                var zRailMax = zMax;
                var zRailMin = zMin;

                while (true) //TODO this is brute force
                {
                    var aboveCnt = 0;
                    var belowCnt = 0;
                    foreach (var site in vertices)
                    {
                        if (site.z > zCheck)
                        {
                            aboveCnt++;
                        }
                        else
                        {
                            belowCnt++;
                        }
                    }

                    var pctLandCheck = aboveCnt / (float)(aboveCnt + belowCnt);
                    var errorPct     = 0.05;
                    if (pctLandCheck > landPctTgt + errorPct)
                    {
                        zRailMin = zCheck;
                        zCheck  += (zRailMax - zCheck) / 2f;
                        continue;
                    }

                    if (pctLandCheck < landPctTgt - errorPct)
                    {
                        zRailMax = zCheck;
                        zCheck  -= (zCheck - zRailMin) / 2f;
                        continue;
                    }

                    break;
                }

                _tMap.WaterSurfaceZ = zCheck;
            }
            public static void SetSeaLevelByLandRatio(TerraMap _tMap, float _landToWaterRatio)
            {
                var tMesh          = _tMap.TMesh;
                var sortedVertices = tMesh.Vertices.ToList();

                sortedVertices.Sort((_a, _b) => _a.z.CompareTo(_b.z));

                var vIdx = (int)(_landToWaterRatio * sortedVertices.Count);

                _tMap.WaterSurfaceZ = sortedVertices[vIdx].z;
            }
Beispiel #5
0
            public BiomeStuff(TerraMap _host)
            {
                Host = _host;
                //Set up Biomes
                SetupBiomes();

                //TODO Config Biomes on map using units of distance
                var sitePos = Host.TMesh.GetAllSitePositions();

                SiteBiomeMoistZone = new int[sitePos.Length];
                //SiteBiomeElevZone = new int[sitePos.Length];
                //SiteBiomes = new Biome[sitePos.Length];
                for (var sIdx = 0; sIdx < SiteBiomeMoistZone.Length; ++sIdx)
                {
                    SiteBiomeMoistZone[sIdx] = 5;
                }
            }
Beispiel #6
0
            public TerraTexture(TerraMap _host, Progress.OnUpdate _onUpdate = null)
            {
                Host   = _host;
                canvas = new Canvas((int)Math.Ceiling(Host.settings.TextureResolution * Host.settings.Bounds.width),
                                    (int)Math.Ceiling(Host.settings.TextureResolution * Host.settings.Bounds.height));

                m_Progress = new Progress("TerraTexture");
                var actProg = _onUpdate ?? ((_progPct, _progStr) => { });

                m_Progress.SetOnUpdate(actProg);
                m_PixSize    = new Vector2(Host.TMesh.bounds.size.x / canvas.Width, Host.TMesh.bounds.size.y / canvas.Height);
                m_ZeroOffset = Host.TMesh.bounds.min.ToVec2();

                Trace.WriteLine("Init Texture W: " + canvas.Width + " H: " + canvas.Height);

                //Paint Waterways

                //PaintRivers();
            }
            //TODO - consider wind effect on rain?  ie less rain on downward slopes?
            public static void ApplyWaterFlux(TerraMap _tMap, Progress.OnUpdate _onUpdate)
            {
                var pdSurface = TerraMesh.Generator.PlanchonDarboux(_tMap.TMesh, _tMap.settings.MinPDSlope, _onUpdate);

                //Calc water flux
                var sitePos = _tMap.TMesh.GetAllSitePositions();

                _tMap.WaterFlux = new WaterNode[sitePos.Length];

                //Init waterflux and heightmap - TODO sort not needed?
                var pIdxByHt = new int[sitePos.Length];

                for (var pIdx = 0; pIdx < sitePos.Length; ++pIdx)
                {
                    pIdxByHt[pIdx]        = pIdx;
                    _tMap.WaterFlux[pIdx] = new WaterNode
                    {
                        Flux    = _tMap.settings.RainfallGlobal,
                        SiteIdx = pIdx
                    };
                }

                Array.Sort(pIdxByHt, (_a, _b) => pdSurface[_b].z.CompareTo(pdSurface[_a].z));

                var dbgHtArr = new float[pIdxByHt.Length];

                for (var idx = 0; idx < pIdxByHt.Length; idx++)
                {
                    dbgHtArr[idx] = pdSurface[pIdxByHt[idx]].z;
                }


                for (var hIdx = 0; hIdx < sitePos.Length; ++hIdx)
                {
                    var pIdx = pIdxByHt[hIdx];
                    var w    = pdSurface[pIdx];

                    //Find biggest slope neighbor
                    var minNIdx = -1;
                    //var maxNSlp = 0f;
                    float maxZdiff = 0;
                    var   siteNbrs = _tMap.TMesh.SiteNeighbors;
                    foreach (var nIdx in siteNbrs[pIdx])
                    {
                        if (nIdx == TerraMesh.SiteIdxNull)
                        {
                            continue;
                        }
                        var n = pdSurface[nIdx];

                        if (n.z <= w.z)
                        {
                            var diff = w.z - n.z;
                            if (diff > maxZdiff)
                            {
                                maxZdiff = diff;
                                minNIdx  = nIdx;
                            }

                            /*  Use slope - (Not working?)
                             * var vec = n - w;
                             * var run = (float) Math.Sqrt(vec.x * vec.x + vec.y * vec.y);
                             * var rise = w.z - n.z;
                             * var slp = rise / run;
                             * if (slp > maxNSlp)
                             * {
                             *  minNIdx = nIdx;
                             *  maxNSlp = slp;
                             * }
                             */
                        }
                    }

                    if (minNIdx == -1) //TODO DEBUG should never happen?
                    {
                        continue;
                    }
                    if (minNIdx == pIdx) //TODO DEBUG
                    {
                        continue;
                    }

                    //Add this nodes flux to downhill neighbor
                    _tMap.WaterFlux[minNIdx].Flux += _tMap.WaterFlux[pIdx].Flux;
                    //Set waterway direction
                    _tMap.WaterFlux[pIdx].NodeTo = _tMap.WaterFlux[minNIdx];

                    //Check min / max
                    var chkFlx = _tMap.WaterFlux[minNIdx].Flux;
                    if (chkFlx > _tMap.WaterFluxMax)
                    {
                        _tMap.WaterFluxMax = chkFlx;
                    }
                }
            }