diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/examples/09.Meshviewer/main.cpp | 1042 |
1 files changed, 1042 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/examples/09.Meshviewer/main.cpp b/libraries/irrlicht-1.8/examples/09.Meshviewer/main.cpp new file mode 100644 index 0000000..b9dc550 --- /dev/null +++ b/libraries/irrlicht-1.8/examples/09.Meshviewer/main.cpp | |||
@@ -0,0 +1,1042 @@ | |||
1 | /** Example 009 Mesh Viewer | ||
2 | |||
3 | This tutorial show how to create a more complex application with the engine. | ||
4 | We construct a simple mesh viewer using the user interface API and the | ||
5 | scene management of Irrlicht. The tutorial show how to create and use Buttons, | ||
6 | Windows, Toolbars, Menus, ComboBoxes, Tabcontrols, Editboxes, Images, | ||
7 | MessageBoxes, SkyBoxes, and how to parse XML files with the integrated XML | ||
8 | reader of the engine. | ||
9 | |||
10 | We start like in most other tutorials: Include all necessary header files, add | ||
11 | a comment to let the engine be linked with the right .lib file in Visual | ||
12 | Studio, and declare some global variables. We also add two 'using namespace' | ||
13 | statements, so we do not need to write the whole names of all classes. In this | ||
14 | tutorial, we use a lot stuff from the gui namespace. | ||
15 | */ | ||
16 | #include <irrlicht.h> | ||
17 | #include "driverChoice.h" | ||
18 | |||
19 | using namespace irr; | ||
20 | using namespace gui; | ||
21 | |||
22 | #ifdef _MSC_VER | ||
23 | #pragma comment(lib, "Irrlicht.lib") | ||
24 | #endif | ||
25 | |||
26 | |||
27 | /* | ||
28 | Some global variables used later on | ||
29 | */ | ||
30 | IrrlichtDevice *Device = 0; | ||
31 | core::stringc StartUpModelFile; | ||
32 | core::stringw MessageText; | ||
33 | core::stringw Caption; | ||
34 | scene::ISceneNode* Model = 0; | ||
35 | scene::ISceneNode* SkyBox = 0; | ||
36 | bool Octree=false; | ||
37 | bool UseLight=false; | ||
38 | |||
39 | scene::ICameraSceneNode* Camera[2] = {0, 0}; | ||
40 | |||
41 | // Values used to identify individual GUI elements | ||
42 | enum | ||
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 | /* | ||
99 | Toggle between various cameras | ||
100 | */ | ||
101 | void 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 | */ | ||
116 | void 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 | */ | ||
129 | void 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 | /* | ||
150 | Function showAboutText() displays a messagebox with a caption and | ||
151 | a message text. The texts will be stored in the MessageText and Caption | ||
152 | variables at startup. | ||
153 | */ | ||
154 | void 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 | /* | ||
164 | Function loadModel() loads a model and displays it using an | ||
165 | addAnimatedMeshSceneNode and the scene manager. Nothing difficult. It also | ||
166 | displays a short message box, if the model could not be loaded. | ||
167 | */ | ||
168 | void 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 | /* | ||
261 | Function createToolBox() creates a toolbox window. In this simple mesh | ||
262 | viewer, this toolbox only contains a tab control with three edit boxes for | ||
263 | changing the scale of the displayed model. | ||
264 | */ | ||
265 | void 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 | /* | ||
326 | Function updateToolBox() is called each frame to update dynamic information in | ||
327 | the toolbox. | ||
328 | */ | ||
329 | void 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 | |||
355 | void 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 | /* | ||
382 | Function hasModalDialog() checks if we currently have a modal dialog open. | ||
383 | */ | ||
384 | bool 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 | /* | ||
400 | To get all the events sent by the GUI Elements, we need to create an event | ||
401 | receiver. This one is really simple. If an event occurs, it checks the id of | ||
402 | the caller and the event type, and starts an action based on these values. For | ||
403 | example, if a menu item with id GUI_ID_OPEN_MODEL was selected, it opens a file-open-dialog. | ||
404 | */ | ||
405 | class MyEventReceiver : public IEventReceiver | ||
406 | { | ||
407 | public: | ||
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 | /* | ||
722 | Most of the hard work is done. We only need to create the Irrlicht Engine | ||
723 | device and all the buttons, menus and toolbars. We start up the engine as | ||
724 | usual, using createDevice(). To make our application catch events, we set our | ||
725 | eventreceiver as parameter. As you can see, there is also a call to | ||
726 | IrrlichtDevice::setResizeable(). This makes the render window resizeable, which | ||
727 | is quite useful for a mesh viewer. | ||
728 | */ | ||
729 | int 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 | **/ | ||