public static void Erode(TerraMesh _tMesh, float _maxErosionRate, float[] _waterFlux) { var sitePositions = _tMesh.GetAllSitePositions(); //TODO SLOW //Get all site slope vectors and slope values var slopeVecs = new Vector3[sitePositions.Length]; var slopeVals = new float[sitePositions.Length]; for (var pIdx = 0; pIdx < sitePositions.Length; ++pIdx) { var p = sitePositions[pIdx]; var aveSlp = Vector3.zero; var nbrCnt = 0; foreach (var nIdx in _tMesh.SiteNeighbors[pIdx]) { if (nIdx == SiteIdxNull) { continue; } nbrCnt++; var n = sitePositions[nIdx]; var slpVec = n - p; if (slpVec.z > 0) { slpVec = -slpVec; } aveSlp += slpVec; } var slpVecCell = aveSlp / nbrCnt; slopeVecs[pIdx] = slpVecCell; slopeVals[pIdx] = slpVecCell.z / new Vector2(slpVecCell.x, slpVecCell.y).magnitude; } //Apply erosion to terra mesh surface for (var pIdx = 0; pIdx < _waterFlux.Length; ++pIdx) { var sitePos = sitePositions[pIdx]; var fx = (float)Math.Sqrt(_waterFlux[pIdx]); var slp = slopeVals[pIdx]; var erosionShift = Math.Min(-slp * fx, _maxErosionRate); //var newPos = new Vector3(sitePos.x, sitePos.y, sitePos.z - erosionShift); SetSiteHeight(_tMesh, pIdx, sitePos.z - erosionShift); } _tMesh.RecalculateBounds(); }
public static Vector3[] PlanchonDarboux(TerraMesh _tMesh, float _minSlope, Progress.OnUpdate _onUpdate) { var prog = new Progress("PlanchonDarboux"); prog.SetOnUpdate(_onUpdate); var sitePosArr = _tMesh.GetAllSitePositions(); //TODO slow? var hullSites = new HashSet <int>(_tMesh.HullSites); //var hullSites = _tMesh.HullSites; //Generate waterflow surface points var newSurf = new Vector3[sitePosArr.Length]; for (var pIdx = 0; pIdx < sitePosArr.Length; ++pIdx) { var sPos = sitePosArr[pIdx]; var z = float.PositiveInfinity; if (hullSites.Contains(pIdx)) { z = sPos.z; } newSurf[pIdx] = new Vector3(sPos.x, sPos.y, z); } Func <int, float> Z = _idx => sitePosArr[_idx].z; Func <int, float> W = _idx => newSurf[_idx].z; Func <int, int, float> E = (_cIdx, _nIdx) => { var cVert = sitePosArr[_cIdx]; var nVert = sitePosArr[_nIdx]; var subX = nVert.x - cVert.x; var subY = nVert.y - cVert.y; return((float)Math.Sqrt(subX * subX + subY * subY) * _minSlope); }; var opDone = false; var wCnt = 0; //DEBUG todo do { opDone = false; var sitePosArrLen = sitePosArr.Length; //TODO Debug for (var pIdx = 0; pIdx < sitePosArrLen; ++pIdx) { var progPct = (float)pIdx / sitePosArrLen; prog.Update(progPct, pIdx + " of " + sitePosArrLen); if (hullSites.Contains(pIdx)) { continue; } var sitePos = sitePosArr[pIdx]; var c = pIdx; if (!(W(c) > Z(c))) { continue; } var cVertZ = sitePos; foreach (var n in _tMesh.SiteNeighbors[pIdx]) { var e = E(c, n); var wpn = W(n) + e; if (cVertZ.z >= wpn) { newSurf[c].Set(cVertZ.x, cVertZ.y, cVertZ.z); opDone = true; break; } if (W(c) > wpn) { newSurf[c].Set(cVertZ.x, cVertZ.y, wpn); opDone = true; } } } if (++wCnt > 2) { break; // TODO DEBUG } } while (opDone); return(newSurf); }