Game Development Community

Better smoothing for terrain editor! (code inside)

by Dan Keller · in Torque 3D Professional · 01/22/2012 (4:58 pm) · 18 replies

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 TerrainEditPallette.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/22/2012 (11:55 pm)
very nice Dan.
#2
01/23/2012 (12:46 am)
That sounds like a fantastic idea - will have to try it out!

EDIT: Works like a dream :).
#3
01/23/2012 (10:57 pm)
This worked really well. I have always had a hard time getting a foot path to look right going up a hill I made in my terrain but this little mod let me do it easily and it looks great.


Thanks for the resource :)
#4
01/24/2012 (7:19 am)
Great idea ... now stick it under resources. :)
#5
01/24/2012 (10:21 am)
! Awesome !
#6
01/24/2012 (8:48 pm)
This is beautiful, dude! Should be added to stock T3D in my opinion, thank you very much!
#7
01/25/2012 (4:44 am)
Very awesome dan, any chance you could have a try at the flatten function so we could get an alternate mode where the height it flatten to is where the cursor was when the mouse button is pressed down rather than where the brush center is right now?

#8
01/25/2012 (2:57 pm)
I don't think so, I don't believe terrain actions have access to any mouse info, it just tells the function what points are currently under the brush.
#9
01/25/2012 (3:57 pm)
can u link this to resource? it'll be lost in a week here.
#10
01/25/2012 (7:01 pm)
@Kyrah: Have you tried using the Set Height tool in the Terrain Editor?
#11
02/10/2012 (2:08 pm)
Works really nicely.

Only bug I've spotted is that if you set the brush size to one it just sets the terrain in the selected area to height 0.
#12
02/15/2012 (4:02 pm)
This is exactly what I was looking for! Thank you so much!
#13
02/20/2012 (2:01 am)
I may be over looking something: I can't find the TerrainEditPallete.ed.gui file for the life of me.
#14
02/20/2012 (3:34 am)
only one "t" missing.
game\tools\worldEditor\gui\ToolsPaletteGroups\TerrainEditPalette.ed.gui


#15
02/20/2012 (11:31 am)
I was too tired to copy and paste :p

I was looking for it in visual studio, but it's a .cs file right?
#16
02/20/2012 (4:34 pm)
It's not in visual studio, its a script file.
#17
02/21/2012 (1:19 am)
I was making sure. I found it in Torsion after an hour of looking for it in Studio.
#18
08/06/2012 (4:15 am)
Very nice. Thanks.