
版权声明:本文为博主原创文章,未经博主允许不得转载。
拉出来的地下不平滑怎么办,笨办法就是美工一个顶点一个顶点的调整,而且效果还不好。实际上程序只要实现一个完美平滑算法,随便一刷,地形就平滑了。
平滑算法最重要的就是不能改变原来的地形的大概结构,
基本思路,就是和相邻的点取一个混合值。混合公式和alpha混合公式一样。
海滩边岩石的平滑效果非常好。
- #include "SmoothHeightAction.h"
- #include "SceneManipulator.h"
- #include "HitIndicator.h"
- namespace WX {
- //
- SmoothHeightAction::SmoothHeightAction(SceneManipulator* sceneManipulator)
- : TimeBasedHeightAction(sceneManipulator)
- {
- }
- const String& SmoothHeightAction::getName(void) const
- {
- static const String name = "SmoothHeightAction";
- return name;
- }
- void SmoothHeightAction::_onBegin(const Point& pt)
- {
- TimeBasedHeightAction::_onBegin(pt);
- //computeAverageHeight();
- }
- void SmoothHeightAction::_onDrag(const Point& pt)
- {
- TimeBasedHeightAction::_onDrag(pt);
- //computeAverageHeight();
- }
- void SmoothHeightAction::computeAverageHeight(void)
- {
- //Real totalHeight = 0;
- //Real totalWeight = 0;
- //JunctionSelection* selection = static_cast<JunctionSelection*>(
- // getSceneManipulator()->_getSelection("JunctionSelection"));
- //const JunctionSelection::JunctionMap& junctions = selection->getJunctions();
- //JunctionSelection::JunctionMap::const_iterator it;
- //for (it = junctions.begin(); it != junctions.end(); ++it)
- //{
- // const JunctionSelection::Junction& junction = it->second;
- // totalWeight += junction.weight;
- // totalHeight += getTerrainData()->getHeight(junction.x, junction.z) * junction.weight;
- //}
- //mAverageHeight = totalWeight ? totalHeight / totalWeight : 0;
- }
- Real SmoothHeightAction::_computeHeight(const JunctionSelection::Junction& junction, Real seconds)
- {
- //Real height = getTerrainData()->getHeight(junction.x, junction.z);
- //Real diff = mAverageHeight - height;
- //Real secondsRequest = Ogre::Math::Abs(diff * junction.weight / getSceneManipulator()->_getHeightAdjustSpeed());
- //if (secondsRequest < seconds)
- // return mAverageHeight;
- //else
- // return height + diff * seconds / secondsRequest;
- return 0;
- }
- void SmoothHeightAction::_onUpdate(const Point& pt, Real seconds)
- {
- // 控制每秒平滑的次数
- static Real time = 0;
- time += seconds;
- if (time > 0.1)
- {
- smooth();
- time = 0;
- }
- getSceneManipulator()->getHitIndicator("JunctionPoints")->refresh();
- getSceneManipulator()->getHitIndicator("IntersectPoint")->setHitPoint(pt);
- }
- void SmoothHeightAction::smooth(void)
- {
- // 2012.9.16 luoyinan 实现新的平滑算法,基本思路是和相邻的点取
- // 一个混合值.再通过多次采样实现完美平滑效果
- JunctionSelection* selection = static_cast<JunctionSelection*>(
- getSceneManipulator()->_getSelection("JunctionSelection"));
- //_prepareUpdate(*selection, seconds);
- const JunctionSelection::JunctionMap& junctions = selection->getJunctions();
- JunctionSelection::JunctionMap::const_iterator it;
- std::vector<TerrainInfo> terrainInfo;
- float k = 0.98;
- // 从左到右
- for (it = junctions.begin(); it != junctions.end(); ++it)
- {
- const JunctionSelection::Junction& junction = it->second;
- mModifiedJunctions->add(junction.x, junction.z, 1);
- //
- if (getTerrainData()->isValidJunction(junction.x-1,junction.z))
- {
- float oldHeight = getTerrainData()->getHeight(junction.x,junction.z);
- float newHeight = getTerrainData()->getHeight(junction.x-1,junction.z) * (1-k) + oldHeight * k;
- TerrainInfo terrInfo;
- terrInfo.x = junction.x;
- terrInfo.z = junction.z;
- terrInfo.oldHeight = junction.height;
- terrInfo.nowHeight = newHeight;
- terrainInfo.push_back(terrInfo);
- getTerrainData()->setHeight(junction.x, junction.z, newHeight);
- }
- }
- // 从右到左
- for (it = junctions.begin(); it != junctions.end(); ++it)
- {
- const JunctionSelection::Junction& junction = it->second;
- mModifiedJunctions->add(junction.x, junction.z, 1);
- //
- if (getTerrainData()->isValidJunction(junction.x+1,junction.z))
- {
- float oldHeight = getTerrainData()->getHeight(junction.x,junction.z);
- float newHeight = getTerrainData()->getHeight(junction.x+1,junction.z) * (1-k) + oldHeight * k;
- TerrainInfo terrInfo;
- terrInfo.x = junction.x;
- terrInfo.z = junction.z;
- terrInfo.oldHeight = junction.height;
- terrInfo.nowHeight = newHeight;
- terrainInfo.push_back(terrInfo);
- getTerrainData()->setHeight(junction.x, junction.z, newHeight);
- }
- }
- // 从上到下
- for (it = junctions.begin(); it != junctions.end(); ++it)
- {
- const JunctionSelection::Junction& junction = it->second;
- mModifiedJunctions->add(junction.x, junction.z, 1);
- //
- if (getTerrainData()->isValidJunction(junction.x,junction.z+1))
- {
- float oldHeight = getTerrainData()->getHeight(junction.x,junction.z);
- float newHeight = getTerrainData()->getHeight(junction.x,junction.z+1) * (1-k) + oldHeight * k;
- TerrainInfo terrInfo;
- terrInfo.x = junction.x;
- terrInfo.z = junction.z;
- terrInfo.oldHeight = junction.height;
- terrInfo.nowHeight = newHeight;
- terrainInfo.push_back(terrInfo);
- getTerrainData()->setHeight(junction.x, junction.z, newHeight);
- }
- }
- // 从下到上
- for (it = junctions.begin(); it != junctions.end(); ++it)
- {
- const JunctionSelection::Junction& junction = it->second;
- mModifiedJunctions->add(junction.x, junction.z, 1);
- //
- if (getTerrainData()->isValidJunction(junction.x,junction.z-1))
- {
- float oldHeight = getTerrainData()->getHeight(junction.x,junction.z);
- float newHeight = getTerrainData()->getHeight(junction.x,junction.z-1) * (1-k) + oldHeight * k;
- TerrainInfo terrInfo;
- terrInfo.x = junction.x;
- terrInfo.z = junction.z;
- terrInfo.oldHeight = junction.height;
- terrInfo.nowHeight = newHeight;
- terrainInfo.push_back(terrInfo);
- getTerrainData()->setHeight(junction.x, junction.z, newHeight);
- }
- }
- getSceneManipulator()->_fireTerrainHeightChanged(terrainInfo);
- selection->notifyModified();
- }
- }