aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/examples/09.Meshviewer/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/examples/09.Meshviewer/main.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/examples/09.Meshviewer/main.cpp1042
1 files changed, 1042 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/examples/09.Meshviewer/main.cpp b/src/others/irrlicht-1.8.1/examples/09.Meshviewer/main.cpp
new file mode 100644
index 0000000..b9dc550
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/examples/09.Meshviewer/main.cpp
@@ -0,0 +1,1042 @@
1/** Example 009 Mesh Viewer
2
3This tutorial show how to create a more complex application with the engine.
4We construct a simple mesh viewer using the user interface API and the
5scene management of Irrlicht. The tutorial show how to create and use Buttons,
6Windows, Toolbars, Menus, ComboBoxes, Tabcontrols, Editboxes, Images,
7MessageBoxes, SkyBoxes, and how to parse XML files with the integrated XML
8reader of the engine.
9
10We start like in most other tutorials: Include all necessary header files, add
11a comment to let the engine be linked with the right .lib file in Visual
12Studio, and declare some global variables. We also add two 'using namespace'
13statements, so we do not need to write the whole names of all classes. In this
14tutorial, we use a lot stuff from the gui namespace.
15*/
16#include <irrlicht.h>
17#include "driverChoice.h"
18
19using namespace irr;
20using namespace gui;
21
22#ifdef _MSC_VER
23#pragma comment(lib, "Irrlicht.lib")
24#endif
25
26
27/*
28Some global variables used later on
29*/
30IrrlichtDevice *Device = 0;
31core::stringc StartUpModelFile;
32core::stringw MessageText;
33core::stringw Caption;
34scene::ISceneNode* Model = 0;
35scene::ISceneNode* SkyBox = 0;
36bool Octree=false;
37bool UseLight=false;
38
39scene::ICameraSceneNode* Camera[2] = {0, 0};
40
41// Values used to identify individual GUI elements
42enum
43{
44 GUI_ID_DIALOG_ROOT_WINDOW = 0x10000,
45
46 GUI_ID_X_SCALE,
47 GUI_ID_Y_SCALE,
48 GUI_ID_Z_SCALE,
49
50 GUI_ID_OPEN_MODEL,
51 GUI_ID_SET_MODEL_ARCHIVE,
52 GUI_ID_LOAD_AS_OCTREE,
53
54 GUI_ID_SKY_BOX_VISIBLE,
55 GUI_ID_TOGGLE_DEBUG_INFO,
56
57 GUI_ID_DEBUG_OFF,
58 GUI_ID_DEBUG_BOUNDING_BOX,
59 GUI_ID_DEBUG_NORMALS,
60 GUI_ID_DEBUG_SKELETON,
61 GUI_ID_DEBUG_WIRE_OVERLAY,
62 GUI_ID_DEBUG_HALF_TRANSPARENT,
63 GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES,
64 GUI_ID_DEBUG_ALL,
65
66 GUI_ID_MODEL_MATERIAL_SOLID,
67 GUI_ID_MODEL_MATERIAL_TRANSPARENT,
68 GUI_ID_MODEL_MATERIAL_REFLECTION,
69
70 GUI_ID_CAMERA_MAYA,
71 GUI_ID_CAMERA_FIRST_PERSON,
72
73 GUI_ID_POSITION_TEXT,
74
75 GUI_ID_ABOUT,
76 GUI_ID_QUIT,
77
78 GUI_ID_TEXTUREFILTER,
79 GUI_ID_SKIN_TRANSPARENCY,
80 GUI_ID_SKIN_ANIMATION_FPS,
81
82 GUI_ID_BUTTON_SET_SCALE,
83 GUI_ID_BUTTON_SCALE_MUL10,
84 GUI_ID_BUTTON_SCALE_DIV10,
85 GUI_ID_BUTTON_OPEN_MODEL,
86 GUI_ID_BUTTON_SHOW_ABOUT,
87 GUI_ID_BUTTON_SHOW_TOOLBOX,
88 GUI_ID_BUTTON_SELECT_ARCHIVE,
89
90 GUI_ID_ANIMATION_INFO,
91
92 // And some magic numbers
93 MAX_FRAMERATE = 80,
94 DEFAULT_FRAMERATE = 30
95};
96
97
98/*
99Toggle between various cameras
100*/
101void setActiveCamera(scene::ICameraSceneNode* newActive)
102{
103 if (0 == Device)
104 return;
105
106 scene::ICameraSceneNode * active = Device->getSceneManager()->getActiveCamera();
107 active->setInputReceiverEnabled(false);
108
109 newActive->setInputReceiverEnabled(true);
110 Device->getSceneManager()->setActiveCamera(newActive);
111}
112
113/*
114 Set the skin transparency by changing the alpha values of all skin-colors
115*/
116void setSkinTransparency(s32 alpha, irr::gui::IGUISkin * skin)
117{
118 for (s32 i=0; i<irr::gui::EGDC_COUNT ; ++i)
119 {
120 video::SColor col = skin->getColor((EGUI_DEFAULT_COLOR)i);
121 col.setAlpha(alpha);
122 skin->setColor((EGUI_DEFAULT_COLOR)i, col);
123 }
124}
125
126/*
127 Update the display of the model scaling
128*/
129void updateScaleInfo(scene::ISceneNode* model)
130{
131 IGUIElement* toolboxWnd = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true);
132 if (!toolboxWnd)
133 return;
134 if (!model)
135 {
136 toolboxWnd->getElementFromId(GUI_ID_X_SCALE, true)->setText( L"-" );
137 toolboxWnd->getElementFromId(GUI_ID_Y_SCALE, true)->setText( L"-" );
138 toolboxWnd->getElementFromId(GUI_ID_Z_SCALE, true)->setText( L"-" );
139 }
140 else
141 {
142 core::vector3df scale = model->getScale();
143 toolboxWnd->getElementFromId(GUI_ID_X_SCALE, true)->setText( core::stringw(scale.X).c_str() );
144 toolboxWnd->getElementFromId(GUI_ID_Y_SCALE, true)->setText( core::stringw(scale.Y).c_str() );
145 toolboxWnd->getElementFromId(GUI_ID_Z_SCALE, true)->setText( core::stringw(scale.Z).c_str() );
146 }
147}
148
149/*
150Function showAboutText() displays a messagebox with a caption and
151a message text. The texts will be stored in the MessageText and Caption
152variables at startup.
153*/
154void showAboutText()
155{
156 // create modal message box with the text
157 // loaded from the xml file.
158 Device->getGUIEnvironment()->addMessageBox(
159 Caption.c_str(), MessageText.c_str());
160}
161
162
163/*
164Function loadModel() loads a model and displays it using an
165addAnimatedMeshSceneNode and the scene manager. Nothing difficult. It also
166displays a short message box, if the model could not be loaded.
167*/
168void loadModel(const c8* fn)
169{
170 // modify the name if it a .pk3 file
171
172 io::path filename(fn);
173
174 io::path extension;
175 core::getFileNameExtension(extension, filename);
176 extension.make_lower();
177
178 // if a texture is loaded apply it to the current model..
179 if (extension == ".jpg" || extension == ".pcx" ||
180 extension == ".png" || extension == ".ppm" ||
181 extension == ".pgm" || extension == ".pbm" ||
182 extension == ".psd" || extension == ".tga" ||
183 extension == ".bmp" || extension == ".wal" ||
184 extension == ".rgb" || extension == ".rgba")
185 {
186 video::ITexture * texture =
187 Device->getVideoDriver()->getTexture( filename );
188 if ( texture && Model )
189 {
190 // always reload texture
191 Device->getVideoDriver()->removeTexture(texture);
192 texture = Device->getVideoDriver()->getTexture( filename );
193
194 Model->setMaterialTexture(0, texture);
195 }
196 return;
197 }
198 // if a archive is loaded add it to the FileArchive..
199 else if (extension == ".pk3" || extension == ".zip" || extension == ".pak" || extension == ".npk")
200 {
201 Device->getFileSystem()->addFileArchive(filename.c_str());
202 return;
203 }
204
205 // load a model into the engine
206
207 if (Model)
208 Model->remove();
209
210 Model = 0;
211
212 if (extension==".irr")
213 {
214 core::array<scene::ISceneNode*> outNodes;
215 Device->getSceneManager()->loadScene(filename);
216 Device->getSceneManager()->getSceneNodesFromType(scene::ESNT_ANIMATED_MESH, outNodes);
217 if (outNodes.size())
218 Model = outNodes[0];
219 return;
220 }
221
222 scene::IAnimatedMesh* m = Device->getSceneManager()->getMesh( filename.c_str() );
223
224 if (!m)
225 {
226 // model could not be loaded
227
228 if (StartUpModelFile != filename)
229 Device->getGUIEnvironment()->addMessageBox(
230 Caption.c_str(), L"The model could not be loaded. " \
231 L"Maybe it is not a supported file format.");
232 return;
233 }
234
235 // set default material properties
236
237 if (Octree)
238 Model = Device->getSceneManager()->addOctreeSceneNode(m->getMesh(0));
239 else
240 {
241 scene::IAnimatedMeshSceneNode* animModel = Device->getSceneManager()->addAnimatedMeshSceneNode(m);
242 animModel->setAnimationSpeed(30);
243 Model = animModel;
244 }
245 Model->setMaterialFlag(video::EMF_LIGHTING, UseLight);
246 Model->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, UseLight);
247// Model->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
248 Model->setDebugDataVisible(scene::EDS_OFF);
249
250 // we need to uncheck the menu entries. would be cool to fake a menu event, but
251 // that's not so simple. so we do it brute force
252 gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_TOGGLE_DEBUG_INFO, true);
253 if (menu)
254 for(int item = 1; item < 6; ++item)
255 menu->setItemChecked(item, false);
256 updateScaleInfo(Model);
257}
258
259
260/*
261Function createToolBox() creates a toolbox window. In this simple mesh
262viewer, this toolbox only contains a tab control with three edit boxes for
263changing the scale of the displayed model.
264*/
265void createToolBox()
266{
267 // remove tool box if already there
268 IGUIEnvironment* env = Device->getGUIEnvironment();
269 IGUIElement* root = env->getRootGUIElement();
270 IGUIElement* e = root->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true);
271 if (e)
272 e->remove();
273
274 // create the toolbox window
275 IGUIWindow* wnd = env->addWindow(core::rect<s32>(600,45,800,480),
276 false, L"Toolset", 0, GUI_ID_DIALOG_ROOT_WINDOW);
277
278 // create tab control and tabs
279 IGUITabControl* tab = env->addTabControl(
280 core::rect<s32>(2,20,800-602,480-7), wnd, true, true);
281
282 IGUITab* t1 = tab->addTab(L"Config");
283
284 // add some edit boxes and a button to tab one
285 env->addStaticText(L"Scale:",
286 core::rect<s32>(10,20,60,45), false, false, t1);
287 env->addStaticText(L"X:", core::rect<s32>(22,48,40,66), false, false, t1);
288 env->addEditBox(L"1.0", core::rect<s32>(40,46,130,66), true, t1, GUI_ID_X_SCALE);
289 env->addStaticText(L"Y:", core::rect<s32>(22,82,40,96), false, false, t1);
290 env->addEditBox(L"1.0", core::rect<s32>(40,76,130,96), true, t1, GUI_ID_Y_SCALE);
291 env->addStaticText(L"Z:", core::rect<s32>(22,108,40,126), false, false, t1);
292 env->addEditBox(L"1.0", core::rect<s32>(40,106,130,126), true, t1, GUI_ID_Z_SCALE);
293
294 env->addButton(core::rect<s32>(10,134,85,165), t1, GUI_ID_BUTTON_SET_SCALE, L"Set");
295
296 // quick scale buttons
297 env->addButton(core::rect<s32>(65,20,95,40), t1, GUI_ID_BUTTON_SCALE_MUL10, L"* 10");
298 env->addButton(core::rect<s32>(100,20,130,40), t1, GUI_ID_BUTTON_SCALE_DIV10, L"* 0.1");
299
300 updateScaleInfo(Model);
301
302 // add transparency control
303 env->addStaticText(L"GUI Transparency Control:",
304 core::rect<s32>(10,200,150,225), true, false, t1);
305 IGUIScrollBar* scrollbar = env->addScrollBar(true,
306 core::rect<s32>(10,225,150,240), t1, GUI_ID_SKIN_TRANSPARENCY);
307 scrollbar->setMax(255);
308 scrollbar->setPos(255);
309
310 // add framerate control
311 env->addStaticText(L":", core::rect<s32>(10,240,150,265), true, false, t1);
312 env->addStaticText(L"Framerate:",
313 core::rect<s32>(12,240,75,265), false, false, t1);
314 // current frame info
315 env->addStaticText(L"", core::rect<s32>(75,240,200,265), false, false, t1,
316 GUI_ID_ANIMATION_INFO);
317 scrollbar = env->addScrollBar(true,
318 core::rect<s32>(10,265,150,280), t1, GUI_ID_SKIN_ANIMATION_FPS);
319 scrollbar->setMax(MAX_FRAMERATE);
320 scrollbar->setMin(-MAX_FRAMERATE);
321 scrollbar->setPos(DEFAULT_FRAMERATE);
322 scrollbar->setSmallStep(1);
323}
324
325/*
326Function updateToolBox() is called each frame to update dynamic information in
327the toolbox.
328*/
329void updateToolBox()
330{
331 IGUIEnvironment* env = Device->getGUIEnvironment();
332 IGUIElement* root = env->getRootGUIElement();
333 IGUIElement* dlg = root->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true);
334 if (!dlg )
335 return;
336
337 // update the info we have about the animation of the model
338 IGUIStaticText * aniInfo = (IGUIStaticText *)(dlg->getElementFromId(GUI_ID_ANIMATION_INFO, true));
339 if (aniInfo)
340 {
341 if ( Model && scene::ESNT_ANIMATED_MESH == Model->getType() )
342 {
343 scene::IAnimatedMeshSceneNode* animatedModel = (scene::IAnimatedMeshSceneNode*)Model;
344
345 core::stringw str( (s32)core::round_(animatedModel->getAnimationSpeed()) );
346 str += L" Frame: ";
347 str += core::stringw((s32)animatedModel->getFrameNr());
348 aniInfo->setText(str.c_str());
349 }
350 else
351 aniInfo->setText(L"");
352 }
353}
354
355void onKillFocus()
356{
357 // Avoid that the FPS-camera continues moving when the user presses alt-tab while
358 // moving the camera.
359 const core::list<scene::ISceneNodeAnimator*>& animators = Camera[1]->getAnimators();
360 core::list<irr::scene::ISceneNodeAnimator*>::ConstIterator iter = animators.begin();
361 while ( iter != animators.end() )
362 {
363 if ( (*iter)->getType() == scene::ESNAT_CAMERA_FPS )
364 {
365 // we send a key-down event for all keys used by this animator
366 scene::ISceneNodeAnimatorCameraFPS * fpsAnimator = static_cast<scene::ISceneNodeAnimatorCameraFPS*>(*iter);
367 const core::array<SKeyMap>& keyMap = fpsAnimator->getKeyMap();
368 for ( irr::u32 i=0; i< keyMap.size(); ++i )
369 {
370 irr::SEvent event;
371 event.EventType = EET_KEY_INPUT_EVENT;
372 event.KeyInput.Key = keyMap[i].KeyCode;
373 event.KeyInput.PressedDown = false;
374 fpsAnimator->OnEvent(event);
375 }
376 }
377 ++iter;
378 }
379}
380
381/*
382Function hasModalDialog() checks if we currently have a modal dialog open.
383*/
384bool hasModalDialog()
385{
386 if ( !Device )
387 return false;
388 IGUIEnvironment* env = Device->getGUIEnvironment();
389 IGUIElement * focused = env->getFocus();
390 while ( focused )
391 {
392 if ( focused->isVisible() && focused->hasType(EGUIET_MODAL_SCREEN) )
393 return true;
394 focused = focused->getParent();
395 }
396 return false;
397}
398
399/*
400To get all the events sent by the GUI Elements, we need to create an event
401receiver. This one is really simple. If an event occurs, it checks the id of
402the caller and the event type, and starts an action based on these values. For
403example, if a menu item with id GUI_ID_OPEN_MODEL was selected, it opens a file-open-dialog.
404*/
405class MyEventReceiver : public IEventReceiver
406{
407public:
408 virtual bool OnEvent(const SEvent& event)
409 {
410 // Escape swaps Camera Input
411 if (event.EventType == EET_KEY_INPUT_EVENT &&
412 event.KeyInput.PressedDown == false)
413 {
414 if ( OnKeyUp(event.KeyInput.Key) )
415 return true;
416 }
417
418 if (event.EventType == EET_GUI_EVENT)
419 {
420 s32 id = event.GUIEvent.Caller->getID();
421 IGUIEnvironment* env = Device->getGUIEnvironment();
422
423 switch(event.GUIEvent.EventType)
424 {
425 case EGET_MENU_ITEM_SELECTED:
426 // a menu item was clicked
427 OnMenuItemSelected( (IGUIContextMenu*)event.GUIEvent.Caller );
428 break;
429
430 case EGET_FILE_SELECTED:
431 {
432 // load the model file, selected in the file open dialog
433 IGUIFileOpenDialog* dialog =
434 (IGUIFileOpenDialog*)event.GUIEvent.Caller;
435 loadModel(core::stringc(dialog->getFileName()).c_str());
436 }
437 break;
438
439 case EGET_SCROLL_BAR_CHANGED:
440
441 // control skin transparency
442 if (id == GUI_ID_SKIN_TRANSPARENCY)
443 {
444 const s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
445 setSkinTransparency(pos, env->getSkin());
446 }
447 // control animation speed
448 else if (id == GUI_ID_SKIN_ANIMATION_FPS)
449 {
450 const s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
451 if (scene::ESNT_ANIMATED_MESH == Model->getType())
452 ((scene::IAnimatedMeshSceneNode*)Model)->setAnimationSpeed((f32)pos);
453 }
454 break;
455
456 case EGET_COMBO_BOX_CHANGED:
457
458 // control anti-aliasing/filtering
459 if (id == GUI_ID_TEXTUREFILTER)
460 {
461 OnTextureFilterSelected( (IGUIComboBox*)event.GUIEvent.Caller );
462 }
463 break;
464
465 case EGET_BUTTON_CLICKED:
466
467 switch(id)
468 {
469 case GUI_ID_BUTTON_SET_SCALE:
470 {
471 // set scale
472 gui::IGUIElement* root = env->getRootGUIElement();
473 core::vector3df scale;
474 core::stringc s;
475
476 s = root->getElementFromId(GUI_ID_X_SCALE, true)->getText();
477 scale.X = (f32)atof(s.c_str());
478 s = root->getElementFromId(GUI_ID_Y_SCALE, true)->getText();
479 scale.Y = (f32)atof(s.c_str());
480 s = root->getElementFromId(GUI_ID_Z_SCALE, true)->getText();
481 scale.Z = (f32)atof(s.c_str());
482
483 if (Model)
484 Model->setScale(scale);
485 updateScaleInfo(Model);
486 }
487 break;
488 case GUI_ID_BUTTON_SCALE_MUL10:
489 if (Model)
490 Model->setScale(Model->getScale()*10.f);
491 updateScaleInfo(Model);
492 break;
493 case GUI_ID_BUTTON_SCALE_DIV10:
494 if (Model)
495 Model->setScale(Model->getScale()*0.1f);
496 updateScaleInfo(Model);
497 break;
498 case GUI_ID_BUTTON_OPEN_MODEL:
499 env->addFileOpenDialog(L"Please select a model file to open");
500 break;
501 case GUI_ID_BUTTON_SHOW_ABOUT:
502 showAboutText();
503 break;
504 case GUI_ID_BUTTON_SHOW_TOOLBOX:
505 createToolBox();
506 break;
507 case GUI_ID_BUTTON_SELECT_ARCHIVE:
508 env->addFileOpenDialog(L"Please select your game archive/directory");
509 break;
510 }
511
512 break;
513 default:
514 break;
515 }
516 }
517
518 return false;
519 }
520
521
522 /*
523 Handle key-up events
524 */
525 bool OnKeyUp(irr::EKEY_CODE keyCode)
526 {
527 // Don't handle keys if we have a modal dialog open as it would lead
528 // to unexpected application behaviour for the user.
529 if ( hasModalDialog() )
530 return false;
531
532 if (keyCode == irr::KEY_ESCAPE)
533 {
534 if (Device)
535 {
536 scene::ICameraSceneNode * camera =
537 Device->getSceneManager()->getActiveCamera();
538 if (camera)
539 {
540 camera->setInputReceiverEnabled( !camera->isInputReceiverEnabled() );
541 }
542 return true;
543 }
544 }
545 else if (keyCode == irr::KEY_F1)
546 {
547 if (Device)
548 {
549 IGUIElement* elem = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_POSITION_TEXT);
550 if (elem)
551 elem->setVisible(!elem->isVisible());
552 }
553 }
554 else if (keyCode == irr::KEY_KEY_M)
555 {
556 if (Device)
557 Device->minimizeWindow();
558 }
559 else if (keyCode == irr::KEY_KEY_L)
560 {
561 UseLight=!UseLight;
562 if (Model)
563 {
564 Model->setMaterialFlag(video::EMF_LIGHTING, UseLight);
565 Model->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, UseLight);
566 }
567 }
568 return false;
569 }
570
571
572 /*
573 Handle "menu item clicked" events.
574 */
575 void OnMenuItemSelected( IGUIContextMenu* menu )
576 {
577 s32 id = menu->getItemCommandId(menu->getSelectedItem());
578 IGUIEnvironment* env = Device->getGUIEnvironment();
579
580 switch(id)
581 {
582 case GUI_ID_OPEN_MODEL: // FilOnButtonSetScalinge -> Open Model
583 env->addFileOpenDialog(L"Please select a model file to open");
584 break;
585 case GUI_ID_SET_MODEL_ARCHIVE: // File -> Set Model Archive
586 env->addFileOpenDialog(L"Please select your game archive/directory");
587 break;
588 case GUI_ID_LOAD_AS_OCTREE: // File -> LoadAsOctree
589 Octree = !Octree;
590 menu->setItemChecked(menu->getSelectedItem(), Octree);
591 break;
592 case GUI_ID_QUIT: // File -> Quit
593 Device->closeDevice();
594 break;
595 case GUI_ID_SKY_BOX_VISIBLE: // View -> Skybox
596 menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
597 SkyBox->setVisible(!SkyBox->isVisible());
598 break;
599 case GUI_ID_DEBUG_OFF: // View -> Debug Information
600 menu->setItemChecked(menu->getSelectedItem()+1, false);
601 menu->setItemChecked(menu->getSelectedItem()+2, false);
602 menu->setItemChecked(menu->getSelectedItem()+3, false);
603 menu->setItemChecked(menu->getSelectedItem()+4, false);
604 menu->setItemChecked(menu->getSelectedItem()+5, false);
605 menu->setItemChecked(menu->getSelectedItem()+6, false);
606 if (Model)
607 Model->setDebugDataVisible(scene::EDS_OFF);
608 break;
609 case GUI_ID_DEBUG_BOUNDING_BOX: // View -> Debug Information
610 menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
611 if (Model)
612 Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX));
613 break;
614 case GUI_ID_DEBUG_NORMALS: // View -> Debug Information
615 menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
616 if (Model)
617 Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_NORMALS));
618 break;
619 case GUI_ID_DEBUG_SKELETON: // View -> Debug Information
620 menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
621 if (Model)
622 Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_SKELETON));
623 break;
624 case GUI_ID_DEBUG_WIRE_OVERLAY: // View -> Debug Information
625 menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
626 if (Model)
627 Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY));
628 break;
629 case GUI_ID_DEBUG_HALF_TRANSPARENT: // View -> Debug Information
630 menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
631 if (Model)
632 Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_HALF_TRANSPARENCY));
633 break;
634 case GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES: // View -> Debug Information
635 menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
636 if (Model)
637 Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX_BUFFERS));
638 break;
639 case GUI_ID_DEBUG_ALL: // View -> Debug Information
640 menu->setItemChecked(menu->getSelectedItem()-1, true);
641 menu->setItemChecked(menu->getSelectedItem()-2, true);
642 menu->setItemChecked(menu->getSelectedItem()-3, true);
643 menu->setItemChecked(menu->getSelectedItem()-4, true);
644 menu->setItemChecked(menu->getSelectedItem()-5, true);
645 menu->setItemChecked(menu->getSelectedItem()-6, true);
646 if (Model)
647 Model->setDebugDataVisible(scene::EDS_FULL);
648 break;
649 case GUI_ID_ABOUT: // Help->About
650 showAboutText();
651 break;
652 case GUI_ID_MODEL_MATERIAL_SOLID: // View -> Material -> Solid
653 if (Model)
654 Model->setMaterialType(video::EMT_SOLID);
655 break;
656 case GUI_ID_MODEL_MATERIAL_TRANSPARENT: // View -> Material -> Transparent
657 if (Model)
658 Model->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
659 break;
660 case GUI_ID_MODEL_MATERIAL_REFLECTION: // View -> Material -> Reflection
661 if (Model)
662 Model->setMaterialType(video::EMT_SPHERE_MAP);
663 break;
664
665 case GUI_ID_CAMERA_MAYA:
666 setActiveCamera(Camera[0]);
667 break;
668 case GUI_ID_CAMERA_FIRST_PERSON:
669 setActiveCamera(Camera[1]);
670 break;
671 }
672 }
673
674 /*
675 Handle the event that one of the texture-filters was selected in the corresponding combobox.
676 */
677 void OnTextureFilterSelected( IGUIComboBox* combo )
678 {
679 s32 pos = combo->getSelected();
680 switch (pos)
681 {
682 case 0:
683 if (Model)
684 {
685 Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
686 Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, false);
687 Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, false);
688 }
689 break;
690 case 1:
691 if (Model)
692 {
693 Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, true);
694 Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, false);
695 }
696 break;
697 case 2:
698 if (Model)
699 {
700 Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
701 Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, true);
702 }
703 break;
704 case 3:
705 if (Model)
706 {
707 Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, true);
708 }
709 break;
710 case 4:
711 if (Model)
712 {
713 Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, false);
714 }
715 break;
716 }
717 }
718};
719
720
721/*
722Most of the hard work is done. We only need to create the Irrlicht Engine
723device and all the buttons, menus and toolbars. We start up the engine as
724usual, using createDevice(). To make our application catch events, we set our
725eventreceiver as parameter. As you can see, there is also a call to
726IrrlichtDevice::setResizeable(). This makes the render window resizeable, which
727is quite useful for a mesh viewer.
728*/
729int main(int argc, char* argv[])
730{
731 // ask user for driver
732 video::E_DRIVER_TYPE driverType=driverChoiceConsole();
733 if (driverType==video::EDT_COUNT)
734 return 1;
735
736 // create device and exit if creation failed
737 MyEventReceiver receiver;
738 Device = createDevice(driverType, core::dimension2d<u32>(800, 600),
739 16, false, false, false, &receiver);
740
741 if (Device == 0)
742 return 1; // could not create selected driver.
743
744 Device->setResizable(true);
745
746 Device->setWindowCaption(L"Irrlicht Engine - Loading...");
747
748 video::IVideoDriver* driver = Device->getVideoDriver();
749 IGUIEnvironment* env = Device->getGUIEnvironment();
750 scene::ISceneManager* smgr = Device->getSceneManager();
751 smgr->getParameters()->setAttribute(scene::COLLADA_CREATE_SCENE_INSTANCES, true);
752
753 driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
754
755 smgr->addLightSceneNode(0, core::vector3df(200,200,200),
756 video::SColorf(1.0f,1.0f,1.0f),2000);
757 smgr->setAmbientLight(video::SColorf(0.3f,0.3f,0.3f));
758 // add our media directory as "search path"
759 Device->getFileSystem()->addFileArchive("../../media/");
760
761 /*
762 The next step is to read the configuration file. It is stored in the xml
763 format and looks a little bit like this:
764
765 @verbatim
766 <?xml version="1.0"?>
767 <config>
768 <startUpModel file="some filename" />
769 <messageText caption="Irrlicht Engine Mesh Viewer">
770 Hello!
771 </messageText>
772 </config>
773 @endverbatim
774
775 We need the data stored in there to be written into the global variables
776 StartUpModelFile, MessageText and Caption. This is now done using the
777 Irrlicht Engine integrated XML parser:
778 */
779
780 // read configuration from xml file
781
782 io::IXMLReader* xml = Device->getFileSystem()->createXMLReader( L"config.xml");
783
784 while(xml && xml->read())
785 {
786 switch(xml->getNodeType())
787 {
788 case io::EXN_TEXT:
789 // in this xml file, the only text which occurs is the
790 // messageText
791 MessageText = xml->getNodeData();
792 break;
793 case io::EXN_ELEMENT:
794 {
795 if (core::stringw("startUpModel") == xml->getNodeName())
796 StartUpModelFile = xml->getAttributeValue(L"file");
797 else
798 if (core::stringw("messageText") == xml->getNodeName())
799 Caption = xml->getAttributeValue(L"caption");
800 }
801 break;
802 default:
803 break;
804 }
805 }
806
807 if (xml)
808 xml->drop(); // don't forget to delete the xml reader
809
810 if (argc > 1)
811 StartUpModelFile = argv[1];
812
813 /*
814 That wasn't difficult. Now we'll set a nicer font and create the Menu.
815 It is possible to create submenus for every menu item. The call
816 menu->addItem(L"File", -1, true, true); for example adds a new menu
817 Item with the name "File" and the id -1. The following parameter says
818 that the menu item should be enabled, and the last one says, that there
819 should be a submenu. The submenu can now be accessed with
820 menu->getSubMenu(0), because the "File" entry is the menu item with
821 index 0.
822 */
823
824 // set a nicer font
825
826 IGUISkin* skin = env->getSkin();
827 IGUIFont* font = env->getFont("fonthaettenschweiler.bmp");
828 if (font)
829 skin->setFont(font);
830
831 // create menu
832 gui::IGUIContextMenu* menu = env->addMenu();
833 menu->addItem(L"File", -1, true, true);
834 menu->addItem(L"View", -1, true, true);
835 menu->addItem(L"Camera", -1, true, true);
836 menu->addItem(L"Help", -1, true, true);
837
838 gui::IGUIContextMenu* submenu;
839 submenu = menu->getSubMenu(0);
840 submenu->addItem(L"Open Model File & Texture...", GUI_ID_OPEN_MODEL);
841 submenu->addItem(L"Set Model Archive...", GUI_ID_SET_MODEL_ARCHIVE);
842 submenu->addItem(L"Load as Octree", GUI_ID_LOAD_AS_OCTREE);
843 submenu->addSeparator();
844 submenu->addItem(L"Quit", GUI_ID_QUIT);
845
846 submenu = menu->getSubMenu(1);
847 submenu->addItem(L"sky box visible", GUI_ID_SKY_BOX_VISIBLE, true, false, true);
848 submenu->addItem(L"toggle model debug information", GUI_ID_TOGGLE_DEBUG_INFO, true, true);
849 submenu->addItem(L"model material", -1, true, true );
850
851 submenu = submenu->getSubMenu(1);
852 submenu->addItem(L"Off", GUI_ID_DEBUG_OFF);
853 submenu->addItem(L"Bounding Box", GUI_ID_DEBUG_BOUNDING_BOX);
854 submenu->addItem(L"Normals", GUI_ID_DEBUG_NORMALS);
855 submenu->addItem(L"Skeleton", GUI_ID_DEBUG_SKELETON);
856 submenu->addItem(L"Wire overlay", GUI_ID_DEBUG_WIRE_OVERLAY);
857 submenu->addItem(L"Half-Transparent", GUI_ID_DEBUG_HALF_TRANSPARENT);
858 submenu->addItem(L"Buffers bounding boxes", GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES);
859 submenu->addItem(L"All", GUI_ID_DEBUG_ALL);
860
861 submenu = menu->getSubMenu(1)->getSubMenu(2);
862 submenu->addItem(L"Solid", GUI_ID_MODEL_MATERIAL_SOLID);
863 submenu->addItem(L"Transparent", GUI_ID_MODEL_MATERIAL_TRANSPARENT);
864 submenu->addItem(L"Reflection", GUI_ID_MODEL_MATERIAL_REFLECTION);
865
866 submenu = menu->getSubMenu(2);
867 submenu->addItem(L"Maya Style", GUI_ID_CAMERA_MAYA);
868 submenu->addItem(L"First Person", GUI_ID_CAMERA_FIRST_PERSON);
869
870 submenu = menu->getSubMenu(3);
871 submenu->addItem(L"About", GUI_ID_ABOUT);
872
873 /*
874 Below the menu we want a toolbar, onto which we can place colored
875 buttons and important looking stuff like a senseless combobox.
876 */
877
878 // create toolbar
879
880 gui::IGUIToolBar* bar = env->addToolBar();
881
882 video::ITexture* image = driver->getTexture("open.png");
883 bar->addButton(GUI_ID_BUTTON_OPEN_MODEL, 0, L"Open a model",image, 0, false, true);
884
885 image = driver->getTexture("tools.png");
886 bar->addButton(GUI_ID_BUTTON_SHOW_TOOLBOX, 0, L"Open Toolset",image, 0, false, true);
887
888 image = driver->getTexture("zip.png");
889 bar->addButton(GUI_ID_BUTTON_SELECT_ARCHIVE, 0, L"Set Model Archive",image, 0, false, true);
890
891 image = driver->getTexture("help.png");
892 bar->addButton(GUI_ID_BUTTON_SHOW_ABOUT, 0, L"Open Help", image, 0, false, true);
893
894 // create a combobox for texture filters
895
896 gui::IGUIComboBox* box = env->addComboBox(core::rect<s32>(250,4,350,23), bar, GUI_ID_TEXTUREFILTER);
897 box->addItem(L"No filtering");
898 box->addItem(L"Bilinear");
899 box->addItem(L"Trilinear");
900 box->addItem(L"Anisotropic");
901 box->addItem(L"Isotropic");
902
903 /*
904 To make the editor look a little bit better, we disable transparent gui
905 elements, and add an Irrlicht Engine logo. In addition, a text showing
906 the current frames per second value is created and the window caption is
907 changed.
908 */
909
910 // disable alpha
911
912 for (s32 i=0; i<gui::EGDC_COUNT ; ++i)
913 {
914 video::SColor col = env->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);
915 col.setAlpha(255);
916 env->getSkin()->setColor((gui::EGUI_DEFAULT_COLOR)i, col);
917 }
918
919 // add a tabcontrol
920
921 createToolBox();
922
923 // create fps text
924
925 IGUIStaticText* fpstext = env->addStaticText(L"",
926 core::rect<s32>(400,4,570,23), true, false, bar);
927
928 IGUIStaticText* postext = env->addStaticText(L"",
929 core::rect<s32>(10,50,470,80),false, false, 0, GUI_ID_POSITION_TEXT);
930 postext->setVisible(false);
931
932 // set window caption
933
934 Caption += " - [";
935 Caption += driver->getName();
936 Caption += "]";
937 Device->setWindowCaption(Caption.c_str());
938
939 /*
940 That's nearly the whole application. We simply show the about message
941 box at start up, and load the first model. To make everything look
942 better, a skybox is created and a user controlled camera, to make the
943 application a little bit more interactive. Finally, everything is drawn
944 in a standard drawing loop.
945 */
946
947 // show about message box and load default model
948 if (argc==1)
949 showAboutText();
950 loadModel(StartUpModelFile.c_str());
951
952 // add skybox
953
954 SkyBox = smgr->addSkyBoxSceneNode(
955 driver->getTexture("irrlicht2_up.jpg"),
956 driver->getTexture("irrlicht2_dn.jpg"),
957 driver->getTexture("irrlicht2_lf.jpg"),
958 driver->getTexture("irrlicht2_rt.jpg"),
959 driver->getTexture("irrlicht2_ft.jpg"),
960 driver->getTexture("irrlicht2_bk.jpg"));
961
962 // add a camera scene node
963 Camera[0] = smgr->addCameraSceneNodeMaya();
964 Camera[0]->setFarValue(20000.f);
965 // Maya cameras reposition themselves relative to their target, so target the location
966 // where the mesh scene node is placed.
967 Camera[0]->setTarget(core::vector3df(0,30,0));
968
969 Camera[1] = smgr->addCameraSceneNodeFPS();
970 Camera[1]->setFarValue(20000.f);
971 Camera[1]->setPosition(core::vector3df(0,0,-70));
972 Camera[1]->setTarget(core::vector3df(0,30,0));
973
974 setActiveCamera(Camera[0]);
975
976 // load the irrlicht engine logo
977 IGUIImage *img =
978 env->addImage(driver->getTexture("irrlichtlogo2.png"),
979 core::position2d<s32>(10, driver->getScreenSize().Height - 128));
980
981 // lock the logo's edges to the bottom left corner of the screen
982 img->setAlignment(EGUIA_UPPERLEFT, EGUIA_UPPERLEFT,
983 EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT);
984
985 // remember state so we notice when the window does lose the focus
986 bool hasFocus = Device->isWindowFocused();
987
988 // draw everything
989
990 while(Device->run() && driver)
991 {
992 // Catch focus changes (workaround until Irrlicht has events for this)
993 bool focused = Device->isWindowFocused();
994 if ( hasFocus && !focused )
995 onKillFocus();
996 hasFocus = focused;
997
998 if (Device->isWindowActive())
999 {
1000 driver->beginScene(true, true, video::SColor(150,50,50,50));
1001
1002 smgr->drawAll();
1003 env->drawAll();
1004
1005 driver->endScene();
1006
1007 // update information about current frame-rate
1008 core::stringw str(L"FPS: ");
1009 str.append(core::stringw(driver->getFPS()));
1010 str += L" Tris: ";
1011 str.append(core::stringw(driver->getPrimitiveCountDrawn()));
1012 fpstext->setText(str.c_str());
1013
1014 // update information about the active camera
1015 scene::ICameraSceneNode* cam = Device->getSceneManager()->getActiveCamera();
1016 str = L"Pos: ";
1017 str.append(core::stringw(cam->getPosition().X));
1018 str += L" ";
1019 str.append(core::stringw(cam->getPosition().Y));
1020 str += L" ";
1021 str.append(core::stringw(cam->getPosition().Z));
1022 str += L" Tgt: ";
1023 str.append(core::stringw(cam->getTarget().X));
1024 str += L" ";
1025 str.append(core::stringw(cam->getTarget().Y));
1026 str += L" ";
1027 str.append(core::stringw(cam->getTarget().Z));
1028 postext->setText(str.c_str());
1029
1030 // update the tool dialog
1031 updateToolBox();
1032 }
1033 else
1034 Device->yield();
1035 }
1036
1037 Device->drop();
1038 return 0;
1039}
1040
1041/*
1042**/