Game Development Community

dev|Pro Game Development Curriculum

Better smoothing for terrain editor!

by Dan Keller · 01/25/2012 (5:08 pm) · 11 comments

So I came up with a little improvement to the terrain editor's smooth tool. Instead of just moving everything towards the average height, it takes a linear regression of the included terrain and moves the ground toward it. This lets you make smooth slopes, and is helpful for fixing small mistakes made with the other terrain editor tools.

To add:
In terrainActions.h around line 243 add
class SmoothSlopeAction : public TerrainAction
{
   public:
      SmoothSlopeAction(TerrainEditor * editor) : TerrainAction(editor){}
      StringTableEntry getName(){return("smoothSlope");}

      void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
};

In terrainActions.cpp around line 614 add
//------------------------------------------------------------------------------

void SmoothSlopeAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
{
   if(!sel->size())
      return;

   if(selChanged)
   {
      //perform simple 2d lin reg 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();
   }
}

In terrainEditor.cpp at line 695 add
mActions.push_back(new SmoothSlopeAction(this));

In terrFile.h change line 254 to
return U16(val * 32.0 + 0.5f);
This fixes an error that causes the terrain height to be rounded down.

In TerrainEditPallete.ed.gui at line 103 add
new GuiBitmapButtonCtrl() {
      canSaveDynamicFields = "0";
      internalName = "smoothSlope";
      Enabled = "1";
      isContainer = "0";
      Profile = "GuiButtonProfile";
      HorizSizing = "right";
      VertSizing = "bottom";
      position = "144 0";
      Extent = "25 19";
      MinExtent = "8 2";
      canSave = "1";
      Visible = "1";
      Command = "ETerrainEditor.switchAction( smoothSlope );";
      tooltipprofile = "GuiToolTipProfile";
      ToolTip = "Smooth Slope (5)";
      hovertime = "750";
      text = "Button";
      buttonType = "RadioButton";
      useMouseEvents = "0";
      bitmap = "tools/worldEditor/images/softCurve";
   };

Compile and enjoy!

#1
01/25/2012 (11:53 pm)
This is awesome! great resource:O) Any chance of some before and after shots screenshots?
#2
01/26/2012 (5:01 am)
Sounds like a cool resource.
#3
01/27/2012 (1:21 am)
Implemented and working like a charm -much better than the original code...
#4
01/27/2012 (12:48 pm)
This is a great resource. Thanks for sharing it with us.
#5
01/30/2012 (12:15 pm)
Very nice resource, this will definitely help to make the terrain more friendly to users.
#6
02/06/2012 (11:15 pm)
this was great, for cleaning up terrains created by importing google earth height maps -- otherwise the mountains all looked like pyramids.
#7
02/17/2012 (12:13 pm)
Awesome! You have no idea how much the stock smoothing has been driving me crazy! (Especially since I've been "practicing" building levels in Farcry 2, which has the perfect smoothing tool.)

Can't wait to try this out!
#8
02/21/2012 (12:16 pm)
Ok, not exactly what I was expecting, but definitely useful. Guess I'll have to continue digging through the smoothing code to see what's causing the issue.

The issue, BTW, is that no matter what settings are used for the selection brush softness or filter, there's always an edge created around the selection area, so you can never get the surface to be perfectly smooth. I compared the smoothing code in T3D against TGE 1.52; it's the same code, but in TGE there's no edges, so I think something is wonky with how the selection itself is handled in T3D.


#9
09/01/2012 (2:32 am)
Is this available without compiling, as ready compiled file?
#10
10/09/2012 (2:06 pm)
Thanks for this!

Still new to T3D, I created a terrain I liked and went to smooth out a walk path. It must be the brushes as mentioned above, but it did more of a flatten. Looking forward to trying this out.
#11
01/01/2013 (7:00 am)
Quote:
I compared the smoothing code in T3D against TGE 1.52; it's the same code, but in TGE there's no edges, so I think something is wonky with how the selection itself is handled in T3D.

kevin,
did u find the cause?