[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Игровые движки » IrrLicht Engine » Туториал №22: Просмотрщик материалов
Туториал №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;
}
 
Форум » Игровые движки » IrrLicht Engine » Туториал №22: Просмотрщик материалов
  • Страница 1 из 1
  • 1
Поиск: