Add a new Terrain brush action: Smooth Slope.

This smoothes the terrain using a linear regression algorithm.  Exists alongside the oldstyle height averaging action -- options are good!
This commit is contained in:
thecelloman 2013-04-10 08:44:22 -04:00
parent 1ed1a41256
commit 8eb0e98f86
8 changed files with 125 additions and 23 deletions

View file

@ -631,6 +631,52 @@ void SmoothHeightAction::process(Selection * sel, const Gui3DMouseEvent &, bool
}
}
void SmoothSlopeAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
{
if(!sel->size())
return;
if(selChanged)
{
// Perform simple 2d linear regression on x&z and y&z:
// b = (Avg(xz) - Avg(x)Avg(z))/(Avg(x^2) - Avg(x)^2)
Point2F prod(0.f, 0.f); // mean of product for covar
Point2F avgSqr(0.f, 0.f); // mean sqr of x, y for var
Point2F avgPos(0.f, 0.f);
F32 avgHeight = 0.f;
F32 z;
Point2F pos;
for(U32 k = 0; k < sel->size(); k++)
{
mTerrainEditor->getUndoSel()->add((*sel)[k]);
pos = Point2F((*sel)[k].mGridPoint.gridPos.x, (*sel)[k].mGridPoint.gridPos.y);
z = (*sel)[k].mHeight;
prod += pos * z;
avgSqr += pos * pos;
avgPos += pos;
avgHeight += z;
}
prod /= sel->size();
avgSqr /= sel->size();
avgPos /= sel->size();
avgHeight /= sel->size();
Point2F avgSlope = (prod - avgPos*avgHeight)/(avgSqr - avgPos*avgPos);
F32 goalHeight;
for(U32 i = 0; i < sel->size(); i++)
{
goalHeight = avgHeight + ((*sel)[i].mGridPoint.gridPos.x - avgPos.x)*avgSlope.x +
((*sel)[i].mGridPoint.gridPos.y - avgPos.y)*avgSlope.y;
(*sel)[i].mHeight += (goalHeight - (*sel)[i].mHeight) * (*sel)[i].mWeight;
mTerrainEditor->setGridInfo((*sel)[i]);
}
mTerrainEditor->scheduleGridUpdate();
}
}
void PaintNoiseAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type type)
{
// If this is the ending