Туториал №22: Просмотрщик материалов
|
|
MerGC_Team | Дата: Четверг, 03.04.2014, 18:36 | Сообщение # 1 |
Веселый админ
Группа: Администраторы
Сообщений: 32
Статус: Оффлайн
| Этот пример может быть использован для того, чтобы поиграть с установками материалов и оценить результат. Здесь используются только нешейдерные стандартные материалы.
У вас имеется две ноды-кубышки, чтобы облегчить просмотр того, какой результат вызывают изменения установок. Вдобавок вы имеете одну ноду-источник света и вы можете устанавливать глобальные переменные окружения. Код #include < irrlicht.h > #include "driverChoice.h"
using namespace irr;
#ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif
Переменные в пределах неименованного namespace(пространства имён) являются глобальными, с видимостью ограниченной данным файлом. Код namespace { const wchar_t* const DriverTypeNames[] = { L"NULL", L"SOFTWARE", L"BURNINGSVIDEO", L"DIRECT3D8", L"DIRECT3D9", L"OPENGL", 0, };
// Для идентификаторов(id) gui enum EGUI_IDS { GUI_ID_OPEN_TEXTURE = 1, GUI_ID_QUIT, GUI_ID_MAX };
// Текст пункта в меню выбора текстур, этот пункт будет означать "снять текстуру" const core::stringw CLEAR_TEXTURE = L"CLEAR texture";
// несколько полезных констант const video::SColor SCOL_BLACK = video::SColor(255, 0,0,0); const video::SColor SCOL_BLUE= video::SColor(255, 0,0, 255); const video::SColor SCOL_CYAN= video::SColor(255, 0, 255, 255); const video::SColor SCOL_GRAY= video::SColor(255, 128,128, 128); const video::SColor SCOL_GREEN = video::SColor(255, 0, 255, 0); const video::SColor SCOL_MAGENTA= video::SColor(255, 255, 0, 255); const video::SColor SCOL_RED = video::SColor(255, 255, 0,0); const video::SColor SCOL_YELLOW = video::SColor(255, 255, 255, 0); const video::SColor SCOL_WHITE = video::SColor(255, 255, 255, 255); };// пространство имен
Возвращает новое уникальное значение при каждом вызове. Код s32 makeUniqueId() { static int unique = GUI_ID_MAX; ++unique; return unique; }
Находит какой тип вершин требуется для данного типа материала. Код video::E_VERTEX_TYPE getVertexTypeForMaterialType(video::E_MATERIAL_TYPE materialType) { using namespace video;
switch ( materialType ) { case EMT_SOLID: return EVT_STANDARD;
case EMT_SOLID_2_LAYER: return EVT_STANDARD;
case EMT_LIGHTMAP: case EMT_LIGHTMAP_ADD: case EMT_LIGHTMAP_M2: case EMT_LIGHTMAP_M4: case EMT_LIGHTMAP_LIGHTING: case EMT_LIGHTMAP_LIGHTING_M2: case EMT_LIGHTMAP_LIGHTING_M4: return EVT_2TCOORDS;
case EMT_DETAIL_MAP: return EVT_2TCOORDS;
case EMT_SPHERE_MAP: return EVT_STANDARD;
case EMT_REFLECTION_2_LAYER: return EVT_2TCOORDS;
case EMT_TRANSPARENT_ADD_COLOR: return EVT_STANDARD;
case EMT_TRANSPARENT_ALPHA_CHANNEL: return EVT_STANDARD;
case EMT_TRANSPARENT_ALPHA_CHANNEL_REF: return EVT_STANDARD;
case EMT_TRANSPARENT_VERTEX_ALPHA: return EVT_STANDARD;
case EMT_TRANSPARENT_REFLECTION_2_LAYER: return EVT_2TCOORDS;
case EMT_NORMAL_MAP_SOLID: case EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR: case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA: case EMT_PARALLAX_MAP_SOLID: case EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR: case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA: return EVT_TANGENTS;
case EMT_ONETEXTURE_BLEND: return EVT_STANDARD;
case EMT_FORCE_32BIT: return EVT_STANDARD; } return EVT_STANDARD; }
Пользовательский GUI интерфейс для редактирования цветовых значений. Код class CColorControl : public gui::IGUIElement { public: // конструктор CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2d< s32 > & pos, const wchar_t *text, IGUIElement* parent, s32 id=-1 ) : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos, pos+core::dimension2d< s32 >(80, 75))) , DirtyFlag(true) , ColorStatic(0) , EditAlpha(0) , EditRed(0) , EditGreen(0) , EditBlue(0) { using namespace gui; ButtonSetId = makeUniqueId();
const core::rect< s32 > rectControls(0,0,AbsoluteRect.getWidth(),AbsoluteRect.getHeight() ); IGUIStaticText * groupElement = guiEnv->addStaticText (L"", rectControls, true, false, this, -1, false); groupElement->setNotClipped(true);
guiEnv->addStaticText (text, core::rect< s32 >(0,0,80,15), false, false, groupElement, -1, false);
EditAlpha = addEditForNumbers(guiEnv, core::position2d< s32 >(0,15), L"a", -1, groupElement ); EditRed = addEditForNumbers(guiEnv, core::position2d< s32 >(0,30), L"r", -1, groupElement ); EditGreen = addEditForNumbers(guiEnv, core::position2d< s32 >(0,45), L"g", -1, groupElement ); EditBlue = addEditForNumbers(guiEnv, core::position2d< s32 >(0,60), L"b", -1, groupElement );
ColorStatic = guiEnv->addStaticText (L"", core::rect< s32 >(60,15,80,75), true, false, groupElement, -1, true);
guiEnv->addButton (core::rect< s32 >(60,35,80,50), groupElement, ButtonSetId, L"set"); SetEditsFromColor(Color); }
// обработчик событий virtual bool OnEvent(const SEvent &event) { if ( event.EventType != EET_GUI_EVENT ) return false;
if ( event.GUIEvent.Caller->getID() == ButtonSetId && event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) { Color = GetColorFromEdits(); SetEditsFromColor(Color); }
return false; }
// установить значение цвета void setColor(const video::SColor& col) { DirtyFlag = true; Color = col; SetEditsFromColor(Color); }
// получить значение цвета const video::SColor& getColor() const { return Color; }
// сбросить флаг черновика void resetDirty() { DirtyFlag = false; }
// если цвет изменился, то флаг черновика установлен bool isDirty() const { return DirtyFlag; };
protected:
// Добавляет текстовую метку и поле ввода для цифровых значений gui::IGUIEditBox* addEditForNumbers(gui::IGUIEnvironment* guiEnv, const core::position2d< s32 > & pos, const wchar_t *text, s32 id, gui::IGUIElement * parent) { using namespace gui;
core::rect< s32 > rect(pos, pos+core::dimension2d< s32 >(10, 15)); guiEnv->addStaticText (text, rect, false, false, parent, -1, false); rect += core::position2d< s32 <img src="http://s80.ucoz.net/sm/7/angry.gif" border="0" align="absmiddle" alt="angry" /> 20, 0 ); rect.LowerRightCorner.X += 20; gui::IGUIEditBox* edit = guiEnv->addEditBox(L"0", rect, true, parent, id); return edit; }
// получает значение из поля ввода video::SColor GetColorFromEdits() { video::SColor col;
u32 alpha=col.getAlpha(); if ( EditAlpha ) { alpha = (u32)core::strtol10( core::stringc( EditAlpha->getText() ).c_str(), 0); if ( alpha > 255 ) alpha = 255; } col.setAlpha(alpha);
u32 red=col.getRed(); if ( EditRed ) { red = (u32)core::strtol10( core::stringc( EditRed->getText() ).c_str(), 0); if ( red > 255 ) red = 255; } col.setRed(red);
u32 green=col.getGreen(); if ( EditGreen ) { green = (u32)core::strtol10( core::stringc( EditGreen->getText() ).c_str(), 0); if ( green > 255 ) green = 255; } col.setGreen(green);
u32 blue=col.getBlue(); if ( EditBlue ) { blue = (u32)core::strtol10( core::stringc( EditBlue->getText() ).c_str(), 0); if ( blue > 255 ) blue = 255; } col.setBlue(blue);
return col; }
// заполняет поле ввода значением заданного цвета void SetEditsFromColor(video::SColor col) { DirtyFlag = true; if ( EditAlpha ) EditAlpha->setText( core::stringw(col.getAlpha()).c_str() ); if ( EditRed ) EditRed->setText( core::stringw(col.getRed()).c_str() ); if ( EditGreen ) EditGreen->setText( core::stringw(col.getGreen()).c_str() ); if ( EditBlue ) EditBlue->setText( core::stringw(col.getBlue()).c_str() ); if ( ColorStatic ) ColorStatic->setBackgroundColor(col); }
private:
bool DirtyFlag; video::SColor Color; s32 ButtonSetId; gui::IGUIStaticText * ColorStatic; gui::IGUIEditBox * EditAlpha; gui::IGUIEditBox * EditRed; gui::IGUIEditBox * EditGreen; gui::IGUIEditBox * EditBlue; };
|
|
| |
MerGC_Team | Дата: Четверг, 03.04.2014, 18:37 | Сообщение # 2 |
Веселый админ
Группа: Администраторы
Сообщений: 32
Статус: Оффлайн
| Пользовательский GUI-интерфейс для редактирования всех цветов, обычно используется в материалах и источниках света Код class CAllColorsControl : public gui::IGUIElement { public: // конструктор CAllColorsControl(gui::IGUIEnvironment* guiEnv, const core::position2d< s32 > & pos, const wchar_t * description, bool hasEmissive, IGUIElement* parent, s32 id=-1) : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos,pos+core::dimension2d< s32 >(60,250))) , ControlAmbientColor(0), ControlDiffuseColor(0), ControlSpecularColor(0), ControlEmissiveColor(0) { core::rect< s32 > rect(0, 0, 60, 15); guiEnv->addStaticText (description, rect, false, false, this, -1, false); createColorControls(guiEnv, core::position2d< s32 >(0, 15), hasEmissive); }
// деструктор virtual ~CAllColorsControl() { ControlAmbientColor->drop(); ControlDiffuseColor->drop(); ControlEmissiveColor->drop(); ControlSpecularColor->drop(); }
// установить контрольные значения цветов по заданному материалу void setColorsToMaterialColors(const video::SMaterial & material) { ControlAmbientColor->setColor(material.AmbientColor); ControlDiffuseColor->setColor(material.DiffuseColor); ControlEmissiveColor->setColor(material.EmissiveColor); ControlSpecularColor->setColor(material.SpecularColor); }
// обновить все изменившиеся цвета в материале void updateMaterialColors(video::SMaterial & material) { if ( ControlAmbientColor->isDirty() ) material.AmbientColor = ControlAmbientColor->getColor(); if ( ControlDiffuseColor->isDirty() ) material.DiffuseColor = ControlDiffuseColor->getColor(); if ( ControlEmissiveColor->isDirty() ) material.EmissiveColor = ControlEmissiveColor->getColor(); if ( ControlSpecularColor->isDirty() ) material.SpecularColor = ControlSpecularColor->getColor(); }
// установить значения цветов по световым данным void setColorsToLightDataColors(const video::SLight & lightData) { ControlAmbientColor->setColor(lightData.AmbientColor.toSColor()); ControlAmbientColor->setColor(lightData.DiffuseColor.toSColor()); ControlAmbientColor->setColor(lightData.SpecularColor.toSColor()); }
// обновить все изменившиеся цвета в световых данных void updateMaterialColors(video::SLight & lightData) { if ( ControlAmbientColor->isDirty() ) lightData.AmbientColor = video::SColorf( ControlAmbientColor->getColor() ); if ( ControlDiffuseColor->isDirty() ) lightData.DiffuseColor = video::SColorf( ControlDiffuseColor->getColor() ); if ( ControlSpecularColor->isDirty() ) lightData.SpecularColor = video::SColorf(ControlSpecularColor->getColor() ); }
// сброс флагов черновика void resetDirty() { ControlAmbientColor->resetDirty(); ControlDiffuseColor->resetDirty(); ControlSpecularColor->resetDirty(); ControlEmissiveColor->resetDirty(); }
protected: void createColorControls(gui::IGUIEnvironment* guiEnv, const core::position2d< s32 > & pos, bool hasEmissive) { ControlAmbientColor = new CColorControl( guiEnv, pos, L"ambient", this); ControlDiffuseColor = new CColorControl( guiEnv, pos + core::position2d< s32 >(0, 75), L"diffuse", this ); ControlSpecularColor = new CColorControl( guiEnv, pos + core::position2d< s32 >(0, 150), L"specular", this ); if ( hasEmissive ) { ControlEmissiveColor = new CColorControl( guiEnv, pos + core::position2d< s32 >(0, 225), L"emissive", this ); } }
private: CColorControl* ControlAmbientColor; CColorControl* ControlDiffuseColor; CColorControl* ControlSpecularColor; CColorControl* ControlEmissiveColor; };
GUI-интерфейс для выбора доступных текстур. Код class CTextureControl : public gui::IGUIElement { public: CTextureControl(gui::IGUIEnvironment* guiEnv, video::IVideoDriver * driver, const core::position2d & pos, IGUIElement* parent, s32 id=-1) : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos,pos+core::dimension2d< s32 >(100,15))) , DirtyFlag(true), ComboTexture(0) { core::rect< s32 > rectCombo(0, 0, AbsoluteRect.getWidth(),AbsoluteRect.getHeight()); ComboTexture = guiEnv->addComboBox (rectCombo, this); updateTextures(driver); }
virtual bool OnEvent(const SEvent &event) { if ( event.EventType != EET_GUI_EVENT ) return false;
if ( event.GUIEvent.Caller == ComboTexture && event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED ) { DirtyFlag = true; }
return false; }
// Обрабатываем проблему выпадающих списков, когда они рисуются // под другими элементами, выносим их наверх. virtual bool bringToFront(IGUIElement* element) { bool result = gui::IGUIElement::bringToFront(element); if ( Parent && element == ComboTexture ) result &= Parent->bringToFront(this); return result; }
// возвращаяем имя текстуры, если таковое имеется const wchar_t * getSelectedTextureName() const { s32 selected = ComboTexture->getSelected(); if ( selected < 0 ) return 0; return ComboTexture->getItem(selected); }
// сбрасываем влаг черновика void resetDirty() { DirtyFlag = false; }
// если текстура изменилась, то флаг черновика установлен bool isDirty() const { return DirtyFlag; };
// вставить имена всех загруженных текстур в выпадающий список void updateTextures(video::IVideoDriver * driver) { s32 oldSelected = ComboTexture->getSelected(); s32 selectNew = -1; const wchar_t * oldTextureName = 0; if ( oldSelected >= 0 ) { oldTextureName = ComboTexture->getItem(oldSelected); } ComboTexture->clear(); for ( u32 i=0; i < driver->getTextureCount(); ++i ) { video::ITexture * texture = driver->getTextureByIndex(i); core::stringw name( texture->getName() ); ComboTexture->addItem( name.c_str() ); if ( oldTextureName && selectNew < 0 && name == oldTextureName ) selectNew = i; }
// добавляем пункт списка для очистки текстуры ComboTexture->addItem( CLEAR_TEXTURE.c_str() ); if ( CLEAR_TEXTURE == oldTextureName ) selectNew = ComboTexture->getItemCount()-1;
if ( selectNew >= 0 ) ComboTexture->setSelected(selectNew);
DirtyFlag = true; }
private: bool DirtyFlag; gui::IGUIComboBox * ComboTexture; };
Контролер, который позволяет устанвоить некоторые значения материалов для ноды-меша Код struct SMeshNodeControl { // конструктор SMeshNodeControl() : Initialized(false), Driver(0), MeshManipulator(0), SceneNode(0), SceneNode2T(0), SceneNodeTangents(0) , AllColorsControl(0), ButtonLighting(0), InfoLighting(0), ComboMaterial(0), TextureControl1(0), TextureControl2(0), ControlVertexColors(0) { }
// деструктор virtual ~SMeshNodeControl() { if ( TextureControl1 ) TextureControl1->drop(); if ( TextureControl2 ) TextureControl2->drop(); if ( ControlVertexColors ) ControlVertexColors->drop(); }
void init(scene::IMeshSceneNode* node, IrrlichtDevice * device, const core::position2d< s32 > & pos, const wchar_t * description) { if ( Initialized || !node || !device) // двойная инициализация или наличие пустых данных недопустимы return;
Driver = device->getVideoDriver (); gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment(); scene::ISceneManager* smgr = device->getSceneManager(); MeshManipulator = smgr->getMeshManipulator();
SceneNode = node; scene::IMeshManipulator * meshManip = smgr->getMeshManipulator();
scene::IMesh * mesh2T = meshManip->createMeshWith2TCoords(node->getMesh()); SceneNode2T = smgr->addMeshSceneNode(mesh2T, 0, -1, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() ); mesh2T->drop();
scene::IMesh * meshTangents = meshManip->createMeshWithTangents(node->getMesh(), false, false, false); SceneNodeTangents = smgr->addMeshSceneNode(meshTangents, 0, -1 , SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() ); meshTangents->drop();
video::SMaterial & material = SceneNode->getMaterial(0); material.Lighting = true; AllColorsControl = new CAllColorsControl(guiEnv, pos, description, true, guiEnv->getRootGUIElement()); AllColorsControl->setColorsToMaterialColors(material);
core::rect< s32 > rectBtn(pos + core::position2d(0, 320), core::dimension2d< s32 >(60, 15)); ButtonLighting = guiEnv->addButton (rectBtn, 0, -1, L"Lighting"); ButtonLighting->setIsPushButton(true); ButtonLighting->setPressed(material.Lighting); core::rect< s32 > rectInfo( rectBtn.LowerRightCorner.X, rectBtn.UpperLeftCorner.Y, rectBtn.LowerRightCorner.X+40, rectBtn.UpperLeftCorner.Y+15 ); InfoLighting = guiEnv->addStaticText(L"", rectInfo, true, false ); InfoLighting->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER );
core::rect< s32 > rectCombo(pos.X, rectBtn.LowerRightCorner.Y, pos.X+100, rectBtn.LowerRightCorner.Y+15); ComboMaterial = guiEnv->addComboBox (rectCombo); for ( int i=0; i <= (int)video::EMT_ONETEXTURE_BLEND; ++i ) { ComboMaterial->addItem( core::stringw(video::sBuiltInMaterialTypeNames[i]).c_str() ); } ComboMaterial->setSelected( (s32)material.MaterialType );
core::position2d< s32 > posTex(rectCombo.UpperLeftCorner.X,rectCombo.LowerRightCorner.Y); TextureControl1 = new CTextureControl(guiEnv, Driver, posTex, guiEnv->getRootGUIElement()); posTex.Y += 15; TextureControl2 = new CTextureControl(guiEnv, Driver, posTex, guiEnv->getRootGUIElement());
core::position2d< s32 > posVertexColors( posTex.X, posTex.Y + 15); ControlVertexColors = new CColorControl( guiEnv, posVertexColors, L"Vertex colors", guiEnv->getRootGUIElement());
video::S3DVertex * vertices = (video::S3DVertex *)node->getMesh()->getMeshBuffer(0)->getVertices(); if ( vertices ) { ControlVertexColors->setColor(vertices[0].Color); }
Initialized = true; }
void update() { if ( !Initialized ) return;
video::SMaterial & material = SceneNode->getMaterial(0); video::SMaterial & material2T = SceneNode2T->getMaterial(0); video::SMaterial & materialTangents = SceneNodeTangents->getMaterial(0);
s32 selectedMaterial = ComboMaterial->getSelected(); if ( selectedMaterial >= (s32)video::EMT_SOLID && selectedMaterial <= (s32)video::EMT_ONETEXTURE_BLEND) { video::E_VERTEX_TYPE vertexType = getVertexTypeForMaterialType((video::E_MATERIAL_TYPE)selectedMaterial); switch ( vertexType ) { case video::EVT_STANDARD: material.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; SceneNode->setVisible(true); SceneNode2T->setVisible(false); SceneNodeTangents->setVisible(false); break; case video::EVT_2TCOORDS: material2T.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; SceneNode->setVisible(false); SceneNode2T->setVisible(true); SceneNodeTangents->setVisible(false); break; case video::EVT_TANGENTS: materialTangents.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; SceneNode->setVisible(false); SceneNode2T->setVisible(false); SceneNodeTangents->setVisible(true); break; } }
updateMaterial(material); updateMaterial(material2T); updateMaterial(materialTangents);
if ( ButtonLighting->isPressed() ) InfoLighting->setText(L"on"); else InfoLighting->setText(L"off");
AllColorsControl->resetDirty(); TextureControl1->resetDirty(); TextureControl2->resetDirty(); ControlVertexColors->resetDirty(); }
void updateTextures() { TextureControl1->updateTextures(Driver); TextureControl2->updateTextures(Driver); }
protected:
void updateMaterial(video::SMaterial & material) { AllColorsControl->updateMaterialColors(material); material.Lighting = ButtonLighting->isPressed(); if ( TextureControl1->isDirty() ) { material.TextureLayer[0].Texture = Driver->getTexture( io::path(TextureControl1->getSelectedTextureName()) ); } if ( TextureControl2->isDirty() ) { material.TextureLayer[1].Texture = Driver->getTexture( io::path(TextureControl2->getSelectedTextureName()) ); } if ( ControlVertexColors->isDirty() ) { MeshManipulator->setVertexColors (SceneNode->getMesh(), ControlVertexColors->getColor()); MeshManipulator->setVertexColors (SceneNode2T->getMesh(), ControlVertexColors->getColor()); MeshManipulator->setVertexColors (SceneNodeTangents->getMesh(), ControlVertexColors->getColor()); } }
bool Initialized; video::IVideoDriver * Driver; scene::IMeshManipulator* MeshManipulator; scene::IMeshSceneNode* SceneNode; scene::IMeshSceneNode* SceneNode2T; scene::IMeshSceneNode* SceneNodeTangents; CAllColorsControl* AllColorsControl; gui::IGUIButton * ButtonLighting; gui::IGUIStaticText*InfoLighting; gui::IGUIComboBox * ComboMaterial; CTextureControl*TextureControl1; CTextureControl*TextureControl2; CColorControl* ControlVertexColors; };
Контроллер, управлящий установками значений цвета для ноды-источника света. Код struct SLightNodeControl { // конструктор SLightNodeControl() : Initialized(false), SceneNode(0), AllColorsControl(0) { }
void init(scene::ILightSceneNode* node, gui::IGUIEnvironment* guiEnv, const core::position2d< s32 > & pos, const wchar_t * description) { if ( Initialized || !node || !guiEnv) // двойная инициализация или пустые данные недопустимы return; SceneNode = node; AllColorsControl = new CAllColorsControl(guiEnv, pos, description, false, guiEnv->getRootGUIElement()); const video::SLight & lightData = SceneNode->getLightData(); AllColorsControl->setColorsToLightDataColors(lightData); Initialized = true; }
void update() { if ( !Initialized ) return;
video::SLight & lightData = SceneNode->getLightData(); AllColorsControl->updateMaterialColors(lightData); }
protected: bool Initialized; scene::ILightSceneNode* SceneNode; CAllColorsControl* AllColorsControl; };
|
|
| |
MerGC_Team | Дата: Четверг, 03.04.2014, 18:37 | Сообщение # 3 |
Веселый админ
Группа: Администраторы
Сообщений: 32
Статус: Оффлайн
| Конфигурация приложения Код struct SConfig { SConfig() : RenderInBackground(true) , DriverType(video::EDT_BURNINGSVIDEO) , ScreenSize(640, 480) { }
bool RenderInBackground; video::E_DRIVER_TYPE DriverType; core::dimension2d ScreenSize; };
Главный класс приложения Код class CApp : public IEventReceiver { friend int main(int argc, char *argv[]);
public: // конструктор CApp() : IsRunning(false) , Device(0) , Camera(0) , GlobalAmbient(0) { }
// деструктор ~CApp() { }
// прекращение выполнения - выход в конце главного цикла void stopApp() { IsRunning = false; }
// обработчик событий virtual bool OnEvent(const SEvent &event) { if (event.EventType == EET_GUI_EVENT) { gui::IGUIEnvironment* env = Device->getGUIEnvironment();
switch(event.GUIEvent.EventType) { case gui::EGET_MENU_ITEM_SELECTED: { gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)event.GUIEvent.Caller; s32 id = menu->getItemCommandId(menu->getSelectedItem());
switch(id) { case GUI_ID_OPEN_TEXTURE: // меню File -> Open Texture env->addFileOpenDialog(L"Please select a texture file to open"); break; case GUI_ID_QUIT: // меню File -> Quit stopApp(); break; } } break;
case gui::EGET_FILE_SELECTED: { // загрузка модели, выбранной из файлового диалога gui::IGUIFileOpenDialog* dialog = (gui::IGUIFileOpenDialog*)event.GUIEvent.Caller; loadTexture(io::path(dialog->getFileName()).c_str()); } break;
default: break; } }
return false; }
protected:
// инициализация приложения // возвращает true, если все нормально, иначе false. bool init(int argc, char *argv[]) { // запрашиваем видеодрайвер Config.DriverType=driverChoiceConsole(); if (Config.DriverType==video::EDT_COUNT) return false;
// создаем движок со значениями из конфига Device = createDevice(Config.DriverType, Config.ScreenSize); if (!Device) return false; Device->setWindowCaption( DriverTypeNames[Config.DriverType] ); Device->setEventReceiver(this); scene::ISceneManager* smgr = Device->getSceneManager(); video::IVideoDriver * driver = Device->getVideoDriver (); gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
// устанавливаем шрифт gui::IGUISkin* skin = guiEnv->getSkin(); gui::IGUIFont* font = guiEnv->getFont("../../media/fonthaettenschweiler.bmp"); if (font) skin->setFont(font); // убираем прозрачность выделенных элементов, для лучшей их видимости video::SColor col3dHighLight( skin->getColor(gui::EGDC_APP_WORKSPACE) ); col3dHighLight.setAlpha(255); video::SColor colHighLight( col3dHighLight ); skin->setColor(gui::EGDC_HIGH_LIGHT, colHighLight ); skin->setColor(gui::EGDC_3D_HIGH_LIGHT, col3dHighLight );
// создаем несколько текстур для тестирования настроек материала createDefaultTextures(driver);
// создаем меню gui::IGUIContextMenu * menuBar = guiEnv->addMenu(); menuBar->addItem(L"File", -1, true, true);
gui::IGUIContextMenu* subMenuFile = menuBar->getSubMenu(0); subMenuFile->addItem(L"Open texture ...", GUI_ID_OPEN_TEXTURE); subMenuFile->addSeparator(); subMenuFile->addItem(L"Quit", GUI_ID_QUIT);
// статическая камера Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 0, 0), core::vector3df(0, 0, 100), -1);
// создаем узлы(ноды) для демонстрации наших материалов scene::IMeshSceneNode* nodeL = smgr->addCubeSceneNode (30.0f, 0, -1, core::vector3df(-35, 0, 100), core::vector3df(0, 0, 0), core::vector3df(1.0f, 1.0f, 1.0f)); NodeLeft.init( nodeL, Device, core::position2d(10,20), L"left node" );
scene::IMeshSceneNode* nodeR = smgr->addCubeSceneNode (30.0f, 0, -1, core::vector3df(35, 0, 100), core::vector3df(0, 0, 0), core::vector3df(1.0f, 1.0f, 1.0f)); NodeRight.init( nodeR, Device, core::position2d(530,20), L"right node" );
// добавляем освещение scene::ILightSceneNode* nodeLight = smgr->addLightSceneNode(0, core::vector3df(0, 0, 0), video::SColorf(1.0f, 1.0f, 1.0f), 100.0f); LightControl.init(nodeLight, guiEnv, core::position2d(270,20), L"light" ); // один большой куб вокруг всего для того, чтобы сделать освещение более ясным scene::IMeshSceneNode* backgroundCube = smgr->addCubeSceneNode (200.0f, 0, -1, core::vector3df(0, 0, 0), core::vector3df(45, 0, 0), core::vector3df(1.0f, 1.0f, 1.0f)); backgroundCube->getMaterial(0).BackfaceCulling = false; // отключаем отрисовку внешних стенок, мы ведь внутри backgroundCube->getMaterial(0).EmissiveColor.set(255,50,50,50); // we keep some self lighting to keep texts visible
// устанавливаем значение для окружающего освещения GlobalAmbient = new CColorControl( guiEnv, core::position2d< s32 >(270, 300), L"global ambient", guiEnv->getRootGUIElement()); GlobalAmbient->setColor( smgr->getAmbientLight().toSColor() );
return true; }
// обработка на каждом фрейме bool update() { using namespace irr;
video::IVideoDriver* videoDriver = Device->getVideoDriver(); if ( !Device->run() ) return false;
if ( Device->isWindowActive() || Config.RenderInBackground ) { gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment(); scene::ISceneManager* smgr = Device->getSceneManager(); gui::IGUISkin * skin = guiEnv->getSkin();
// обновляем наши контроллеры (узлы демонстрирующие материалы и освещение) NodeLeft.update(); NodeRight.update(); LightControl.update();
// обновляем окружающее освещение if ( GlobalAmbient->isDirty() ) { smgr->setAmbientLight( GlobalAmbient->getColor() ); GlobalAmbient->resetDirty(); }
// отрисовка сцены video::SColor bkColor( skin->getColor(gui::EGDC_APP_WORKSPACE) ); videoDriver->beginScene(true, true, bkColor);
smgr->drawAll(); guiEnv->drawAll();
videoDriver->endScene(); }
return true; }
// запуск главного цикла приложения void run() { IsRunning = true;
if ( !Device ) return;
// главный цикл while(IsRunning) { if ( !update() ) break;
Device->sleep( 5 ); } }
// завершение приложения void quit() { IsRunning = false; GlobalAmbient->drop(); GlobalAmbient = NULL; if ( Device ) { Device->closeDevice(); Device->drop(); Device = NULL; } }
// Создание набора полезных текстур // Заметка: НЕ ИСПОЛЬЗУЙТЕ setPixel() во время исполнения из-за медленности, старайтесь во время инициализации void createDefaultTextures(video::IVideoDriver * driver) { const u32 width = 256; const u32 height = 256; video::IImage * imageA8R8G8B8 = driver->createImage (video::ECF_A8R8G8B8, core::dimension2d(width, height)); if ( !imageA8R8G8B8 ) return; const u32 pitch = imageA8R8G8B8->getPitch();
// шахматка 3х3 из 9ти цветов for ( u32 y = 0; y < height; ++ y ) { for ( u32 x = 0; x < pitch; ++x ) { if ( y < height/3 ) { if ( x < width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_BLACK); else if ( x < 2*width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_BLUE); else imageA8R8G8B8->setPixel (x, y, SCOL_CYAN); } else if ( y < 2*height/3 ) { if ( x < width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_GRAY); else if ( x < 2*width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_GREEN); else imageA8R8G8B8->setPixel (x, y, SCOL_MAGENTA); } else { if ( x < width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_RED); else if ( x < 2*width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_YELLOW); else imageA8R8G8B8->setPixel (x, y, SCOL_WHITE); } } } driver->addTexture (io::path("CARO_A8R8G8B8"), imageA8R8G8B8);
// все белое imageA8R8G8B8->fill(SCOL_WHITE); driver->addTexture (io::path("WHITE_A8R8G8B8"), imageA8R8G8B8);
// все черное imageA8R8G8B8->fill(SCOL_BLACK); driver->addTexture (io::path("BLACK_A8R8G8B8"), imageA8R8G8B8);
// в градациях серого for ( u32 y = 0; y < height; ++ y ) { for ( u32 x = 0; x < pitch; ++x ) { imageA8R8G8B8->setPixel (x, y, video::SColor(y, x,x,x) ); } } driver->addTexture (io::path("GRAYSCALE_A8R8G8B8"), imageA8R8G8B8); }
// загрузка текстуры и применение их к демонстрационным узлам(нодам). void loadTexture(const io::path &name) { Device->getVideoDriver()->getTexture(name); NodeLeft.updateTextures(); NodeRight.updateTextures(); }
private: SConfig Config; volatile boolIsRunning; IrrlichtDevice *Device; scene::ICameraSceneNode * Camera; SMeshNodeControlNodeLeft; SMeshNodeControlNodeRight; SLightNodeControl LightControl; CColorControl * GlobalAmbient; };
Очень маленькая ф-ция main(), так как мы делаем всё остальное в классах.. Код int main(int argc, char *argv[]) { CApp APP;
if ( !APP.init(argc, argv) ) { printf("init failedn"); return 1; }
APP.run(); APP.quit();
return 0; }
|
|
| |