main.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  1. /** Example 022 Material Viewer
  2. This example can be used to experiment with material settings and watch the results.
  3. Only the default non-shader materials are used in here.
  4. You have a node with a mesh, one dynamic light and global ambient light to play around with.
  5. You can move the light with cursor-keys and +/-.
  6. You can move the camera while left-mouse button is clicked.
  7. */
  8. // TODO: Should be possible to set all material values by the GUI.
  9. // For now just change the defaultMaterial in CApp::setActiveMeshNodeType for the rest.
  10. #include <irrlicht.h>
  11. #include "driverChoice.h"
  12. #include "exampleHelper.h"
  13. #include "main.h"
  14. using namespace irr;
  15. #ifdef _MSC_VER
  16. #pragma comment(lib, "Irrlicht.lib")
  17. #endif
  18. /*
  19. Variables within the empty namespace are globals which are restricted to this file.
  20. */
  21. namespace
  22. {
  23. // For the gui id's
  24. enum EGUI_IDS
  25. {
  26. GUI_ID_OPEN_TEXTURE = 1,
  27. GUI_ID_QUIT,
  28. GUI_ID_MAX
  29. };
  30. // Name used in texture selection to clear the textures on the node
  31. const core::stringw CLEAR_TEXTURE = L"CLEAR texture";
  32. // some useful color constants
  33. const video::SColor SCOL_BLACK = video::SColor(255, 0, 0, 0);
  34. const video::SColor SCOL_BLUE = video::SColor(255, 0, 0, 255);
  35. const video::SColor SCOL_CYAN = video::SColor(255, 0, 255, 255);
  36. const video::SColor SCOL_GRAY = video::SColor(255, 128,128, 128);
  37. const video::SColor SCOL_GREEN = video::SColor(255, 0, 255, 0);
  38. const video::SColor SCOL_MAGENTA = video::SColor(255, 255, 0, 255);
  39. const video::SColor SCOL_RED = video::SColor(255, 255, 0, 0);
  40. const video::SColor SCOL_YELLOW = video::SColor(255, 255, 255, 0);
  41. const video::SColor SCOL_WHITE = video::SColor(255, 255, 255, 255);
  42. }; // namespace
  43. /*
  44. Returns a new unique number on each call.
  45. */
  46. s32 makeUniqueId()
  47. {
  48. static int unique = GUI_ID_MAX;
  49. ++unique;
  50. return unique;
  51. }
  52. /*
  53. Find out which vertex-type is needed for the given material type.
  54. */
  55. video::E_VERTEX_TYPE getVertexTypeForMaterialType(video::E_MATERIAL_TYPE materialType)
  56. {
  57. using namespace video;
  58. switch ( materialType )
  59. {
  60. case EMT_SOLID:
  61. return EVT_STANDARD;
  62. case EMT_SOLID_2_LAYER:
  63. return EVT_STANDARD;
  64. case EMT_LIGHTMAP:
  65. case EMT_LIGHTMAP_ADD:
  66. case EMT_LIGHTMAP_M2:
  67. case EMT_LIGHTMAP_M4:
  68. case EMT_LIGHTMAP_LIGHTING:
  69. case EMT_LIGHTMAP_LIGHTING_M2:
  70. case EMT_LIGHTMAP_LIGHTING_M4:
  71. return EVT_2TCOORDS;
  72. case EMT_DETAIL_MAP:
  73. return EVT_2TCOORDS;
  74. case EMT_SPHERE_MAP:
  75. return EVT_STANDARD;
  76. case EMT_REFLECTION_2_LAYER:
  77. return EVT_2TCOORDS;
  78. case EMT_TRANSPARENT_ADD_COLOR:
  79. return EVT_STANDARD;
  80. case EMT_TRANSPARENT_ALPHA_CHANNEL:
  81. return EVT_STANDARD;
  82. case EMT_TRANSPARENT_ALPHA_CHANNEL_REF:
  83. return EVT_STANDARD;
  84. case EMT_TRANSPARENT_VERTEX_ALPHA:
  85. return EVT_STANDARD;
  86. case EMT_TRANSPARENT_REFLECTION_2_LAYER:
  87. return EVT_2TCOORDS;
  88. case EMT_NORMAL_MAP_SOLID:
  89. case EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR:
  90. case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA:
  91. case EMT_PARALLAX_MAP_SOLID:
  92. case EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR:
  93. case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA:
  94. return EVT_TANGENTS;
  95. case EMT_ONETEXTURE_BLEND:
  96. return EVT_STANDARD;
  97. case EMT_FORCE_32BIT:
  98. return EVT_STANDARD;
  99. }
  100. return EVT_STANDARD;
  101. }
  102. /*
  103. Custom GUI-control to edit color values.
  104. */
  105. CColorControl::CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, IGUIElement* parent, s32 id)
  106. : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos, pos+core::dimension2d<s32>(80, 75)))
  107. , DirtyFlag(true)
  108. , Color(0)
  109. , ColorStatic(0)
  110. , EditAlpha(0)
  111. , EditRed(0)
  112. , EditGreen(0)
  113. , EditBlue(0)
  114. {
  115. using namespace gui;
  116. ButtonSetId = makeUniqueId();
  117. const core::rect< s32 > rectControls(0,0,AbsoluteRect.getWidth(),AbsoluteRect.getHeight() );
  118. IGUIStaticText * groupElement = guiEnv->addStaticText (L"", rectControls, true, false, this, -1, false);
  119. groupElement->setNotClipped(true);
  120. s32 border=guiEnv->getSkin()->getSize(EGDS_TEXT_DISTANCE_X);
  121. guiEnv->addStaticText(text, core::rect<s32>(border,border,80,15), false, false, groupElement, -1, true);
  122. EditAlpha = addEditForNumbers(guiEnv, core::position2d<s32>(border,15), L"a", -1, groupElement );
  123. EditRed = addEditForNumbers(guiEnv, core::position2d<s32>(border,30), L"r", -1, groupElement );
  124. EditGreen = addEditForNumbers(guiEnv, core::position2d<s32>(border,45), L"g", -1, groupElement );
  125. EditBlue = addEditForNumbers(guiEnv, core::position2d<s32>(border,60), L"b", -1, groupElement );
  126. ColorStatic = guiEnv->addStaticText (L"", core::rect<s32>(60,15,80,75), true, false, groupElement, -1, true);
  127. guiEnv->addButton (core::rect<s32>(60,35,80,50), groupElement, ButtonSetId, L"set");
  128. setEditsFromColor(Color);
  129. }
  130. // event receiver
  131. bool CColorControl::OnEvent(const SEvent &event)
  132. {
  133. if ( event.EventType == EET_GUI_EVENT
  134. && event.GUIEvent.Caller->getID() == ButtonSetId
  135. && event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
  136. {
  137. Color = getColorFromEdits();
  138. setEditsFromColor(Color);
  139. }
  140. return false;
  141. }
  142. // set the color values
  143. void CColorControl::setColor(const video::SColor& col)
  144. {
  145. DirtyFlag = true;
  146. Color = col;
  147. setEditsFromColor(Color);
  148. }
  149. // Add a statictext for a description + an editbox so users can enter numbers
  150. gui::IGUIEditBox* CColorControl::addEditForNumbers(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, s32 id, gui::IGUIElement * parent)
  151. {
  152. using namespace gui;
  153. core::recti rect(pos, pos+core::dimension2d<s32>(10, 15));
  154. guiEnv->addStaticText(text, rect, false, false, parent, -1, false);
  155. rect += core::position2d<s32>( 20, 0 );
  156. rect.LowerRightCorner.X += 20;
  157. gui::IGUIEditBox* edit = guiEnv->addEditBox(L"0", rect, true, parent, id);
  158. return edit;
  159. }
  160. // Get the color value from the editboxes
  161. video::SColor CColorControl::getColorFromEdits() const
  162. {
  163. video::SColor col;
  164. if (EditAlpha)
  165. {
  166. u32 alpha = core::min_(core::strtoul10(core::stringc(EditAlpha->getText()).c_str()), 255u);
  167. col.setAlpha(alpha);
  168. }
  169. if (EditRed)
  170. {
  171. u32 red = core::min_(core::strtoul10(core::stringc(EditRed->getText()).c_str()), 255u);
  172. col.setRed(red);
  173. }
  174. if (EditGreen)
  175. {
  176. u32 green = core::min_(core::strtoul10(core::stringc(EditGreen->getText()).c_str()), 255u);
  177. col.setGreen(green);
  178. }
  179. if (EditBlue)
  180. {
  181. u32 blue = core::min_(core::strtoul10(core::stringc(EditBlue->getText()).c_str()), 255u);
  182. col.setBlue(blue);
  183. }
  184. return col;
  185. }
  186. // Fill the editboxes with a color value
  187. void CColorControl::setEditsFromColor(video::SColor col)
  188. {
  189. DirtyFlag = true;
  190. if ( EditAlpha )
  191. EditAlpha->setText( core::stringw(col.getAlpha()).c_str() );
  192. if ( EditRed )
  193. EditRed->setText( core::stringw(col.getRed()).c_str() );
  194. if ( EditGreen )
  195. EditGreen->setText( core::stringw(col.getGreen()).c_str() );
  196. if ( EditBlue )
  197. EditBlue->setText( core::stringw(col.getBlue()).c_str() );
  198. if ( ColorStatic )
  199. ColorStatic->setBackgroundColor(col);
  200. }
  201. /*
  202. Custom GUI-control for to edit all colors typically used in materials and lights
  203. */
  204. // Constructor
  205. CTypicalColorsControl::CTypicalColorsControl(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, bool hasEmissive, IGUIElement* parent, s32 id)
  206. : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect<s32>(pos,pos+core::dimension2d<s32>(60,250)))
  207. , ControlAmbientColor(0), ControlDiffuseColor(0), ControlSpecularColor(0), ControlEmissiveColor(0)
  208. {
  209. ControlAmbientColor = new CColorControl( guiEnv, core::position2d<s32>(0, 0), L"Ambient", this);
  210. ControlDiffuseColor = new CColorControl( guiEnv, core::position2d<s32>(0, 75), L"Diffuse", this );
  211. ControlSpecularColor = new CColorControl( guiEnv, core::position2d<s32>(0, 150), L"Specular", this );
  212. if ( hasEmissive )
  213. {
  214. ControlEmissiveColor = new CColorControl( guiEnv, core::position2d<s32>(0, 225), L"Emissive", this );
  215. }
  216. }
  217. // Destructor
  218. CTypicalColorsControl::~CTypicalColorsControl()
  219. {
  220. ControlAmbientColor->drop();
  221. ControlDiffuseColor->drop();
  222. if ( ControlEmissiveColor )
  223. ControlEmissiveColor->drop();
  224. ControlSpecularColor->drop();
  225. }
  226. // Set the color values to those within the material
  227. void CTypicalColorsControl::setColorsToMaterialColors(const video::SMaterial & material)
  228. {
  229. ControlAmbientColor->setColor(material.AmbientColor);
  230. ControlDiffuseColor->setColor(material.DiffuseColor);
  231. ControlEmissiveColor->setColor(material.EmissiveColor);
  232. ControlSpecularColor->setColor(material.SpecularColor);
  233. }
  234. // Update all changed colors in the material
  235. void CTypicalColorsControl::updateMaterialColors(video::SMaterial & material) const
  236. {
  237. if ( ControlAmbientColor->isDirty() )
  238. material.AmbientColor = ControlAmbientColor->getColor();
  239. if ( ControlDiffuseColor->isDirty() )
  240. material.DiffuseColor = ControlDiffuseColor->getColor();
  241. if ( ControlEmissiveColor->isDirty() )
  242. material.EmissiveColor = ControlEmissiveColor->getColor();
  243. if ( ControlSpecularColor->isDirty() )
  244. material.SpecularColor = ControlSpecularColor->getColor();
  245. }
  246. // Set the color values to those from the light data
  247. void CTypicalColorsControl::setColorsToLightDataColors(const video::SLight & lightData)
  248. {
  249. ControlAmbientColor->setColor(lightData.AmbientColor.toSColor());
  250. ControlDiffuseColor->setColor(lightData.DiffuseColor.toSColor());
  251. ControlSpecularColor->setColor(lightData.SpecularColor.toSColor());
  252. }
  253. // Update all changed colors in the light data
  254. void CTypicalColorsControl::updateLightColors(video::SLight & lightData) const
  255. {
  256. if ( ControlAmbientColor->isDirty() )
  257. lightData.AmbientColor = video::SColorf( ControlAmbientColor->getColor() );
  258. if ( ControlDiffuseColor->isDirty() )
  259. lightData.DiffuseColor = video::SColorf( ControlDiffuseColor->getColor() );
  260. if ( ControlSpecularColor->isDirty() )
  261. lightData.SpecularColor = video::SColorf(ControlSpecularColor->getColor() );
  262. }
  263. // To reset the dirty flags
  264. void CTypicalColorsControl::resetDirty()
  265. {
  266. ControlAmbientColor->resetDirty();
  267. ControlDiffuseColor->resetDirty();
  268. ControlSpecularColor->resetDirty();
  269. if ( ControlEmissiveColor )
  270. ControlEmissiveColor->resetDirty();
  271. }
  272. /*
  273. GUI-Control to offer a selection of available textures.
  274. */
  275. CTextureControl::CTextureControl(gui::IGUIEnvironment* guiEnv, video::IVideoDriver * driver, const core::position2d<s32> & pos, IGUIElement* parent, s32 id)
  276. : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect<s32>(pos,pos+core::dimension2d<s32>(150,15)))
  277. , DirtyFlag(true), ComboTexture(0)
  278. {
  279. core::rect<s32> rectCombo(0, 0, AbsoluteRect.getWidth(),AbsoluteRect.getHeight());
  280. ComboTexture = guiEnv->addComboBox (rectCombo, this);
  281. updateTextures(driver);
  282. }
  283. bool CTextureControl::OnEvent(const SEvent &event)
  284. {
  285. if ( event.EventType == EET_GUI_EVENT
  286. && event.GUIEvent.Caller == ComboTexture
  287. && event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED )
  288. {
  289. DirtyFlag = true;
  290. }
  291. return false;
  292. }
  293. // Workaround for a problem with comboboxes.
  294. // We have to get in front when the combobox wants to get in front or combobox-list might be drawn below other elements.
  295. bool CTextureControl::bringToFront(IGUIElement* element)
  296. {
  297. bool result = gui::IGUIElement::bringToFront(element);
  298. if ( Parent && element == ComboTexture )
  299. result &= Parent->bringToFront(this);
  300. return result;
  301. }
  302. // return selected texturename (if any, otherwise 0)
  303. const wchar_t * CTextureControl::getSelectedTextureName() const
  304. {
  305. s32 selected = ComboTexture->getSelected();
  306. if ( selected < 0 )
  307. return 0;
  308. return ComboTexture->getItem(selected);
  309. }
  310. void CTextureControl::selectTextureByName(const irr::core::stringw& name)
  311. {
  312. for (u32 i=0; i< ComboTexture->getItemCount(); ++i)
  313. {
  314. if ( name == ComboTexture->getItem(i))
  315. {
  316. ComboTexture->setSelected(i);
  317. DirtyFlag = true;
  318. return;
  319. }
  320. }
  321. }
  322. // Put the names of all currently loaded textures in a combobox
  323. void CTextureControl::updateTextures(video::IVideoDriver * driver)
  324. {
  325. s32 oldSelected = ComboTexture->getSelected();
  326. core::stringw oldTextureName;
  327. if ( oldSelected >= 0 )
  328. {
  329. oldTextureName = ComboTexture->getItem(oldSelected);
  330. }
  331. ComboTexture->clear();
  332. s32 selectNew = -1;
  333. for ( u32 i=0; i < driver->getTextureCount(); ++i )
  334. {
  335. video::ITexture * texture = driver->getTextureByIndex(i);
  336. core::stringw name( texture->getName() );
  337. ComboTexture->addItem( name.c_str() );
  338. if ( !oldTextureName.empty() && selectNew < 0 && name == oldTextureName )
  339. selectNew = i;
  340. }
  341. // add another name which can be used to clear the texture
  342. ComboTexture->addItem( CLEAR_TEXTURE.c_str() );
  343. if ( CLEAR_TEXTURE == oldTextureName )
  344. selectNew = ComboTexture->getItemCount()-1;
  345. if ( selectNew >= 0 )
  346. ComboTexture->setSelected(selectNew);
  347. DirtyFlag = true;
  348. }
  349. /*
  350. Control which allows setting some of the material values for a meshscenenode
  351. */
  352. void CMaterialControl::init(IrrlichtDevice * device, const core::position2d<s32> & pos, const wchar_t * description)
  353. {
  354. if ( Initialized || !device) // initializing twice or with invalid data not allowed
  355. return;
  356. Driver = device->getVideoDriver ();
  357. gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment();
  358. s32 top = pos.Y;
  359. // Description
  360. guiEnv->addStaticText(description, core::rect<s32>(pos.X, top, pos.X+150, top+15), true, false, 0, -1, true);
  361. top += 15;
  362. // Control for material type
  363. core::rect<s32> rectCombo(pos.X, top, pos.X+150, top+15);
  364. top += 15;
  365. ComboMaterial = guiEnv->addComboBox (rectCombo);
  366. for ( int i=0; i <= (int)video::EMT_ONETEXTURE_BLEND; ++i )
  367. {
  368. ComboMaterial->addItem( core::stringw(video::sBuiltInMaterialTypeNames[i]).c_str() );
  369. }
  370. ComboMaterial->setSelected(0);
  371. // Control to enable/disabling material lighting
  372. core::rect<s32> rectBtn(core::position2d<s32>(pos.X, top), core::dimension2d<s32>(100, 15));
  373. top += 15;
  374. ButtonLighting = guiEnv->addButton (rectBtn, 0, -1, L"Lighting");
  375. ButtonLighting->setIsPushButton(true);
  376. core::rect<s32> rectInfo( rectBtn.LowerRightCorner.X, rectBtn.UpperLeftCorner.Y, rectBtn.LowerRightCorner.X+50, rectBtn.UpperLeftCorner.Y+15 );
  377. InfoLighting = guiEnv->addStaticText(L"", rectInfo, true, false );
  378. InfoLighting->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER );
  379. // Controls for colors
  380. TypicalColorsControl = new CTypicalColorsControl(guiEnv, core::position2d<s32>(pos.X, top), true, guiEnv->getRootGUIElement());
  381. top += 300;
  382. guiEnv->addStaticText(L"Shininess", core::rect<s32>(pos.X, top, pos.X + 150, top + 15), true, false, 0, -1, true);
  383. top += 15;
  384. ShininessControl = guiEnv->addScrollBar(true, core::rect<s32>(pos.X, top, pos.X + 150, top + 15));
  385. ShininessControl->setMax(10000);
  386. top += 20;
  387. // Controls for selecting the material textures
  388. guiEnv->addStaticText(L"Textures", core::rect<s32>(pos.X, top, pos.X+150, top+15), true, false, 0, -1, true);
  389. top += 15;
  390. // The default material types only use first 2 textures
  391. irr::u32 maxTextures = core::min_(2u, irr::video::MATERIAL_MAX_TEXTURES);
  392. for (irr::u32 i=0; i<maxTextures; ++i)
  393. {
  394. TextureControls.push_back(new CTextureControl(guiEnv, Driver, core::position2di(pos.X, top), guiEnv->getRootGUIElement()));
  395. top += 15;
  396. }
  397. Initialized = true;
  398. }
  399. void CMaterialControl::setMaterial(const irr::video::SMaterial & material)
  400. {
  401. if (ComboMaterial)
  402. ComboMaterial->setSelected( (s32)material.MaterialType );
  403. if (ButtonLighting)
  404. ButtonLighting->setPressed(material.Lighting);
  405. if (TypicalColorsControl)
  406. TypicalColorsControl->setColorsToMaterialColors(material);
  407. for (irr::u32 i=0; i<TextureControls.size(); ++i)
  408. TextureControls[i]->setDirty();
  409. if (ShininessControl)
  410. ShininessControl->setPos((int)(material.Shininess*100.f));
  411. }
  412. void CMaterialControl::update(scene::IMeshSceneNode* sceneNode, scene::IMeshSceneNode* sceneNode2T, scene::IMeshSceneNode* sceneNodeTangents)
  413. {
  414. if ( !Initialized )
  415. return;
  416. video::SMaterial & material = sceneNode->getMaterial(0);
  417. video::SMaterial & material2T = sceneNode2T->getMaterial(0);
  418. video::SMaterial & materialTangents = sceneNodeTangents->getMaterial(0);
  419. s32 selectedMaterial = ComboMaterial->getSelected();
  420. if ( selectedMaterial >= (s32)video::EMT_SOLID && selectedMaterial <= (s32)video::EMT_ONETEXTURE_BLEND)
  421. {
  422. // Show the node which has a mesh to work with the currently selected material
  423. video::E_VERTEX_TYPE vertexType = getVertexTypeForMaterialType((video::E_MATERIAL_TYPE)selectedMaterial);
  424. switch ( vertexType )
  425. {
  426. case video::EVT_STANDARD:
  427. material.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial;
  428. sceneNode->setVisible(true);
  429. sceneNode2T->setVisible(false);
  430. sceneNodeTangents->setVisible(false);
  431. break;
  432. case video::EVT_2TCOORDS:
  433. material2T.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial;
  434. sceneNode->setVisible(false);
  435. sceneNode2T->setVisible(true);
  436. sceneNodeTangents->setVisible(false);
  437. break;
  438. case video::EVT_TANGENTS:
  439. materialTangents.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial;
  440. sceneNode->setVisible(false);
  441. sceneNode2T->setVisible(false);
  442. sceneNodeTangents->setVisible(true);
  443. break;
  444. }
  445. }
  446. // Always update materials of all nodes, otherwise the tool is confusing to use.
  447. updateMaterial(material);
  448. updateMaterial(material2T);
  449. updateMaterial(materialTangents);
  450. if ( ButtonLighting->isPressed() )
  451. InfoLighting->setText(L"is on");
  452. else
  453. InfoLighting->setText(L"is off");
  454. TypicalColorsControl->resetDirty();
  455. for (irr::u32 i=0; i<TextureControls.size(); ++i)
  456. TextureControls[i]->resetDirty();
  457. }
  458. void CMaterialControl::updateTextures()
  459. {
  460. for (irr::u32 i=0; i<TextureControls.size(); ++i)
  461. TextureControls[i]->updateTextures(Driver);
  462. }
  463. void CMaterialControl::selectTextures(const irr::core::stringw& name)
  464. {
  465. for (irr::u32 i=0; i<TextureControls.size(); ++i)
  466. TextureControls[i]->selectTextureByName(name);
  467. }
  468. bool CMaterialControl::isLightingEnabled() const
  469. {
  470. return ButtonLighting && ButtonLighting->isPressed();
  471. }
  472. void CMaterialControl::updateMaterial(video::SMaterial & material)
  473. {
  474. TypicalColorsControl->updateMaterialColors(material);
  475. material.Lighting = ButtonLighting->isPressed();
  476. for (irr::u32 i=0; i<TextureControls.size(); ++i)
  477. {
  478. if ( TextureControls[i]->isDirty() )
  479. {
  480. material.TextureLayer[i].Texture = Driver->findTexture( io::path(TextureControls[i]->getSelectedTextureName()) );
  481. }
  482. }
  483. material.Shininess = ShininessControl->getPos() * 0.01f;
  484. }
  485. /*
  486. Control to allow setting the color values of a lightscenenode.
  487. */
  488. void CLightNodeControl::init(scene::ILightSceneNode* node, gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t * description)
  489. {
  490. if ( Initialized || !node || !guiEnv) // initializing twice or with invalid data not allowed
  491. return;
  492. gui::IGUIStaticText* st = guiEnv->addStaticText(description, core::rect<s32>(pos.X, pos.Y, pos.X+80, pos.Y+15), true, false, 0, -1, true);
  493. st->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
  494. TypicalColorsControl = new CTypicalColorsControl(guiEnv, core::position2d<s32>(pos.X, pos.Y+15), false, guiEnv->getRootGUIElement());
  495. TypicalColorsControl->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
  496. const video::SLight & lightData = node->getLightData();
  497. TypicalColorsControl->setColorsToLightDataColors(lightData);
  498. Initialized = true;
  499. }
  500. void CLightNodeControl::update(scene::ILightSceneNode* node)
  501. {
  502. if ( !Initialized )
  503. return;
  504. video::SLight & lightData = node->getLightData();
  505. TypicalColorsControl->updateLightColors(lightData);
  506. }
  507. /*
  508. Main application class
  509. */
  510. // Event handler
  511. bool CApp::OnEvent(const SEvent &event)
  512. {
  513. if (event.EventType == EET_GUI_EVENT)
  514. {
  515. gui::IGUIEnvironment* env = Device->getGUIEnvironment();
  516. switch(event.GUIEvent.EventType)
  517. {
  518. case gui::EGET_MENU_ITEM_SELECTED:
  519. {
  520. gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)event.GUIEvent.Caller;
  521. s32 id = menu->getItemCommandId(menu->getSelectedItem());
  522. switch(id)
  523. {
  524. case GUI_ID_OPEN_TEXTURE: // File -> Open Texture
  525. env->addFileOpenDialog(L"Please select a texture file to open");
  526. break;
  527. case GUI_ID_QUIT: // File -> Quit
  528. setRunning(false);
  529. break;
  530. }
  531. }
  532. break;
  533. case gui::EGET_FILE_SELECTED:
  534. {
  535. // load the texture file, selected in the file open dialog
  536. gui::IGUIFileOpenDialog* dialog =
  537. (gui::IGUIFileOpenDialog*)event.GUIEvent.Caller;
  538. loadTexture(io::path(dialog->getFileName()).c_str());
  539. }
  540. break;
  541. case gui::EGET_COMBO_BOX_CHANGED:
  542. if (event.GUIEvent.Caller == ComboMeshType )
  543. {
  544. irr::scene::IMeshSceneNode* currentNode = getVisibleMeshNode();
  545. if (currentNode)
  546. {
  547. // ensure next mesh will get same color and material settings
  548. if ( ControlVertexColors )
  549. {
  550. video::S3DVertex * vertices = (video::S3DVertex *)currentNode->getMesh()->getMeshBuffer(0)->getVertices();
  551. ControlVertexColors->setColor(vertices[0].Color);
  552. }
  553. if ( MeshMaterialControl )
  554. MeshMaterialControl->setMaterial(currentNode->getMaterial(0));
  555. }
  556. setActiveMeshNodeType((ENodeType)ComboMeshType->getSelected());
  557. return true;
  558. }
  559. break;
  560. default:
  561. break;
  562. }
  563. }
  564. else if (event.EventType == EET_KEY_INPUT_EVENT)
  565. {
  566. KeysPressed[event.KeyInput.Key] = event.KeyInput.PressedDown;
  567. }
  568. else if (event.EventType == EET_MOUSE_INPUT_EVENT)
  569. {
  570. if (!MousePressed && event.MouseInput.isLeftPressed())
  571. {
  572. gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
  573. if ( guiEnv->getHovered() == guiEnv->getRootGUIElement() ) // Click on background
  574. {
  575. MousePressed = true;
  576. MouseStart.X = event.MouseInput.X;
  577. MouseStart.Y = event.MouseInput.Y;
  578. }
  579. }
  580. else if (MousePressed && !event.MouseInput.isLeftPressed())
  581. {
  582. MousePressed = false;
  583. }
  584. }
  585. return false;
  586. }
  587. // Application initialization
  588. // returns true when it was successful initialized, otherwise false.
  589. bool CApp::init(int argc, char *argv[])
  590. {
  591. // ask user for driver
  592. Config.DriverType=driverChoiceConsole();
  593. if (Config.DriverType==video::EDT_COUNT)
  594. return false;
  595. // create the device with the settings from our config
  596. Device = createDevice(Config.DriverType, Config.ScreenSize);
  597. if (!Device)
  598. return false;
  599. Device->setWindowCaption( core::stringw(video::DRIVER_TYPE_NAMES[Config.DriverType]).c_str() );
  600. Device->setEventReceiver(this);
  601. scene::ISceneManager* smgr = Device->getSceneManager();
  602. video::IVideoDriver * driver = Device->getVideoDriver ();
  603. gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
  604. MeshManipulator = smgr->getMeshManipulator();
  605. // set a nicer font
  606. gui::IGUISkin* skin = guiEnv->getSkin();
  607. gui::IGUIFont* font = guiEnv->getFont(getExampleMediaPath() + "fonthaettenschweiler.bmp");
  608. if (font)
  609. skin->setFont(font);
  610. // remove some alpha value because it makes those menus harder to read otherwise
  611. video::SColor col3dHighLight( skin->getColor(gui::EGDC_APP_WORKSPACE) );
  612. col3dHighLight.setAlpha(255);
  613. video::SColor colHighLight( col3dHighLight );
  614. skin->setColor(gui::EGDC_HIGH_LIGHT, colHighLight );
  615. skin->setColor(gui::EGDC_3D_HIGH_LIGHT, col3dHighLight );
  616. // Add some textures which are useful to test material settings
  617. createDefaultTextures(driver);
  618. // create a menu
  619. gui::IGUIContextMenu * menuBar = guiEnv->addMenu();
  620. menuBar->addItem(L"File", -1, true, true);
  621. gui::IGUIContextMenu* subMenuFile = menuBar->getSubMenu(0);
  622. subMenuFile->addItem(L"Open texture ...", GUI_ID_OPEN_TEXTURE);
  623. subMenuFile->addSeparator();
  624. subMenuFile->addItem(L"Quit", GUI_ID_QUIT);
  625. // a static camera
  626. Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 30, -50),
  627. core::vector3df(0, 0, 0),
  628. -1);
  629. setActiveMeshNodeType(ENT_CUBE);
  630. const s32 controlsTop = 20;
  631. MeshMaterialControl = new CMaterialControl();
  632. MeshMaterialControl->init( Device, core::position2d<s32>(10,controlsTop), L"Material");
  633. MeshMaterialControl->setMaterial(SceneNode->getMaterial(0));
  634. MeshMaterialControl->selectTextures(core::stringw("CARO_A8R8G8B8")); // set a useful default texture
  635. // add one light
  636. const f32 lightRadius = 80.f;
  637. NodeLight = smgr->addLightSceneNode(0, core::vector3df(0, 30, -70),
  638. video::SColorf(1.0f, 1.0f, 1.0f),
  639. lightRadius);
  640. LightControl = new CLightNodeControl();
  641. LightControl->init(NodeLight, guiEnv, core::position2d<s32>(550,controlsTop), L"Dynamic light" );
  642. #if 0 // enable to have some visual feedback for the light size
  643. scene::IMeshSceneNode* lightRadiusNode = smgr->addSphereSceneNode(lightRadius, 64, NodeLight);
  644. lightRadiusNode->getMaterial(0).Lighting = false;
  645. lightRadiusNode->getMaterial(0).Wireframe = true;
  646. #endif
  647. // one large cube around everything. That's mainly to make the light more obvious.
  648. scene::IMeshSceneNode* backgroundCube = smgr->addCubeSceneNode (200.0f, 0, -1, core::vector3df(0, 0, 0),
  649. core::vector3df(45, 0, 0),
  650. core::vector3df(1.0f, 1.0f, 1.0f));
  651. backgroundCube->getMaterial(0).BackfaceCulling = false; // we are within the cube, so we have to disable backface culling to see it
  652. backgroundCube->getMaterial(0).EmissiveColor.set(255,50,50,50); // we keep some self lighting to keep texts visible
  653. // Add a the mesh UI controls
  654. gui::IGUIStaticText* stMesh = guiEnv->addStaticText(L"Mesh", core::rect<s32>(440, controlsTop, 520, controlsTop+15), true, false, 0, -1, true);
  655. stMesh->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
  656. ComboMeshType = guiEnv->addComboBox(core::rect<s32>(440, controlsTop+16, 520, controlsTop+30), 0, -1);
  657. ComboMeshType->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
  658. ComboMeshType->addItem(L"cube");
  659. ComboMeshType->addItem(L"sphere");
  660. ComboMeshType->addItem(L"sphere highres");
  661. ControlVertexColors = new CColorControl( guiEnv, core::position2d<s32>(440, controlsTop+30), L"Vertex colors", guiEnv->getRootGUIElement());
  662. ControlVertexColors->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
  663. ControlVertexColors->setColor(irr::video::SColor(255,255,255,255));
  664. // Add a control for ambient light
  665. GlobalAmbient = new CColorControl( guiEnv, core::position2d<s32>(550, 300), L"Global ambient", guiEnv->getRootGUIElement());
  666. GlobalAmbient->setColor( smgr->getAmbientLight().toSColor() );
  667. GlobalAmbient->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
  668. return true;
  669. }
  670. /*
  671. Update one frame
  672. */
  673. bool CApp::update()
  674. {
  675. video::IVideoDriver* videoDriver = Device->getVideoDriver();
  676. if ( !Device->run() )
  677. return false;
  678. // Figure out delta time since last frame
  679. u32 newTick = Device->getTimer()->getRealTime();
  680. f32 deltaTime = RealTimeTick > 0 ? f32(newTick-RealTimeTick)/1000.f : 0.f; // in seconds
  681. RealTimeTick = newTick;
  682. if ( Device->isWindowActive() || Config.RenderInBackground )
  683. {
  684. gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
  685. scene::ISceneManager* smgr = Device->getSceneManager();
  686. gui::IGUISkin * skin = guiEnv->getSkin();
  687. // update our controls
  688. MeshMaterialControl->update(SceneNode, SceneNode2T, SceneNodeTangents);
  689. LightControl->update(NodeLight);
  690. // Update vertices
  691. if ( ControlVertexColors->isDirty() )
  692. {
  693. MeshManipulator->setVertexColors (SceneNode->getMesh(), ControlVertexColors->getColor());
  694. MeshManipulator->setVertexColors (SceneNode2T->getMesh(), ControlVertexColors->getColor());
  695. MeshManipulator->setVertexColors (SceneNodeTangents->getMesh(), ControlVertexColors->getColor());
  696. ControlVertexColors->resetDirty();
  697. }
  698. // update ambient light settings
  699. if ( GlobalAmbient->isDirty() )
  700. {
  701. smgr->setAmbientLight( GlobalAmbient->getColor() );
  702. GlobalAmbient->resetDirty();
  703. }
  704. const float zoomSpeed = (KeysPressed[KEY_LSHIFT] ? 40.f : 10.f) * deltaTime;
  705. const float rotationSpeed = (KeysPressed[KEY_LSHIFT] ? 20.f : 100.f) * deltaTime;
  706. // Let the user move the light around
  707. irr::gui::IGUIElement* focus=guiEnv->getFocus(); // some checks to prevent interfering with UI input
  708. if ( !focus || focus == guiEnv->getRootGUIElement()
  709. || focus->getType() == irr::gui::EGUIET_STATIC_TEXT
  710. || focus->getType() == irr::gui::EGUIET_BUTTON
  711. )
  712. {
  713. if ( KeysPressed[KEY_PLUS] || KeysPressed[KEY_ADD])
  714. ZoomOut(NodeLight, zoomSpeed);
  715. if ( KeysPressed[KEY_MINUS] || KeysPressed[KEY_SUBTRACT])
  716. ZoomOut(NodeLight, -zoomSpeed);
  717. if ( KeysPressed[KEY_RIGHT])
  718. RotateHorizontal(NodeLight, rotationSpeed);
  719. if ( KeysPressed[KEY_LEFT])
  720. RotateHorizontal(NodeLight, -rotationSpeed);
  721. UpdateRotationAxis(NodeLight, LightRotationAxis);
  722. if ( KeysPressed[KEY_UP])
  723. RotateAroundAxis(NodeLight, rotationSpeed, LightRotationAxis);
  724. if ( KeysPressed[KEY_DOWN])
  725. RotateAroundAxis(NodeLight, -rotationSpeed, LightRotationAxis);
  726. }
  727. // Let the user move the camera around
  728. if (MousePressed && !focus)
  729. {
  730. gui::ICursorControl* cursorControl = Device->getCursorControl();
  731. const core::position2d<s32>& mousePos = cursorControl->getPosition ();
  732. RotateHorizontal(Camera, rotationSpeed * (MouseStart.X - mousePos.X));
  733. RotateAroundAxis(Camera, rotationSpeed * (mousePos.Y - MouseStart.Y), CameraRotationAxis);
  734. MouseStart = mousePos;
  735. }
  736. // draw everything
  737. video::SColor bkColor( skin->getColor(gui::EGDC_APP_WORKSPACE) );
  738. videoDriver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, bkColor);
  739. smgr->drawAll();
  740. guiEnv->drawAll();
  741. if ( MeshMaterialControl->isLightingEnabled() )
  742. {
  743. // draw a line from the light to the target
  744. video::SMaterial lineMaterial;
  745. lineMaterial.Lighting = false;
  746. videoDriver->setMaterial(lineMaterial);
  747. videoDriver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
  748. videoDriver->draw3DLine(NodeLight->getAbsolutePosition(), SceneNode->getAbsolutePosition());
  749. }
  750. videoDriver->endScene();
  751. }
  752. // be nice
  753. Device->yield();
  754. return true;
  755. }
  756. // Close down the application
  757. void CApp::quit()
  758. {
  759. IsRunning = false;
  760. delete LightControl;
  761. LightControl = NULL;
  762. delete MeshMaterialControl;
  763. MeshMaterialControl = NULL;
  764. if ( ControlVertexColors )
  765. {
  766. ControlVertexColors->drop();
  767. ControlVertexColors = NULL;
  768. }
  769. if ( GlobalAmbient )
  770. {
  771. GlobalAmbient->drop();
  772. GlobalAmbient = NULL;
  773. }
  774. if ( Device )
  775. {
  776. Device->closeDevice();
  777. Device->drop();
  778. Device = NULL;
  779. }
  780. }
  781. // Create some useful textures.
  782. void CApp::createDefaultTextures(video::IVideoDriver * driver)
  783. {
  784. const u32 width = 256;
  785. const u32 height = 256;
  786. video::IImage * imageA8R8G8B8 = driver->createImage (video::ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
  787. if ( !imageA8R8G8B8 )
  788. return;
  789. const u32 pitch = imageA8R8G8B8->getPitch();
  790. // Some nice square-pattern with 9 typical colors
  791. // Note that the function put readability over speed, you shouldn't use setPixel at runtime but for initialization it's nice.
  792. for ( u32 y = 0; y < height; ++ y )
  793. {
  794. for ( u32 x = 0; x < pitch; ++x )
  795. {
  796. if ( y < height/3 )
  797. {
  798. if ( x < width/3 )
  799. imageA8R8G8B8->setPixel (x, y, SCOL_BLACK);
  800. else if ( x < 2*width/3 )
  801. imageA8R8G8B8->setPixel (x, y, SCOL_BLUE);
  802. else
  803. imageA8R8G8B8->setPixel (x, y, SCOL_CYAN);
  804. }
  805. else if ( y < 2*height/3 )
  806. {
  807. if ( x < width/3 )
  808. imageA8R8G8B8->setPixel (x, y, SCOL_GRAY);
  809. else if ( x < 2*width/3 )
  810. imageA8R8G8B8->setPixel (x, y, SCOL_GREEN);
  811. else
  812. imageA8R8G8B8->setPixel (x, y, SCOL_MAGENTA);
  813. }
  814. else
  815. {
  816. if ( x < width/3 )
  817. imageA8R8G8B8->setPixel (x, y, SCOL_RED);
  818. else if ( x < 2*width/3 )
  819. imageA8R8G8B8->setPixel (x, y, SCOL_YELLOW);
  820. else
  821. imageA8R8G8B8->setPixel (x, y, SCOL_WHITE);
  822. }
  823. }
  824. }
  825. driver->addTexture (io::path("CARO_A8R8G8B8"), imageA8R8G8B8);
  826. // all white
  827. imageA8R8G8B8->fill(SCOL_WHITE);
  828. driver->addTexture (io::path("WHITE_A8R8G8B8"), imageA8R8G8B8);
  829. // all black
  830. imageA8R8G8B8->fill(SCOL_BLACK);
  831. driver->addTexture (io::path("BLACK_A8R8G8B8"), imageA8R8G8B8);
  832. // gray-scale
  833. for ( u32 y = 0; y < height; ++ y )
  834. {
  835. for ( u32 x = 0; x < pitch; ++x )
  836. {
  837. imageA8R8G8B8->setPixel (x, y, video::SColor(y, x,x,x) );
  838. }
  839. }
  840. driver->addTexture (io::path("GRAYSCALE_A8R8G8B8"), imageA8R8G8B8);
  841. imageA8R8G8B8->drop();
  842. }
  843. // Load a texture and make sure UI knows it when more textures are available.
  844. void CApp::loadTexture(const io::path &name)
  845. {
  846. Device->getVideoDriver()->getTexture(name);
  847. MeshMaterialControl->updateTextures();
  848. }
  849. void CApp::RotateHorizontal(irr::scene::ISceneNode* node, irr::f32 angle)
  850. {
  851. if ( node )
  852. {
  853. core::vector3df pos(node->getPosition());
  854. core::vector2df dir(pos.X, pos.Z);
  855. dir.rotateBy(angle);
  856. pos.X = dir.X;
  857. pos.Z = dir.Y;
  858. node->setPosition(pos);
  859. }
  860. }
  861. void CApp::RotateAroundAxis(irr::scene::ISceneNode* node, irr::f32 angle, const irr::core::vector3df& axis)
  862. {
  863. if ( node )
  864. {
  865. // TOOD: yeah, doesn't rotate around top/bottom yet. Fixes welcome.
  866. core::vector3df pos(node->getPosition());
  867. core::matrix4 mat;
  868. mat.setRotationAxisRadians (core::degToRad(angle), axis);
  869. mat.rotateVect(pos);
  870. node->setPosition(pos);
  871. }
  872. }
  873. void CApp::ZoomOut(irr::scene::ISceneNode* node, irr::f32 units)
  874. {
  875. if ( node )
  876. {
  877. core::vector3df pos(node->getPosition());
  878. irr::f32 len = pos.getLength() + units;
  879. pos.setLength(len);
  880. node->setPosition(pos);
  881. }
  882. }
  883. void CApp::UpdateRotationAxis(irr::scene::ISceneNode* node, irr::core::vector3df& axis)
  884. {
  885. // Find a perpendicular axis to the x,z vector. If none found (vector straight up/down) continue to use the existing one.
  886. core::vector3df pos(node->getPosition());
  887. if ( !core::equals(pos.X, 0.f) || !core::equals(pos.Z, 0.f) )
  888. {
  889. axis.X = -pos.Z;
  890. axis.Z = pos.X;
  891. axis.normalize();
  892. }
  893. }
  894. void CApp::setActiveMeshNodeType(ENodeType nodeType)
  895. {
  896. scene::ISceneManager* smgr = Device->getSceneManager();
  897. if ( SceneNode )
  898. smgr->addToDeletionQueue(SceneNode);
  899. SceneNode = nullptr;
  900. if ( SceneNode2T )
  901. smgr->addToDeletionQueue(SceneNode2T);
  902. SceneNode2T = nullptr;
  903. if ( SceneNodeTangents )
  904. smgr->addToDeletionQueue(SceneNodeTangents);
  905. SceneNodeTangents = nullptr;
  906. // default material
  907. video::SMaterial defaultMaterial;
  908. defaultMaterial.Shininess = 20.f;
  909. // add the nodes which are used to show the materials
  910. const irr::f32 size = 35.f;
  911. if ( nodeType == ENT_CUBE )
  912. {
  913. SceneNode = smgr->addCubeSceneNode (size, 0, -1,
  914. core::vector3df(0, 0, 0),
  915. core::vector3df(0.f, 45.f, 0.f),
  916. core::vector3df(1.0f, 1.0f, 1.0f),
  917. scene::ECMT_1BUF_24VTX_NP);
  918. // avoid wrong colored lines at cube-borders (uv's go from 0-1 currently, which does not work well with interpolation)
  919. for ( u32 i=0; i < irr::video::MATERIAL_MAX_TEXTURES_USED; ++i)
  920. {
  921. defaultMaterial.TextureLayer[i].TextureWrapU = irr::video::ETC_CLAMP_TO_EDGE;
  922. defaultMaterial.TextureLayer[i].TextureWrapV = irr::video::ETC_CLAMP_TO_EDGE;
  923. }
  924. }
  925. else
  926. {
  927. SceneNode = smgr->addSphereSceneNode(size * 0.5f, nodeType == ENT_SPHERE_HIGHRES ? 128 : 16);
  928. }
  929. // off center to test shader
  930. //SceneNode->setPosition(core::vector3df(20.f, -4.f, 10.f));
  931. //SceneNode->setScale(core::vector3df(1.f, 0.2f, 1.5f));
  932. //SceneNode->setRotation(core::vector3df(0.f, 30.f, -10.f));
  933. //defaultMaterial.NormalizeNormals = true;
  934. SceneNode->getMaterial(0) = defaultMaterial;
  935. // SceneNode->setDebugDataVisible(scene::EDS_NORMALS); // showing normals can sometimes be useful to understand what's going on
  936. // create nodes with other vertex types
  937. scene::IMesh * mesh2T = MeshManipulator->createMeshWith2TCoords(SceneNode->getMesh());
  938. SceneNode2T = smgr->addMeshSceneNode(mesh2T, 0, -1, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
  939. mesh2T->drop();
  940. scene::IMesh * meshTangents = MeshManipulator->createMeshWithTangents(SceneNode->getMesh(), false, false, false);
  941. SceneNodeTangents = smgr->addMeshSceneNode(meshTangents, 0, -1
  942. , SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
  943. meshTangents->drop();
  944. }
  945. irr::scene::IMeshSceneNode* CApp::getVisibleMeshNode() const
  946. {
  947. if ( SceneNode && SceneNode->isVisible() )
  948. return SceneNode;
  949. if ( SceneNode2T && SceneNode2T->isVisible() )
  950. return SceneNode2T;
  951. if ( SceneNodeTangents && SceneNodeTangents->isVisible() )
  952. return SceneNodeTangents;
  953. return nullptr;
  954. }
  955. /*
  956. Short main as most is done in classes.
  957. */
  958. int main(int argc, char *argv[])
  959. {
  960. CApp APP;
  961. if ( !APP.init(argc, argv) )
  962. {
  963. printf("init failed\n");
  964. APP.quit();
  965. return 1;
  966. }
  967. APP.setRunning(true);
  968. /*
  969. main application loop
  970. */
  971. while(APP.isRunning())
  972. {
  973. if ( !APP.update() )
  974. break;
  975. }
  976. APP.quit();
  977. return 0;
  978. }
  979. /*
  980. **/