From 8eb0e98f8693cefb4ea903e8d9b7cd89b37928a5 Mon Sep 17 00:00:00 2001 From: thecelloman Date: Wed, 10 Apr 2013 08:44:22 -0400 Subject: [PATCH] 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! --- .../source/gui/worldEditor/terrainActions.cpp | 46 +++++++++++++++++++ .../source/gui/worldEditor/terrainActions.h | 9 ++++ .../source/gui/worldEditor/terrainEditor.cpp | 1 + Engine/source/terrain/terrFile.h | 2 +- .../TerrainEditPalette.ed.gui | 32 +++++++++++-- .../tools/worldEditor/scripts/EditorGui.ed.cs | 13 +++--- .../TerrainEditPalette.ed.gui | 32 +++++++++++-- .../tools/worldEditor/scripts/EditorGui.ed.cs | 13 +++--- 8 files changed, 125 insertions(+), 23 deletions(-) diff --git a/Engine/source/gui/worldEditor/terrainActions.cpp b/Engine/source/gui/worldEditor/terrainActions.cpp index f05847b8c..956fb6eab 100644 --- a/Engine/source/gui/worldEditor/terrainActions.cpp +++ b/Engine/source/gui/worldEditor/terrainActions.cpp @@ -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 diff --git a/Engine/source/gui/worldEditor/terrainActions.h b/Engine/source/gui/worldEditor/terrainActions.h index d091ea5f9..e0e31d988 100644 --- a/Engine/source/gui/worldEditor/terrainActions.h +++ b/Engine/source/gui/worldEditor/terrainActions.h @@ -258,6 +258,15 @@ class SmoothHeightAction : public TerrainAction void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type); }; +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); +}; + class PaintNoiseAction : public TerrainAction { public: diff --git a/Engine/source/gui/worldEditor/terrainEditor.cpp b/Engine/source/gui/worldEditor/terrainEditor.cpp index df8d95d44..ddcd6fda4 100644 --- a/Engine/source/gui/worldEditor/terrainEditor.cpp +++ b/Engine/source/gui/worldEditor/terrainEditor.cpp @@ -710,6 +710,7 @@ TerrainEditor::TerrainEditor() : mActions.push_back(new AdjustHeightAction(this)); mActions.push_back(new FlattenHeightAction(this)); mActions.push_back(new SmoothHeightAction(this)); + mActions.push_back(new SmoothSlopeAction(this)); mActions.push_back(new PaintNoiseAction(this)); //mActions.push_back(new ThermalErosionAction(this)); diff --git a/Engine/source/terrain/terrFile.h b/Engine/source/terrain/terrFile.h index 3640d3664..e6ac593f0 100644 --- a/Engine/source/terrain/terrFile.h +++ b/Engine/source/terrain/terrFile.h @@ -269,7 +269,7 @@ inline F32 fixedToFloat( U16 val ) /// Conversion from floating point to 11.5 fixed point. inline U16 floatToFixed( F32 val ) { - return U16(val * 32.0); + return U16(val * 32.0 + 0.5f); } inline bool TerrainFile::isPointInTerrain( U32 x, U32 y ) const diff --git a/Templates/Empty/game/tools/worldEditor/gui/ToolsPaletteGroups/TerrainEditPalette.ed.gui b/Templates/Empty/game/tools/worldEditor/gui/ToolsPaletteGroups/TerrainEditPalette.ed.gui index 3d281ba72..8f776c932 100644 --- a/Templates/Empty/game/tools/worldEditor/gui/ToolsPaletteGroups/TerrainEditPalette.ed.gui +++ b/Templates/Empty/game/tools/worldEditor/gui/ToolsPaletteGroups/TerrainEditPalette.ed.gui @@ -100,6 +100,28 @@ useMouseEvents = "0"; bitmap = "tools/worldEditor/images/smoothHeight"; }; + 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"; + }; new GuiBitmapButtonCtrl() { canSaveDynamicFields = "0"; internalName = "paintNoise"; @@ -115,7 +137,7 @@ Visible = "1"; Command = "ETerrainEditor.switchAction( paintNoise );"; tooltipprofile = "ToolsGuiToolTipProfile"; - ToolTip = "Paint Noise (5)"; + ToolTip = "Paint Noise (6)"; hovertime = "750"; text = "Button"; buttonType = "RadioButton"; @@ -137,7 +159,7 @@ Visible = "1"; Command = "ETerrainEditor.switchAction( flattenHeight );"; tooltipprofile = "ToolsGuiToolTipProfile"; - ToolTip = "Flatten (6)"; + ToolTip = "Flatten (7)"; hovertime = "750"; text = "Button"; buttonType = "RadioButton"; @@ -159,7 +181,7 @@ Visible = "1"; Command = "ETerrainEditor.switchAction( setHeight );"; tooltipprofile = "ToolsGuiToolTipProfile"; - ToolTip = "Set Height (7)"; + ToolTip = "Set Height (8)"; hovertime = "750"; text = "Button"; buttonType = "RadioButton"; @@ -181,7 +203,7 @@ Visible = "1"; Command = "ETerrainEditor.switchAction( setEmpty );"; tooltipprofile = "ToolsGuiToolTipProfile"; - ToolTip = "Clear Terrain (8)"; + ToolTip = "Clear Terrain (9)"; hovertime = "750"; text = "Button"; buttonType = "RadioButton"; @@ -203,7 +225,7 @@ Visible = "1"; Command = "ETerrainEditor.switchAction( clearEmpty );"; tooltipprofile = "ToolsGuiToolTipProfile"; - ToolTip = "Restore Terrain (9)"; + ToolTip = "Restore Terrain (0)"; hovertime = "750"; text = "Button"; buttonType = "RadioButton"; diff --git a/Templates/Empty/game/tools/worldEditor/scripts/EditorGui.ed.cs b/Templates/Empty/game/tools/worldEditor/scripts/EditorGui.ed.cs index b6e4319f5..f3c27ffbc 100644 --- a/Templates/Empty/game/tools/worldEditor/scripts/EditorGui.ed.cs +++ b/Templates/Empty/game/tools/worldEditor/scripts/EditorGui.ed.cs @@ -997,12 +997,13 @@ function TerrainEditorPlugin::onWorldEditorStartup( %this ) %map.bindCmd( keyboard, "1", "ToolsPaletteArray->brushAdjustHeight.performClick();", "" ); //Grab Terrain %map.bindCmd( keyboard, "2", "ToolsPaletteArray->raiseHeight.performClick();", "" ); // Raise Height %map.bindCmd( keyboard, "3", "ToolsPaletteArray->lowerHeight.performClick();", "" ); // Lower Height - %map.bindCmd( keyboard, "4", "ToolsPaletteArray->smoothHeight.performClick();", "" ); // Smooth - %map.bindCmd( keyboard, "5", "ToolsPaletteArray->paintNoise.performClick();", "" ); // Noise - %map.bindCmd( keyboard, "6", "ToolsPaletteArray->flattenHeight.performClick();", "" ); // Flatten - %map.bindCmd( keyboard, "7", "ToolsPaletteArray->setHeight.performClick();", "" ); // Set Height - %map.bindCmd( keyboard, "8", "ToolsPaletteArray->setEmpty.performClick();", "" ); // Clear Terrain - %map.bindCmd( keyboard, "9", "ToolsPaletteArray->clearEmpty.performClick();", "" ); // Restore Terrain + %map.bindCmd( keyboard, "4", "ToolsPaletteArray->smoothHeight.performClick();", "" ); // Average Height + %map.bindCmd( keyboard, "5", "ToolsPaletteArray->smoothSlope.performClick();", "" ); // Smooth Slope + %map.bindCmd( keyboard, "6", "ToolsPaletteArray->paintNoise.performClick();", "" ); // Noise + %map.bindCmd( keyboard, "7", "ToolsPaletteArray->flattenHeight.performClick();", "" ); // Flatten + %map.bindCmd( keyboard, "8", "ToolsPaletteArray->setHeight.performClick();", "" ); // Set Height + %map.bindCmd( keyboard, "9", "ToolsPaletteArray->setEmpty.performClick();", "" ); // Clear Terrain + %map.bindCmd( keyboard, "0", "ToolsPaletteArray->clearEmpty.performClick();", "" ); // Restore Terrain %map.bindCmd( keyboard, "v", "EWTerrainEditToolbarBrushType->ellipse.performClick();", "" );// Circle Brush %map.bindCmd( keyboard, "b", "EWTerrainEditToolbarBrushType->box.performClick();", "" );// Box Brush %map.bindCmd( keyboard, "=", "TerrainEditorPlugin.keyboardModifyBrushSize(1);", "" );// +1 Brush Size diff --git a/Templates/Full/game/tools/worldEditor/gui/ToolsPaletteGroups/TerrainEditPalette.ed.gui b/Templates/Full/game/tools/worldEditor/gui/ToolsPaletteGroups/TerrainEditPalette.ed.gui index 3d281ba72..8f776c932 100644 --- a/Templates/Full/game/tools/worldEditor/gui/ToolsPaletteGroups/TerrainEditPalette.ed.gui +++ b/Templates/Full/game/tools/worldEditor/gui/ToolsPaletteGroups/TerrainEditPalette.ed.gui @@ -100,6 +100,28 @@ useMouseEvents = "0"; bitmap = "tools/worldEditor/images/smoothHeight"; }; + 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"; + }; new GuiBitmapButtonCtrl() { canSaveDynamicFields = "0"; internalName = "paintNoise"; @@ -115,7 +137,7 @@ Visible = "1"; Command = "ETerrainEditor.switchAction( paintNoise );"; tooltipprofile = "ToolsGuiToolTipProfile"; - ToolTip = "Paint Noise (5)"; + ToolTip = "Paint Noise (6)"; hovertime = "750"; text = "Button"; buttonType = "RadioButton"; @@ -137,7 +159,7 @@ Visible = "1"; Command = "ETerrainEditor.switchAction( flattenHeight );"; tooltipprofile = "ToolsGuiToolTipProfile"; - ToolTip = "Flatten (6)"; + ToolTip = "Flatten (7)"; hovertime = "750"; text = "Button"; buttonType = "RadioButton"; @@ -159,7 +181,7 @@ Visible = "1"; Command = "ETerrainEditor.switchAction( setHeight );"; tooltipprofile = "ToolsGuiToolTipProfile"; - ToolTip = "Set Height (7)"; + ToolTip = "Set Height (8)"; hovertime = "750"; text = "Button"; buttonType = "RadioButton"; @@ -181,7 +203,7 @@ Visible = "1"; Command = "ETerrainEditor.switchAction( setEmpty );"; tooltipprofile = "ToolsGuiToolTipProfile"; - ToolTip = "Clear Terrain (8)"; + ToolTip = "Clear Terrain (9)"; hovertime = "750"; text = "Button"; buttonType = "RadioButton"; @@ -203,7 +225,7 @@ Visible = "1"; Command = "ETerrainEditor.switchAction( clearEmpty );"; tooltipprofile = "ToolsGuiToolTipProfile"; - ToolTip = "Restore Terrain (9)"; + ToolTip = "Restore Terrain (0)"; hovertime = "750"; text = "Button"; buttonType = "RadioButton"; diff --git a/Templates/Full/game/tools/worldEditor/scripts/EditorGui.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/EditorGui.ed.cs index b6e4319f5..f3c27ffbc 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/EditorGui.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/EditorGui.ed.cs @@ -997,12 +997,13 @@ function TerrainEditorPlugin::onWorldEditorStartup( %this ) %map.bindCmd( keyboard, "1", "ToolsPaletteArray->brushAdjustHeight.performClick();", "" ); //Grab Terrain %map.bindCmd( keyboard, "2", "ToolsPaletteArray->raiseHeight.performClick();", "" ); // Raise Height %map.bindCmd( keyboard, "3", "ToolsPaletteArray->lowerHeight.performClick();", "" ); // Lower Height - %map.bindCmd( keyboard, "4", "ToolsPaletteArray->smoothHeight.performClick();", "" ); // Smooth - %map.bindCmd( keyboard, "5", "ToolsPaletteArray->paintNoise.performClick();", "" ); // Noise - %map.bindCmd( keyboard, "6", "ToolsPaletteArray->flattenHeight.performClick();", "" ); // Flatten - %map.bindCmd( keyboard, "7", "ToolsPaletteArray->setHeight.performClick();", "" ); // Set Height - %map.bindCmd( keyboard, "8", "ToolsPaletteArray->setEmpty.performClick();", "" ); // Clear Terrain - %map.bindCmd( keyboard, "9", "ToolsPaletteArray->clearEmpty.performClick();", "" ); // Restore Terrain + %map.bindCmd( keyboard, "4", "ToolsPaletteArray->smoothHeight.performClick();", "" ); // Average Height + %map.bindCmd( keyboard, "5", "ToolsPaletteArray->smoothSlope.performClick();", "" ); // Smooth Slope + %map.bindCmd( keyboard, "6", "ToolsPaletteArray->paintNoise.performClick();", "" ); // Noise + %map.bindCmd( keyboard, "7", "ToolsPaletteArray->flattenHeight.performClick();", "" ); // Flatten + %map.bindCmd( keyboard, "8", "ToolsPaletteArray->setHeight.performClick();", "" ); // Set Height + %map.bindCmd( keyboard, "9", "ToolsPaletteArray->setEmpty.performClick();", "" ); // Clear Terrain + %map.bindCmd( keyboard, "0", "ToolsPaletteArray->clearEmpty.performClick();", "" ); // Restore Terrain %map.bindCmd( keyboard, "v", "EWTerrainEditToolbarBrushType->ellipse.performClick();", "" );// Circle Brush %map.bindCmd( keyboard, "b", "EWTerrainEditToolbarBrushType->box.performClick();", "" );// Box Brush %map.bindCmd( keyboard, "=", "TerrainEditorPlugin.keyboardModifyBrushSize(1);", "" );// +1 Brush Size