mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-04-26 14:55:39 +00:00
Merge pull request #1388 from Azaezel/alpha41/erosionBrushes
additional terrain brushes
This commit is contained in:
commit
7bb8587db5
40 changed files with 349 additions and 62 deletions
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "gui/core/guiCanvas.h"
|
||||
|
||||
TerrainScratchPad gTerrainScratchPad;
|
||||
//------------------------------------------------------------------------------
|
||||
bool TerrainAction::isValid(GridInfo tile)
|
||||
{
|
||||
|
|
@ -746,60 +747,212 @@ void PaintNoiseAction::process(Selection * sel, const Gui3DMouseEvent &, bool se
|
|||
mTerrainEditor->scheduleGridUpdate();
|
||||
}
|
||||
}
|
||||
/*
|
||||
void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type)
|
||||
|
||||
void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type type)
|
||||
{
|
||||
if( selChanged )
|
||||
// If this is the ending
|
||||
// mouse down event, then
|
||||
// update the noise values.
|
||||
|
||||
TerrainBlock* tblock = mTerrainEditor->getActiveTerrain();
|
||||
if (!tblock)
|
||||
return;
|
||||
|
||||
F32 selRange = sel->getMaxHeight()-sel->getMinHeight();
|
||||
F32 avg = sel->getAvgHeight();
|
||||
if (selChanged)
|
||||
{
|
||||
TerrainBlock *tblock = mTerrainEditor->getActiveTerrain();
|
||||
if ( !tblock )
|
||||
return;
|
||||
|
||||
F32 height = 0;
|
||||
F32 maxHeight = 0;
|
||||
U32 shift = getBinLog2( TerrainBlock::BlockSize );
|
||||
|
||||
for ( U32 x = 0; x < TerrainBlock::BlockSize; x++ )
|
||||
{
|
||||
for ( U32 y = 0; y < TerrainBlock::BlockSize; y++ )
|
||||
{
|
||||
height = fixedToFloat( tblock->getHeight( x, y ) );
|
||||
mTerrainHeights[ x + (y << 8)] = height;
|
||||
|
||||
if ( height > maxHeight )
|
||||
maxHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
//mNoise.erodeThermal( &mTerrainHeights, &mNoiseData, 30.0f, 5.0f, 5, TerrainBlock::BlockSize, tblock->getSquareSize(), maxHeight );
|
||||
|
||||
mNoise.erodeHydraulic( &mTerrainHeights, &mNoiseData, 1, TerrainBlock::BlockSize );
|
||||
|
||||
F32 heightDiff = 0;
|
||||
|
||||
for( U32 i = 0; i < sel->size(); i++ )
|
||||
for (U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
if (!isValid((*sel)[i]))
|
||||
continue;
|
||||
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
|
||||
const Point2I &gridPos = (*sel)[i].mGridPoint.gridPos;
|
||||
|
||||
// Need to get the height difference
|
||||
// between the current height and the
|
||||
// erosion height to properly apply the
|
||||
// softness and pressure settings of the brush
|
||||
// for this selection.
|
||||
heightDiff = (*sel)[i].mHeight - mNoiseData[ gridPos.x + (gridPos.y << shift)];
|
||||
F32 bias = ((*sel)[i].mHeight - avg) / selRange;
|
||||
F32 nudge = mRandF(-mTerrainEditor->getBrushPressure(), mTerrainEditor->getBrushPressure());
|
||||
F32 heightTarg = mRoundF((*sel)[i].mHeight - bias * nudge, mTerrainEditor->getBrushPressure() * 2.0f) ;
|
||||
heightDiff = heightTarg - (*sel)[i].mHeight;
|
||||
(*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight;
|
||||
|
||||
(*sel)[i].mHeight -= (heightDiff * (*sel)[i].mWeight);
|
||||
if ((*sel)[i].mHeight > mTerrainEditor->mTileMaxHeight)
|
||||
(*sel)[i].mHeight = mTerrainEditor->mTileMaxHeight;
|
||||
|
||||
if ((*sel)[i].mHeight < mTerrainEditor->mTileMinHeight)
|
||||
(*sel)[i].mHeight = mTerrainEditor->mTileMinHeight;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
|
||||
mTerrainEditor->gridUpdateComplete();
|
||||
mTerrainEditor->scheduleGridUpdate();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type)
|
||||
{
|
||||
// If this is the ending
|
||||
// mouse down event, then
|
||||
// update the noise values.
|
||||
|
||||
TerrainBlock* tblock = mTerrainEditor->getActiveTerrain();
|
||||
if (!tblock)
|
||||
return;
|
||||
|
||||
F32 selRange = sel->getMaxHeight() - sel->getMinHeight();
|
||||
F32 avg = sel->getAvgHeight();
|
||||
if (selChanged)
|
||||
{
|
||||
F32 heightDiff = 0;
|
||||
const F32 squareSize = tblock->getSquareSize();
|
||||
|
||||
for (U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
if (!isValid((*sel)[i]))
|
||||
continue;
|
||||
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
|
||||
Point2F p;
|
||||
Point3F norm;
|
||||
|
||||
p.x = (*sel)[i].mGridPoint.gridPos.x * squareSize;
|
||||
p.y = (*sel)[i].mGridPoint.gridPos.y * squareSize;
|
||||
tblock->getNormal(p, &norm, true);
|
||||
|
||||
F32 bias = mPow(norm.z,3.0f) * ((*sel)[i].mHeight - avg) / selRange;
|
||||
F32 nudge = mRandF(-mTerrainEditor->getBrushPressure(), mTerrainEditor->getBrushPressure());
|
||||
|
||||
heightDiff = bias * (-(*sel)[i].mHeight + bias * nudge) / tblock->getObjBox().len_z() * 2.0;
|
||||
|
||||
(*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight;
|
||||
|
||||
if ((*sel)[i].mHeight > mTerrainEditor->mTileMaxHeight)
|
||||
(*sel)[i].mHeight = mTerrainEditor->mTileMaxHeight;
|
||||
|
||||
if ((*sel)[i].mHeight < mTerrainEditor->mTileMinHeight)
|
||||
(*sel)[i].mHeight = mTerrainEditor->mTileMinHeight;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
|
||||
mTerrainEditor->scheduleGridUpdate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TerrainScratchPad::addTile(F32 height, U8 material)
|
||||
{
|
||||
mContents.push_back(new gridStub(height, material));
|
||||
|
||||
mBottom = mMin(height, mBottom);
|
||||
mTop = mMax(height, mTop);
|
||||
};
|
||||
|
||||
void TerrainScratchPad::clear()
|
||||
{
|
||||
for (U32 i = 0; i < mContents.size(); i++)
|
||||
delete(mContents[i]);
|
||||
mContents.clear();
|
||||
mBottom = F32_MAX;
|
||||
mTop = F32_MIN_EX;
|
||||
}
|
||||
|
||||
void copyAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type)
|
||||
{
|
||||
gTerrainScratchPad.clear();
|
||||
for (U32 i=0;i<sel->size();i++)
|
||||
{
|
||||
if (isValid((*sel)[i]))
|
||||
gTerrainScratchPad.addTile((*sel)[i].mHeight, (*sel)[i].mMaterial);
|
||||
else
|
||||
gTerrainScratchPad.addTile(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void pasteAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type)
|
||||
{
|
||||
if (gTerrainScratchPad.size() == 0)
|
||||
return;
|
||||
|
||||
if (gTerrainScratchPad.size() != sel->size())
|
||||
return;
|
||||
|
||||
if (type != Begin)
|
||||
return;
|
||||
|
||||
for (U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
if (isValid((*sel)[i]))
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
(*sel)[i].mHeight = gTerrainScratchPad[i]->mHeight;
|
||||
(*sel)[i].mMaterial = gTerrainScratchPad[i]->mMaterial;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
mTerrainEditor->scheduleGridUpdate();
|
||||
mTerrainEditor->scheduleMaterialUpdate();
|
||||
}
|
||||
|
||||
void pasteUpAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type)
|
||||
{
|
||||
if (gTerrainScratchPad.size() == 0)
|
||||
return;
|
||||
|
||||
if (gTerrainScratchPad.size() != sel->size())
|
||||
return;
|
||||
|
||||
if (type != Begin)
|
||||
return;
|
||||
F32 floor = F32_MAX;
|
||||
for (U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
floor = mMin((*sel)[i].mHeight, floor);
|
||||
}
|
||||
for (U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
if (isValid((*sel)[i]))
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
(*sel)[i].mHeight = gTerrainScratchPad[i]->mHeight - gTerrainScratchPad.mBottom + floor;
|
||||
(*sel)[i].mMaterial = gTerrainScratchPad[i]->mMaterial;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
mTerrainEditor->scheduleGridUpdate();
|
||||
mTerrainEditor->scheduleMaterialUpdate();
|
||||
}
|
||||
|
||||
void pasteDownAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type)
|
||||
{
|
||||
if (gTerrainScratchPad.size() == 0)
|
||||
return;
|
||||
|
||||
if (gTerrainScratchPad.size() != sel->size())
|
||||
return;
|
||||
|
||||
if (type != Begin)
|
||||
return;
|
||||
|
||||
F32 ceiling = F32_MIN_EX;
|
||||
for (U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
ceiling = mMax((*sel)[i].mHeight, ceiling);
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < sel->size(); i++)
|
||||
{
|
||||
if (isValid((*sel)[i]))
|
||||
{
|
||||
mTerrainEditor->getUndoSel()->add((*sel)[i]);
|
||||
(*sel)[i].mHeight = gTerrainScratchPad[i]->mHeight - gTerrainScratchPad.mTop + ceiling;
|
||||
(*sel)[i].mMaterial = gTerrainScratchPad[i]->mMaterial;
|
||||
mTerrainEditor->setGridInfo((*sel)[i]);
|
||||
}
|
||||
}
|
||||
mTerrainEditor->scheduleGridUpdate();
|
||||
mTerrainEditor->scheduleMaterialUpdate();
|
||||
}
|
||||
|
||||
IMPLEMENT_CONOBJECT( TerrainSmoothAction );
|
||||
|
||||
|
|
|
|||
|
|
@ -302,27 +302,94 @@ class PaintNoiseAction : public TerrainAction
|
|||
F32 mScale;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
class ThermalErosionAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
ThermalErosionAction(TerrainEditor * editor)
|
||||
: TerrainAction(editor)
|
||||
{
|
||||
mNoise.setSeed( 1 );//Sim::getCurrentTime() );
|
||||
mNoiseData.setSize( TerrainBlock::BlockSize * TerrainBlock::BlockSize );
|
||||
mTerrainHeights.setSize( TerrainBlock::BlockSize * TerrainBlock::BlockSize );
|
||||
}
|
||||
|
||||
}
|
||||
StringTableEntry getName(){return("thermalErode");}
|
||||
|
||||
void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type);
|
||||
|
||||
Noise2D mNoise;
|
||||
Vector<F32> mNoiseData;
|
||||
Vector<F32> mTerrainHeights;
|
||||
};
|
||||
*/
|
||||
|
||||
class HydraulicErosionAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
HydraulicErosionAction(TerrainEditor* editor)
|
||||
: TerrainAction(editor)
|
||||
{
|
||||
}
|
||||
|
||||
StringTableEntry getName() { return("hydraulicErode"); }
|
||||
void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
class TerrainScratchPad
|
||||
{
|
||||
public:
|
||||
F32 mBottom, mTop;
|
||||
TerrainScratchPad(): mBottom(F32_MAX), mTop(F32_MIN_EX){};
|
||||
~TerrainScratchPad() { mContents.clear(); };
|
||||
void clear();
|
||||
class gridStub
|
||||
{
|
||||
public:
|
||||
gridStub(F32 height, U8 material) : mHeight(height), mMaterial(material) {};
|
||||
F32 mHeight;
|
||||
U8 mMaterial;
|
||||
};
|
||||
void addTile(F32 height, U8 material);
|
||||
U32 size() { return(mContents.size()); };
|
||||
gridStub* operator [](U32 index) { return mContents[index]; };
|
||||
private:
|
||||
Vector<gridStub*> mContents;
|
||||
};
|
||||
|
||||
class copyAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
copyAction(TerrainEditor* editor)
|
||||
: TerrainAction(editor)
|
||||
{
|
||||
}
|
||||
StringTableEntry getName() { return("copy"); }
|
||||
void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
class pasteAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
pasteAction(TerrainEditor* editor)
|
||||
: TerrainAction(editor)
|
||||
{
|
||||
}
|
||||
StringTableEntry getName() { return("paste"); }
|
||||
void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
class pasteUpAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
pasteUpAction(TerrainEditor* editor)
|
||||
: TerrainAction(editor)
|
||||
{
|
||||
}
|
||||
StringTableEntry getName() { return("pasteUp"); }
|
||||
void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
class pasteDownAction : public TerrainAction
|
||||
{
|
||||
public:
|
||||
pasteDownAction(TerrainEditor* editor)
|
||||
: TerrainAction(editor)
|
||||
{
|
||||
}
|
||||
StringTableEntry getName() { return("pasteDown"); }
|
||||
void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type);
|
||||
};
|
||||
|
||||
/// An undo action used to perform terrain wide smoothing.
|
||||
class TerrainSmoothAction : public UndoAction
|
||||
|
|
|
|||
|
|
@ -712,8 +712,13 @@ TerrainEditor::TerrainEditor() :
|
|||
mActions.push_back(new SmoothHeightAction(this));
|
||||
mActions.push_back(new SmoothSlopeAction(this));
|
||||
mActions.push_back(new PaintNoiseAction(this));
|
||||
//mActions.push_back(new ThermalErosionAction(this));
|
||||
|
||||
mActions.push_back(new ThermalErosionAction(this));
|
||||
mActions.push_back(new HydraulicErosionAction(this));
|
||||
mActions.push_back(new copyAction(this));
|
||||
mActions.push_back(new pasteAction(this));
|
||||
mActions.push_back(new pasteUpAction(this));
|
||||
mActions.push_back(new pasteDownAction(this));
|
||||
|
||||
|
||||
// set the default action
|
||||
mCurrentAction = mActions[0];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue