History: BasicTutorial3SourceCurrent
Source of version: 5 (current)
Copy to clipboard
{CODE(caption="TutorialApplication.h" wrap="1" colors="c++")}
#include <Terrain/OgreTerrain.h>
#include <Terrain/OgreTerrainGroup.h>
#include "BaseApplication.h"
class TutorialApplication : public BaseApplication
{
public:
TutorialApplication();
virtual ~TutorialApplication();
protected:
virtual void createScene();
virtual void createFrameListener();
virtual void destroyScene();
virtual bool frameRenderingQueued(const Ogre::FrameEvent& fe);
private:
void defineTerrain(long x, long y);
void initBlendMaps(Ogre::Terrain* terrain);
void configureTerrainDefaults(Ogre::Light* light);
bool mTerrainsImported;
Ogre::TerrainGroup* mTerrainGroup;
Ogre::TerrainGlobalOptions* mTerrainGlobals;
OgreBites::Label* mInfoLabel;
};
#endif // #ifndef __TutorialApplication_h_
{CODE}
{CODE(caption="TutorialApplication.cpp" wrap="1" colors="c++")}
#include "TutorialApplication.h"
TutorialApplication::TutorialApplication()
: mTerrainGroup(0),
mTerrainGlobals(0),
mInfoLabel(0)
{
}
TutorialApplication::~TutorialApplication()
{
}
void TutorialApplication::createScene()
{
mCamera->setPosition(Ogre::Vector3(1683, 50, 2116));
mCamera->lookAt(Ogre::Vector3(1963, 50, 1660));
mCamera->setNearClipDistance(.1);
bool infiniteClip =
mRoot->getRenderSystem()->getCapabilities()->hasCapability(
Ogre::RSC_INFINITE_FAR_PLANE);
if (infiniteClip)
mCamera->setFarClipDistance(0);
else
mCamera->setFarClipDistance(50000);
mSceneMgr->setAmbientLight(Ogre::ColourValue(.2, .2, .2));
Ogre::Vector3 lightDir(.55, -.3, .75);
lightDir.normalise();
Ogre::Light* light = mSceneMgr->createLight("TestLight");
light->setType(Ogre::Light::LT_DIRECTIONAL);
light->setDirection(lightDir);
light->setDiffuseColour(Ogre::ColourValue::White);
light->setSpecularColour(Ogre::ColourValue(.4, .4, .4));
// Fog
Ogre::ColourValue fadeColour(.9, .9, .9);
mWindow->getViewport(0)->setBackgroundColour(fadeColour);
mSceneMgr->setFog(Ogre::FOG_EXP2, fadeColour, 0.002);
// Terrain
mTerrainGlobals = OGRE_NEW Ogre::TerrainGlobalOptions();
mTerrainGroup = OGRE_NEW Ogre::TerrainGroup(
mSceneMgr,
Ogre::Terrain::ALIGN_X_Z,
513, 12000.0);
mTerrainGroup->setFilenameConvention(Ogre::String("terrain"), Ogre::String("dat"));
mTerrainGroup->setOrigin(Ogre::Vector3::ZERO);
configureTerrainDefaults(light);
for (long x = 0; x <= 0; ++x)
for (long y = 0; y <= 0; ++y)
defineTerrain(x, y);
mTerrainGroup->loadAllTerrains(true);
if (mTerrainsImported)
{
Ogre::TerrainGroup::TerrainIterator ti = mTerrainGroup->getTerrainIterator();
while (ti.hasMoreElements())
{
Ogre::Terrain* t = ti.getNext()->instance;
initBlendMaps(t);
}
}
mTerrainGroup->freeTemporaryResources();
// Sky Techniques
// mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 300, false);
mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);
// Ogre::Plane plane;
// plane.d = 1000;
// plane.normal = Ogre::Vector3::NEGATIVE_UNIT_Y;
// mSceneMgr->setSkyPlane(
// true, plane, "Examples/SpaceSkyPlane", 1500, 40, true, 1.5, 150, 150);
}
void TutorialApplication::createFrameListener()
{
BaseApplication::createFrameListener();
mInfoLabel = mTrayMgr->createLabel(OgreBites::TL_TOP, "TerrainInfo", "", 350);
}
void TutorialApplication::destroyScene()
{
OGRE_DELETE mTerrainGroup;
OGRE_DELETE mTerrainGlobals;
}
bool TutorialApplication::frameRenderingQueued(const Ogre::FrameEvent& fe)
{
bool ret = BaseApplication::frameRenderingQueued(fe);
if (mTerrainGroup->isDerivedDataUpdateInProgress())
{
mTrayMgr->moveWidgetToTray(mInfoLabel, OgreBites::TL_TOP, 0);
mInfoLabel->show();
if (mTerrainsImported)
mInfoLabel->setCaption("Building terrain...");
else
mInfoLabel->setCaption("Updating textures...");
}
else
{
mTrayMgr->removeWidgetFromTray(mInfoLabel);
mInfoLabel->hide();
if (mTerrainsImported)
{
mTerrainGroup->saveAllTerrains(true);
mTerrainsImported = false;
}
}
return ret;
}
void getTerrainImage(bool flipX, bool flipY, Ogre::Image& img)
{
img.load("terrain.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
if (flipX)
img.flipAroundY();
if (flipY)
img.flipAroundX();
}
void TutorialApplication::defineTerrain(long x, long y)
{
Ogre::String filename = mTerrainGroup->generateFilename(x, y);
bool exists =
Ogre::ResourceGroupManager::getSingleton().resourceExists(
mTerrainGroup->getResourceGroup(),
filename);
if (exists)
mTerrainGroup->defineTerrain(x, y);
else
{
Ogre::Image img;
getTerrainImage(x % 2 != 0, y % 2 != 0, img);
mTerrainGroup->defineTerrain(x, y, &img);
mTerrainsImported = true;
}
}
void TutorialApplication::initBlendMaps(Ogre::Terrain* terrain)
{
Ogre::Real minHeight0 = 70;
Ogre::Real fadeDist0 = 40;
Ogre::Real minHeight1 = 70;
Ogre::Real fadeDist1 = 15;
Ogre::TerrainLayerBlendMap* blendMap0 = terrain->getLayerBlendMap(1);
Ogre::TerrainLayerBlendMap* blendMap1 = terrain->getLayerBlendMap(2);
float* pBlend0 = blendMap0->getBlendPointer();
float* pBlend1 = blendMap1->getBlendPointer();
for (Ogre::uint16 y = 0; y < terrain->getLayerBlendMapSize(); ++y)
{
for (Ogre::uint16 x = 0; x < terrain->getLayerBlendMapSize(); ++x)
{
Ogre::Real tx, ty;
blendMap0->convertImageToTerrainSpace(x, y, &tx, &ty);
Ogre::Real height = terrain->getHeightAtTerrainPosition(tx, ty);
Ogre::Real val = (height - minHeight0) / fadeDist0;
val = Ogre::Math::Clamp(val, (Ogre::Real)0, (Ogre::Real)1);
*pBlend0++ = val;
val = (height - minHeight1) / fadeDist1;
val = Ogre::Math::Clamp(val, (Ogre::Real)0, (Ogre::Real)1);
*pBlend1++ = val;
}
}
blendMap0->dirty();
blendMap1->dirty();
blendMap0->update();
blendMap1->update();
}
void TutorialApplication::configureTerrainDefaults(Ogre::Light* light)
{
mTerrainGlobals->setMaxPixelError(8);
mTerrainGlobals->setCompositeMapDistance(3000);
mTerrainGlobals->setLightMapDirection(light->getDerivedDirection());
mTerrainGlobals->setCompositeMapAmbient(mSceneMgr->getAmbientLight());
mTerrainGlobals->setCompositeMapDiffuse(light->getDiffuseColour());
Ogre::Terrain::ImportData& importData = mTerrainGroup->getDefaultImportSettings();
importData.terrainSize = 513;
importData.worldSize = 12000.0;
importData.inputScale = 600;
importData.minBatchSize = 33;
importData.maxBatchSize = 65;
importData.layerList.resize(3);
importData.layerList[0].worldSize = 100;
importData.layerList[0].textureNames.push_back(
"dirt_grayrocky_diffusespecular.dds");
importData.layerList[0].textureNames.push_back(
"dirt_grayrocky_normalheight.dds");
importData.layerList[1].worldSize = 30;
importData.layerList[1].textureNames.push_back(
"grass_green-01_diffusespecular.dds");
importData.layerList[1].textureNames.push_back(
"grass_green-01_normalheight.dds");
importData.layerList[2].worldSize = 200;
importData.layerList[2].textureNames.push_back(
"growth_weirdfungus-03_diffusespecular.dds");
importData.layerList[2].textureNames.push_back(
"growth_weirdfungus-03_normalheight.dds");
}
#if Ogre_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char *argv[])
#endif
{
// Create application object
TutorialApplication app;
try {
app.go();
} catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " <<
e.getFullDescription().c_str() << std::endl;
#endif
}
return 0;
}
#ifdef __cplusplus
}
#endif
{CODE}