По прочтению перевода у вас может возникнуть 2 вопроса.
1. Где взять текстуры для скибокса?
2. Где взять генератор Heightmap"(карт высот) которая является всего лишь gray scale(градиентом серого)".
Текстуры для скибокса можно сделать самому посредством фотошопа или 3D Studio Max-а, а можно взять с сайта, подобного этому:
http://www.alusion-fr.com/fr1ffa.htm
Как генерировать карты высот?
Идём сюда и смотрим:
http://gcup.ru/forum/58-4206-1
Качаем L3DT по ссылке.
То, что выделено зелёным выполняем до шага 9, 9 шаг нам не нужен.
Единственное примечание, чтобы "гористость" была близка тому как в примере Иррлихта на шаге 4 выбираем гористость повыше. Остальное по вкусу. Итак, карта готова. Нам из этого понадобятся 2 вещи:
а) Карта высот. В L3DT она называется Heightfield. Перед тем как экспортировать её надо сжать, изначально она имеет размер 1024х1024. А нам надо как в примере Иррлихта 256х256, так и гористость будет та, что надо. А если брать в оригинальном размере, то плосковато получится. Operations->Heightfield->Resize Heightfield->256х256. Далее, после сжатия, выбираем закладку Heightfield. Ждём пока загрузится. Нажимаем правой кнопкой на той же вкладке Heightfield->Export layer. Выбираем формат Heightmap файла, я выбрал *.jpg. Имя файла по вкусу и место куда его писать. Ok. Готово.
б) Карта текстур. В L3DT она называется Texture Map. Я её взял в том размере, в котором она и была: 1024x1024. Аналогично пункту "а". Выделить закладку, подождать когда загрузится, правой кнопкой->Export layer...
Ах, да. И ещё один важный момент. Чтобы скибокс отображался корректно главный девайс иррлихта надо создавать как в этом примере(012 Terrain Rendering). Если его создать так, как написано в начальных туториалах скибокс может отображаться некорректно. Т.е. создавать надо примерно так:
Далее.
Встраиваем карту высот в Иррлихт, надеваем текстуру. Детализирующую текстуру можно оставить Иррлихтовскую - результат (у меня по крайней мере) столь же замечательный.
Встраиваем свой скибокс. Масштабируем террэин по вкусу. Наслаждаемся результатом...
Что? Вы не знаете как встраивать в Иррлихт всё это, как масштабировать террэин?
Тогда читайте:
/** Example 012 Terrain Rendering(Пример 012 Рендеринг Территории)
Этот туториал вкратце покажет как использовать визуализацию
местности в Иррлихте. Так же покажем как настраивать селектор
треугольников для взаимодействия с визуализированной территорией,
чтобы имело место обнаружение столкновений узла сцены с территорией.
Обратите внимание Terrain Renderer(рендерринг территории) в Иррлихт
основывается на Spintz' GeoMipMapSceneNode, очень благодарен ему.
DeusXL представил новое элегантное и простое решение для построения
больших площадей на небольших heightmaps -> terrain smoothing
(heightmaps = карты высот, terrain smoothing = сглаживание территории).
Поначалу здесь нет ничего особенного. Мы извлекаем необходимые
файлы заголовков и создаём список событий, чтобы фиксировать
нажатия пользователем клавиш: клавиша 'W' для переключения в режим
каркаса, клавиша 'P' переключает в режим pointcloud(облако точек),
и клавиша 'D' переключает между режимами твёрдого и
детализированного отображения материала.
(при переводе использовалась информация:
http://ru.wikipedia.org/wiki/LOD)
*/#include<irrlicht.h>#include"driverChoice.h"usingnamespace irr;
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")#endifclass MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(scene::ISceneNode* terrain, scene::ISceneNode* skybox, scene::ISceneNode* skydome) :
Terrain(terrain), Skybox(skybox), Skydome(skydome), showBox(true)
{
Skybox->setVisible(true);
Skydome->setVisible(false);
}
bool OnEvent(const SEvent& event)
{
// проверить нажал ли пользователь искомые клавишиif(event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
{
switch(event.KeyInput.Key)
{
case irr::KEY_KEY_W: // Перекоючатель в каркасный режим
Terrain->setMaterialFlag(video::EMF_WIREFRAME,
!Terrain->getMaterial(0).Wireframe);
Terrain->setMaterialFlag(video::EMF_POINTCLOUD, false);
returntrue;
case irr::KEY_KEY_P: // Перекоючатель в "облако точек"
Terrain->setMaterialFlag(video::EMF_POINTCLOUD,
!Terrain->getMaterial(0).PointCloud);
Terrain->setMaterialFlag(video::EMF_WIREFRAME, false);
returntrue;
case irr::KEY_KEY_D: // режимы детализации карты
Terrain->setMaterialType(
Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ?
video::EMT_DETAIL_MAP : video::EMT_SOLID);
returntrue;
case irr::KEY_KEY_S: // переключить небо
showBox=!showBox;
Skybox->setVisible(showBox);
Skydome->setVisible(!showBox);
returntrue;
default:
break;
}
}
returnfalse;
}
private:
scene::ISceneNode* Terrain;
scene::ISceneNode* Skybox;
scene::ISceneNode* Skydome;
bool showBox;
};
/*
Начинаем с ф-ции main() как в большинстве других примеров.
Мы спрашиваем пользователя о желаемом типе визуализации и
впускаем его. На этот раз работаем с параметрами главного
устройства более продвинуто.
*/int main()
{
//спросить пользователя про драйвер
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if(driverType==video::EDT_COUNT)return1;
//создать устройство с полной гибкостью над заданием параметров//вы можете добавить больше параметров если пожелаете, используя://irr::SIrrlichtCreationParameters
irr::SIrrlichtCreationParameters params;
params.DriverType=driverType;
params.WindowSize=core::dimension2d<u32>(640, 480);
IrrlichtDevice* device = createDeviceEx(params);
if(device == 0)return1; //не удалось создать устройство./*
Перавым делом, мы добавляем стандартьные элементы сцены:
Симпатичный логотип движка иррлихт, маленький текст справки,
контролируемую пользователем камеру, и мы запрещаем
курсор мыши.
*/
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
gui::IGUIEnvironment* env = device->getGUIEnvironment();
driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
//добавить логотип иррлихта
env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"),
core::position2d<s32>(10,10));
//установить другой шрифт
env->getSkin()->setFont(env->getFont("../../media/fontlucida.png"));
//добавить текст справки
env->addStaticText(
L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map\nPress 'S' to toggle skybox/skydome",
core::rect<s32>(10,421,250,475), true, true, 0, -1, true);
//добавить камеру
scene::ICameraSceneNode* camera =
smgr->addCameraSceneNodeFPS(0,100.0f,1.2f);
camera->setPosition(core::vector3df(2700*2,255*2,2600*2));
camera->setTarget(core::vector3df(2397*2,343*2,2700*2));
camera->setFarValue(42000.0f);
//запретить курсор мыши
device->getCursorControl()->setVisible(false);
/*
А вот и узел сцены визуализации территории: Мы добавляем его как
и любой другой узел сцены с помощью
ISceneManager::addTerrainSceneNode().
Единственный параметр, который мы используем, - это
имя файла heightmap(карты высот), которую потребно использовать.
Heightmap(карта высот) является всего лишь gray scale(градиент серого)
текстурой. Terrain renderer(рендеринг территорий) загружает её и создаёт
3D terrain(трёхмерную территорию) из неё.
Для того чтобы сделать территорию выгдядщей побольше, мы изменим
коэффициент масштабирования на (40, 4.4, 40). Так как у нас нет
динамического освещения в сцене мы, отключаем освещение, и
устанавливаем terrain-texture.jpg как текстуру для территории и
detailmap3.jpg как вторичную текстуру, делающую карту более
детальной(detail map). И наконец, мы устанавливаем коэффициент
масштабирования для текстуры: Первая текстура будет повторяться
только 1 раз(растянута на всю территорию), а вторая(detail map) 20 раз.
*///добавить узел сцены территории
scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode("../../media/terrain-heightmap.bmp",
0, //parent node(корневой узел)
-1, //node id(идентификатор узла)
core::vector3df(0.f, 0.f, 0.f), //position(позиция)
core::vector3df(0.f, 0.f, 0.f), //rotation(поворот, ротация)
core::vector3df(40.f, 4.4f, 40.f), //scale(масштабирование)
video::SColor (255, 255, 255, 255), //vertexColor(цвет вершин)5, //maxLOD (максимальный уровень детализации)
scene::ETPS_17, //patchSize(размер куска карты?)4//smoothFactor(фактор сглаживания));
terrain->setMaterialFlag(video::EMF_LIGHTING, false);
terrain->setMaterialTexture(0,
driver->getTexture("../../media/terrain-texture.jpg"));
terrain->setMaterialTexture(1,
driver->getTexture("../../media/detailmap3.jpg"));
terrain->setMaterialType(video::EMT_DETAIL_MAP);
terrain->scaleTexture(1.0f, 20.0f);
//terrain->setDebugDataVisible ( true );/*
Для того, чтобы фиксировать столкновения с территорией, мы
создадим селектор треугольников.
Если вы хотите знать, что делают селекторы треугольников, просто
посмотрите туториал по столкновениям. Terrain triangle
selector(Территориальный селектор треугольников) работает совместно
с территорией. Для демонстрации этого, мы создадим аниматор
реакции на столкновения и прикрепим его к камере, так что камера не сможет
пролетать сквозь землю.
*///создать селектор треугольников для территории
scene::ITriangleSelector* selector
= smgr->createTerrainTriangleSelector(terrain, 0);
terrain->setTriangleSelector(selector);
//создать аниматор реакции на столкновение и присоединить его к камере
scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
selector, camera, core::vector3df(60,100,60),
core::vector3df(0,0,0),
core::vector3df(0,50,0));
selector->drop();
camera->addAnimator(anim);
anim->drop();
/* Если вы нуждаетесь в доступе к данным территории
вы можете сделать это прямо с помощью следующего
фрагмента кода.
*/
scene::CDynamicMeshBuffer* buffer = new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT);
terrain->getMeshBufferForLOD(*buffer, 0);
video::S3DVertex2TCoords* data = (video::S3DVertex2TCoords*)buffer->getVertexBuffer().getData();
//Работайте с переменной data или получите IndexBuffer аналогичным способом.
buffer->drop(); //Когда работа выполнена освободить буфер./*
Для того, чтобы сделать, чтобы пользователь был в состоянии переключаться
между нормаьным и каркасным режимом, мы создадим event
reciever(получальщик событий) и позволим Иррлихту узнать об этом.
В добавок, мы добавим skybox(звёздный ящик) который мы уже использовали
во многих примерах Иррлихта и skydome(звёздный купол), который
видим взаимноисключающе с skybox. Для переключения со skybox на
skydome надо нажать 'S'.
*///создать skybox и skydome
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
scene::ISceneNode* skybox=smgr->addSkyBoxSceneNode(
driver->getTexture("../../media/irrlicht2_up.jpg"),
driver->getTexture("../../media/irrlicht2_dn.jpg"),
driver->getTexture("../../media/irrlicht2_lf.jpg"),
driver->getTexture("../../media/irrlicht2_rt.jpg"),
driver->getTexture("../../media/irrlicht2_ft.jpg"),
driver->getTexture("../../media/irrlicht2_bk.jpg"));
scene::ISceneNode* skydome=smgr->addSkyDomeSceneNode(
driver->getTexture("../../media/skydome.jpg"),16,8,0.95f,2.0f);
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
//создать event receiver(получальщиек событий)
MyEventReceiver receiver(terrain, skybox, skydome);
device->setEventReceiver(&receiver);
/*
Вот и всё, отрисовываем всё.
*/int lastFPS = -1;
while(device->run())if(device->isWindowActive())
{
driver->beginScene(true, true, 0);
smgr->drawAll();
env->drawAll();
driver->endScene();
//Отобразить кадры в секунду(FPS) в заголовке окнаint fps = driver->getFPS();
if(lastFPS != fps)
{
core::stringw str = L"Terrain Renderer - Irrlicht Engine [";
str += driver->getName();
str += "] FPS:";
str += fps;
//Кроме того напечатаем высоту территории согласно текущей позиции камеры//Мы можем использовать позицию камеры потому,//что территория находится в начале координат
str += " Height: ";
str += terrain->getHeight(camera->getAbsolutePosition().X,
camera->getAbsolutePosition().Z);
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
device->drop();
return0;
}
/*
Теперь вы знаете, как использовать территории в Иррлихте.
**/