SongOfTheWeave
04-02-2008 05:15:36
Reposted from the original ETM thread:
KISS smoothing function:
Stupid, fast.
It's simply checking the average height of the sample and applying it, modified by brush intensity and a passed intensity (to allow you to give the user a slider or somesuch to adjust intensity.)
This algorithm behaves similarly to the one in the NWN2 toolset that you mentioned previously and smooths well until brush size reaches around 60ish (debug build), then it struggles. YMMV as far as performance though.
------
Edit: Forgot this bit...
I suggest generating your intensity to pass to the averageFilter similar to the intensity calculations in CABAListic's ETM demo:
Where:
- m_fFrameTime is the time it took to render the last frame in milliseconds
- m_fVarIntensity is the value of that slider provided to the user that I mentioned earlier.
- m_lMouseDown is a bool storing whether the left mouse button is pressed
- m_editBrush is the brush currently being used for editing.
- and where m_currentArea->smooth is the following function:
A few notes:
KISS smoothing function:
ET::Brush Area::averageFilter(int x, int z, ET::Brush shape, float fIntensity)
{
// When you're doing a loop possibly thousands of times, it's worth setting these
// aside rather than calling a function every iteration.
size_t iWidth = shape.getWidth();
size_t iHeight = shape.getHeight();
// Faster to presize than resize
std::vector<float> vecReturnBuffer(iWidth * iHeight);
std::vector<float> vecHeightBuffer(iWidth * iHeight);
ET::Brush brushReturn = ET::Brush(vecReturnBuffer, iWidth, iHeight);
ET::Brush brushHeights = ET::Brush(vecHeightBuffer, iWidth, iHeight);
m_terrainMgr->getHeights(x, z, brushHeights);
float fSumHeights = 0.0f;
size_t iNumHeights = iWidth * iHeight;
// Find the sum of all the heights within the sample
for (Ogre::uint i = 0; i < iWidth; i++)
{
for(Ogre::uint j = 0; j < iHeight; j++)
{
fSumHeights += brushHeights.at(i, j);
}
}
// Find the average height within the sample
float fAvgHeight = fSumHeights / iNumHeights;
for (Ogre::uint i = 0; i < iWidth; i++)
{
for(Ogre::uint j = 0; j < iHeight; j++)
{
float fHeight = brushHeights.at(i, j);
float fDelta = fHeight - fAvgHeight;
float fShapeMask = shape.at(i, j);
fDelta = (fDelta * fShapeMask * fIntensity);
brushReturn.at(i, j) = fHeight - fDelta;
}
}
return brushReturn;
}
Stupid, fast.
It's simply checking the average height of the sample and applying it, modified by brush intensity and a passed intensity (to allow you to give the user a slider or somesuch to adjust intensity.)
This algorithm behaves similarly to the one in the NWN2 toolset that you mentioned previously and smooths well until brush size reaches around 60ish (debug build), then it struggles. YMMV as far as performance though.
------
Edit: Forgot this bit...
I suggest generating your intensity to pass to the averageFilter similar to the intensity calculations in CABAListic's ETM demo:
float brushIntensity = (m_fFrameTime / 1000) * 2.0 * (m_lMouseDown? 1 : -1);
brushIntensity *= m_fVarIntensity;
// translate our cursor position to vertex indexes
Ogre::Vector3 smoothPos = m_cursor->getPosition();
int x = info->posToVertexX(smoothPos.x);
int z = info->posToVertexZ(smoothPos.z);
m_currentArea->smooth(x, z, m_editBrush, brushIntensity);
Where:
- m_fFrameTime is the time it took to render the last frame in milliseconds
- m_fVarIntensity is the value of that slider provided to the user that I mentioned earlier.
- m_lMouseDown is a bool storing whether the left mouse button is pressed
- m_editBrush is the brush currently being used for editing.
- and where m_currentArea->smooth is the following function:
void Area::smooth(int x, int y, const ET::Brush& brush, float fIntensity)
{
ET::Brush smooth = averageFilter(x, y, brush, fIntensity);
m_terrainMgr->setHeights(x, y, smooth);
}
A few notes:
- - Letting the RMB make the intensity negative results in a cool "Expansion" effect, where stuff that was far from the average height gets farther, as opposed to the positive "compression" effect where stuff that is far from average height gets closer.
- Okay, so it was only one note... but if I think of something later, I'll add it here![/list:u]