Visual Servoing Platform  version 3.6.1 under development (2024-04-16)
vpAROgre.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Augmented Reality viewer using Ogre3D.
33  *
34  * Authors:
35  * Bertrand Delabarre
36  *
37 *****************************************************************************/
38 
49 #include <visp3/core/vpConfig.h>
50 
51 #ifdef VISP_HAVE_OGRE
52 
53 #include <visp3/ar/vpAROgre.h>
54 #include <visp3/core/vpIoTools.h>
55 
56 #include <OgreRectangle2D.h>
57 
73 vpAROgre::vpAROgre(const vpCameraParameters &cam, unsigned int width, unsigned int height, const char *resourcePath,
74  const char *pluginsPath)
75  : name("ViSP - Augmented Reality"), mRoot(0), mCamera(0), mSceneMgr(0), mWindow(0), mResourcePath(resourcePath),
76  mPluginsPath(pluginsPath),
77 #ifdef VISP_HAVE_OIS
78  mInputManager(0), mKeyboard(0),
79 #endif
80  keepOn(true), // When created no reason to stop displaying
81  mImageRGBA(), mImage(), mPixelBuffer(), mBackground(nullptr), mBackgroundHeight(0), mBackgroundWidth(0),
82  mWindowHeight(height), mWindowWidth(width), windowHidden(false), mNearClipping(0.001), mFarClipping(200), mcam(cam),
83  mshowConfigDialog(true), mOptionalResourceLocation()
84 {
85 }
86 
116  bool
117 #ifdef VISP_HAVE_OIS
118  bufferedKeys
119 #endif
120  ,
121  bool hidden)
122 {
125 
126  init(
127 #ifdef VISP_HAVE_OIS
128  bufferedKeys,
129 #else
130  false,
131 #endif
132  hidden);
133  // Create the background image which will come from the grabber
134  createBackground(I);
135 }
136 
166  bool
167 #ifdef VISP_HAVE_OIS
168  bufferedKeys
169 #endif
170  ,
171  bool hidden)
172 {
175 
176  init(
177 #ifdef VISP_HAVE_OIS
178  bufferedKeys,
179 #else
180  false,
181 #endif
182  hidden);
183  // Create the background image which will come from the grabber
184  createBackground(I);
185 }
186 
211 void vpAROgre::init(bool
212 #ifdef VISP_HAVE_OIS
213  bufferedKeys
214 #endif
215  ,
216  bool hidden)
217 {
218  // Create the root
219  // mPluginsPath may contain more than one folder location separated by ";"
220  bool pluginsFileExists = false;
221  std::string pluginFile;
222  std::vector<std::string> plugingsPaths = vpIoTools::splitChain(std::string(mPluginsPath), std::string(";"));
223  for (size_t i = 0; i < plugingsPaths.size(); i++) {
224 #if defined(NDEBUG) || !defined(_WIN32)
225  pluginFile = plugingsPaths[i] + "/plugins.cfg";
226 #else
227  pluginFile = plugingsPaths[i] + "/plugins_d.cfg";
228 #endif
229 
230  if (vpIoTools::checkFilename(pluginFile)) {
231  pluginsFileExists = true;
232  break;
233  }
234  }
235  if (!pluginsFileExists) {
236  std::string errorMsg = std::string("Error: the requested plugins file \"")
237 #if defined(NDEBUG) || !defined(_WIN32)
238  + std::string("plugins.cfg")
239 #else
240  + std::string("plugins_d.cfg")
241 #endif
242  + std::string("\" doesn't exist in ") + std::string(mPluginsPath);
243  std::cout << errorMsg << std::endl;
244 
245  throw(vpException(vpException::ioError, errorMsg));
246  }
247  std::cout << "######################### Load plugin file: " << pluginFile << std::endl;
248 
249  if (Ogre::Root::getSingletonPtr() == nullptr) {
250  mRoot = new Ogre::Root(pluginFile, "ogre.cfg", "Ogre.log");
251  } else {
252  mRoot = Ogre::Root::getSingletonPtr();
253  }
254 
255  // Load resource paths from config file
256 
257  // File format is:
258  // [ResourceGroupName]
259  // ArchiveType=Path
260  // .. repeat
261  // For example:
262  // [General]
263  // FileSystem=media/
264  // Zip=packages/level1.zip
265 
266  // mResourcePath may contain more than one folder location separated by ";"
267  bool resourcesFileExists = false;
268  std::string resourceFile;
269  std::vector<std::string> resourcesPaths = vpIoTools::splitChain(std::string(mResourcePath), std::string(";"));
270  for (size_t i = 0; i < resourcesPaths.size(); i++) {
271  resourceFile = resourcesPaths[i] + "/resources.cfg";
272  if (vpIoTools::checkFilename(resourceFile)) {
273  resourcesFileExists = true;
274  break;
275  }
276  }
277  if (!resourcesFileExists) {
278  std::string errorMsg = std::string("Error: the requested resource file \"resources.cfg\"") +
279  std::string("doesn't exist in ") + std::string(mResourcePath);
280 
281  std::cout << errorMsg << std::endl;
282 
283  throw(vpException(vpException::ioError, errorMsg));
284  }
285  std::cout << "######################### Load resource file: " << resourceFile << std::endl;
286  Ogre::ConfigFile cf;
287  cf.load(resourceFile);
288 
289  // Go through all sections & settings in the file
290  Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
291 
292  Ogre::String secName, typeName, archName;
293  while (seci.hasMoreElements()) {
294  secName = seci.peekNextKey();
295  Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
296  Ogre::ConfigFile::SettingsMultiMap::iterator i;
297  for (i = settings->begin(); i != settings->end(); ++i) {
298  typeName = i->first;
299  archName = i->second;
300  Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
301  }
302  }
303  std::cout << "##################### add resources" << std::endl;
304  // Add Optional resources (given by the user).
305  for (std::list<std::string>::const_iterator iter = mOptionalResourceLocation.begin();
306  iter != mOptionalResourceLocation.end(); ++iter) {
307  Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
308  *iter, "FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
309  }
310 
311  // Create the window
312  bool canInit = true;
313  if (mshowConfigDialog) {
314  mRoot->restoreConfig();
315  if (!mRoot->showConfigDialog()) {
316  canInit = false;
317  }
318  } else {
319  if (!mRoot->restoreConfig()) {
320  canInit = false;
321  }
322  }
323 
324  if (!mRoot->isInitialised()) {
325  if (!canInit) { // We set the default renderer system
326  const Ogre::RenderSystemList &lRenderSystemList = mRoot->getAvailableRenderers();
327  if (lRenderSystemList.size() == 0) {
328  throw "ConfigDialog aborted"; // Exit the application on cancel
329  }
330 
331  Ogre::RenderSystem *lRenderSystem = lRenderSystemList.at(0);
332  std::cout << "Using " << lRenderSystem->getName() << " as renderer." << std::endl;
333  mRoot->setRenderSystem(lRenderSystem);
334  }
335 
336  mRoot->initialise(false);
337  }
338 
339  bool fullscreen = false;
340  Ogre::NameValuePairList misc;
341  Ogre::ConfigOptionMap config = mRoot->getRenderSystem()->getConfigOptions();
342  Ogre::ConfigOptionMap::const_iterator it = config.begin();
343 
344  while (it != config.end()) {
345  Ogre::String leftconf = (*it).first;
346  Ogre::String rightconf = (*it).second.currentValue;
347 
348  if (leftconf == "Video Mode") {
349  if (canInit) {
350  std::stringstream ss(rightconf.c_str());
351  std::string dummy;
352  ss >> mWindowWidth >> dummy >> mWindowHeight;
353  if (ss.fail()) {
354  std::cout << "Cannot read Ogre video mode" << std::endl;
355  }
356  } else if (mWindowWidth == 0 && mWindowHeight == 0) {
359  }
360  } else if (leftconf == "Full Screen") {
361  if (canInit && (rightconf == "Yes")) {
362  fullscreen = true;
363  }
364  } else {
365  misc[leftconf] = rightconf;
366  }
367 
368  ++it;
369  }
370 
371  // With Ogre version >= 1.8.1 we hide the window
372  if (hidden) {
373 #if (OGRE_VERSION >= (1 << 16 | 8 << 8 | 1))
374  misc["hidden"] = "true";
375  windowHidden = true;
376 #endif
377  }
378  mWindow = mRoot->createRenderWindow(name, mWindowWidth, mWindowHeight, fullscreen, &misc);
379 
380  // Initialise resources
381  Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
382  //-----------------------------------------------------
383  // 4 Create the SceneManager
384  //
385  // ST_GENERIC = octree
386  // ST_EXTERIOR_CLOSE = simple terrain
387  // ST_EXTERIOR_FAR = nature terrain (depreciated)
388  // ST_EXTERIOR_REAL_FAR = paging landscape
389  // ST_INTERIOR = Quake3 BSP
390  //-----------------------------------------------------
391 
392  mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC);
393 
394  // Create the camera
395  createCamera();
396 
397  // Create a viewport
398  Ogre::Viewport *viewPort = mWindow->addViewport(mCamera);
399  // Ogre::Viewport* viewPort = mCamera->getViewport();
400  viewPort->setClearEveryFrame(true);
401  // Set the projection parameters to match the camera intrinsic parameters
403 
404  // Create the 3D scene
405  createScene();
406 
407  // Initialise and register event handlers
408  mRoot->addFrameListener(this);
409 
410  // Register as a Window listener
411  Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
412 
413 #ifdef VISP_HAVE_OIS
414  // Initialise OIS
415  Ogre::LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
416  OIS::ParamList pl;
417 
418  size_t windowHnd = 0;
419  std::ostringstream windowHndStr;
420  // Initialise window
421  mWindow->getCustomAttribute("WINDOW", &windowHnd);
422  windowHndStr << windowHnd;
423  pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
424 // Let the user use the keyboard elsewhere
425 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
426  pl.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
427 #endif
428 
429  mInputManager = OIS::InputManager::createInputSystem(pl);
430 
431  // Create all devices
432  // Here we only consider the keyboard input
433  mKeyboard = static_cast<OIS::Keyboard *>(mInputManager->createInputObject(OIS::OISKeyboard, bufferedKeys));
434  if (!bufferedKeys) {
435  mKeyboard->setEventCallback(this);
436  }
437 #endif
438 
439  // Initialise a render to texture to be able to retrieve a screenshot
440  Ogre::TexturePtr Texture = Ogre::TextureManager::getSingleton().createManual(
441  "rtf", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, mWindow->getWidth(),
442  mWindow->getHeight(), 0, Ogre::PF_R8G8B8A8, Ogre::TU_RENDERTARGET);
443 
444  // Ogre::TexturePtr Texture =
445  // Ogre::TextureManager::getSingleton().createManual("rtf",
446  // Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,Ogre::TEX_TYPE_2D,
447  // 640,480, 0, Ogre::PF_R8G8B8A8,
448  // Ogre::TU_RENDERTARGET);
449  Ogre::RenderTexture *RTarget = Texture->getBuffer()->getRenderTarget();
450  /*Ogre::Viewport* Viewport =*/RTarget->addViewport(mCamera);
451  RTarget->getViewport(0)->setClearEveryFrame(true);
452  RTarget->getViewport(0)->setOverlaysEnabled(false);
453 }
454 
459 {
460  // Destroy 3D scene
461  destroyScene();
462  // Close OIS
463  closeOIS();
464 
465  if (mWindow) {
466  Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this);
468  }
469 
470  // Delete root
471  if (Ogre::Root::getSingletonPtr() && !Ogre::Root::getSingletonPtr()->getSceneManagerIterator().hasMoreElements() &&
472  mRoot) {
473  delete mRoot;
474  }
475  mRoot = 0;
476 }
477 
483 bool vpAROgre::stopTest(const Ogre::FrameEvent &evt)
484 {
485  // Always keep this part
486  if (keepOn) {
487  return updateScene(evt);
488  } else {
489  return keepOn;
490  }
491 }
492 
502 bool vpAROgre::frameStarted(const Ogre::FrameEvent &evt)
503 {
504  // custom method telling what to do at the beginning of each frame
505  bool result = customframeStarted(evt);
506 
507  // Listen to the window
508  Ogre::WindowEventUtilities::messagePump();
509  processInputEvent(evt);
510 
511  // See if we have to stop rendering
512  if (result)
513  return stopTest(evt);
514  else
515  return result;
516 }
517 
524 bool vpAROgre::frameEnded(const Ogre::FrameEvent &evt)
525 {
526  // custom method telling what to do at the end of each frame
527  bool result = customframeEnded(evt);
528 
529  // See if we have to stop rendering
530  if (result)
531  return stopTest(evt);
532  else
533  return result;
534 }
535 
544 bool vpAROgre::customframeStarted(const Ogre::FrameEvent & /*evt*/)
545 {
546  // See if window was closed
547  if (mWindow->isClosed())
548  return false;
549 
550 #ifdef VISP_HAVE_OIS
551  // Get keyboard input
552  mKeyboard->capture();
553  if (mKeyboard->isKeyDown(OIS::KC_ESCAPE))
554  return false;
555 #endif
556  return true;
557 }
558 
564 bool vpAROgre::customframeEnded(const Ogre::FrameEvent & /*evt*/) { return true; }
565 
576 void vpAROgre::windowClosed(Ogre::RenderWindow *rw)
577 {
578  // Only close for window that created OIS (the main window in these demos)
579  if (rw == mWindow)
580  closeOIS();
581 }
582 
589 {
590  // Update the background to match the situation
592 
593  // Update the camera parameters to match the grabbed image
595 
596  // Display on Ogre Window
597  return mRoot->renderOneFrame();
598 }
599 
606 {
607  // Update the background to match the situation
609 
610  // Update the camera parameters to match the grabbed image
612 
613  // Display on Ogre Window
614  return mRoot->renderOneFrame();
615 }
616 
623 {
624  // Display on Ogre Window
625  if (renderOneFrame(I, cMw)) {
626  mWindow->update();
627  keepOn = true;
628  } else
629  keepOn = false;
630 }
631 
638 {
639  // Display on Ogre Window
640  if (renderOneFrame(I, cMw)) {
641  mWindow->update();
642  keepOn = true;
643  } else
644  keepOn = false;
645 }
646 
651 bool vpAROgre::continueRendering(void) { return keepOn; }
652 
656 void vpAROgre::setCameraParameters(const vpCameraParameters &cameraP) { mcam = cameraP; }
657 
663 void vpAROgre::load(const std::string &entityName, const std::string &model)
664 {
665  Ogre::Entity *newEntity = mSceneMgr->createEntity(entityName, model);
666  Ogre::SceneNode *newNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(entityName);
667  newNode->attachObject(newEntity);
668 }
669 
676 void vpAROgre::setPosition(const std::string &sceneName, const vpTranslationVector &wTo)
677 {
678  // Reset the position
679  Ogre::SceneNode *node = mSceneMgr->getSceneNode(sceneName);
680  node->setPosition((Ogre::Real)wTo[0], (Ogre::Real)wTo[1], (Ogre::Real)wTo[2]);
681 }
682 
688 vpTranslationVector vpAROgre::getPosition(const std::string &sceneName) const
689 {
690  Ogre::Vector3 translation = mSceneMgr->getSceneNode(sceneName)->getPosition();
691  return vpTranslationVector((Ogre::Real)translation[0], (Ogre::Real)translation[1], (Ogre::Real)translation[2]);
692 }
693 
699 void vpAROgre::setRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
700 {
701  // Get the node in its original position
702  mSceneMgr->getSceneNode(sceneName)->resetOrientation();
703  // Apply the new rotation
704  Ogre::Matrix3 rotationOgre = Ogre::Matrix3((Ogre::Real)wRo[0][0], (Ogre::Real)wRo[0][1], (Ogre::Real)wRo[0][2],
705  (Ogre::Real)wRo[1][0], (Ogre::Real)wRo[1][1], (Ogre::Real)wRo[1][2],
706  (Ogre::Real)wRo[2][0], (Ogre::Real)wRo[2][1], (Ogre::Real)wRo[2][2]);
707  Ogre::Quaternion q(rotationOgre);
708  mSceneMgr->getSceneNode(sceneName)->rotate(q);
709 }
710 
716 void vpAROgre::addRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
717 {
718  // Apply the new rotation
719  Ogre::Matrix3 rotationOgre = Ogre::Matrix3((Ogre::Real)wRo[0][0], (Ogre::Real)wRo[0][1], (Ogre::Real)wRo[0][2],
720  (Ogre::Real)wRo[1][0], (Ogre::Real)wRo[1][1], (Ogre::Real)wRo[1][2],
721  (Ogre::Real)wRo[2][0], (Ogre::Real)wRo[2][1], (Ogre::Real)wRo[2][2]);
722  Ogre::Quaternion q(rotationOgre);
723  mSceneMgr->getSceneNode(sceneName)->rotate(q);
724 }
725 
734 void vpAROgre::setPosition(const std::string &sceneName, const vpHomogeneousMatrix &wMo)
735 {
736  // Extract the position and orientation data
737  vpRotationMatrix rotations;
738  vpTranslationVector translation;
739  wMo.extract(rotations);
740  wMo.extract(translation);
741  // Apply them to the node
742  setPosition(sceneName, translation);
743  setRotation(sceneName, rotations);
744 }
745 
751 void vpAROgre::setVisibility(const std::string &sceneName, bool isVisible)
752 {
753  mSceneMgr->getSceneNode(sceneName)->setVisible(isVisible);
754 }
755 
763 void vpAROgre::setScale(const std::string &sceneName, float factorx, float factory, float factorz)
764 {
765  // Reset the scale to its original value
766  mSceneMgr->getSceneNode(sceneName)->scale(Ogre::Vector3(1, 1, 1) / mSceneMgr->getSceneNode(sceneName)->getScale());
767  // Apply the new scale
768  mSceneMgr->getSceneNode(sceneName)->scale(Ogre::Vector3(factorx, factory, factorz));
769 }
770 
774 void vpAROgre::createCamera(void) { mCamera = mSceneMgr->createCamera("Camera"); }
775 
782 void vpAROgre::createBackground(vpImage<unsigned char> & /* I */)
783 {
784  // Create a rectangle to show the incoming images from the camera
785  mBackground = new Ogre::Rectangle2D(true); // true = textured
786  mBackground->setCorners(-1.0, 1.0, 1.0, -1.0); // Spread all over the window
787  mBackground->setBoundingBox(Ogre::AxisAlignedBox(-100000.0 * Ogre::Vector3::UNIT_SCALE,
788  100000.0 * Ogre::Vector3::UNIT_SCALE)); // To be shown everywhere
789 
790  // Texture options
791  Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_NONE);
792  Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(1);
793 
794  // Dynamic texture
795  // If we are using opengl we can boost a little bit performances with a
796  // dynamic texture
797  if (mRoot->getRenderSystem()->getName() == "OpenGL Rendering Subsystem") {
798  Ogre::TextureManager::getSingleton().createManual(
799  "BackgroundTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
800  mBackgroundWidth, // width
801  mBackgroundHeight, // height
802  0, // num of mip maps
803  Ogre::PF_BYTE_L, Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
804  } else {
805  Ogre::TextureManager::getSingleton().createManual(
806  "BackgroundTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
807  mBackgroundWidth, // width
808  mBackgroundHeight, // height
809  0, // num of mip maps
810  Ogre::PF_BYTE_L, Ogre::TU_DEFAULT);
811  }
812 
813  // Pointer to the dynamic texture
814  Ogre::TexturePtr dynTexPtr = Ogre::TextureManager::getSingleton().getByName("BackgroundTexture");
815  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
816  // .dynamicCast<Ogre::Texture>();// Get the pixel buffer
817  //#else
818  // ;
819  //#endif
820  mPixelBuffer = dynTexPtr->getBuffer();
821 
822  // Material to apply the texture to the background
823  Ogre::MaterialPtr Backgroundmaterial = Ogre::MaterialManager::getSingleton().create(
824  "BackgroundMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
825  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
826  // .dynamicCast<Ogre::Material>();
827  //#else
828  // ;
829  //#endif
830  Ogre::Technique *Backgroundtechnique = Backgroundmaterial->createTechnique();
831  Backgroundtechnique->createPass();
832  Backgroundmaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
833  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); // Background
834  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); // Background
835  Backgroundmaterial->getTechnique(0)->getPass(0)->createTextureUnitState("BackgroundTexture");
836  mBackground->setMaterial("BackgroundMaterial"); // Attach the material to the rectangle
837  mBackground->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND); // To be rendered in Background
838 
839  // Add the background to the Scene Graph so it will be rendered
840  Ogre::SceneNode *BackgroundNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("BackgoundNode");
841  BackgroundNode->attachObject(mBackground);
842 }
843 
850 void vpAROgre::createBackground(vpImage<vpRGBa> & /* I */)
851 {
852  // Create a rectangle to show the incoming images from the camera
853  mBackground = new Ogre::Rectangle2D(true); // true = textured
854  mBackground->setCorners(-1.0, 1.0, 1.0, -1.0); // Spread all over the window
855  mBackground->setBoundingBox(Ogre::AxisAlignedBox(-100000.0 * Ogre::Vector3::UNIT_SCALE,
856  100000.0 * Ogre::Vector3::UNIT_SCALE)); // To be shown everywhere
857 
858  // Texture options
859  Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_NONE);
860  Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(1);
861 
862  // Dynamic texture
863  // If we are using opengl we can boost a little bit performances with a
864  // dynamic texture
865  if (mRoot->getRenderSystem()->getName() == "OpenGL Rendering Subsystem") {
866  Ogre::TextureManager::getSingleton().createManual(
867  "BackgroundTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
868  mBackgroundWidth, // width
869  mBackgroundHeight, // height
870  0, // num of mip maps
871  // Ogre::PF_BYTE_RGBA,
872  Ogre::PF_BYTE_BGRA, Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
873  } else { // As that texture does not seem to work properly with direct3D we
874  // use a default texture
875  Ogre::TextureManager::getSingleton().createManual(
876  "BackgroundTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
877  mBackgroundWidth, // width
878  mBackgroundHeight, // height
879  0, // num of mip maps
880  // Ogre::PF_BYTE_RGBA,
881  Ogre::PF_BYTE_BGRA, Ogre::TU_DEFAULT);
882  }
883 
884  // Pointer to the dynamic texture
885  Ogre::TexturePtr dynTexPtr = Ogre::TextureManager::getSingleton().getByName("BackgroundTexture");
886  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
887  // .dynamicCast<Ogre::Texture>();// Get the pixel buffer
888  //#else
889  // ;
890  //#endif
891 
892  // Get the pixel buffer
893  mPixelBuffer = dynTexPtr->getBuffer();
894 
895  // Material to apply the texture to the background
896  Ogre::MaterialPtr Backgroundmaterial = Ogre::MaterialManager::getSingleton().create(
897  "BackgroundMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
898  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
899  // .dynamicCast<Ogre::Material>();
900  //#else
901  // ;
902  //#endif
903  Ogre::Technique *Backgroundtechnique = Backgroundmaterial->createTechnique();
904  Backgroundtechnique->createPass();
905  Backgroundmaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
906  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); // Background
907  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); // Background
908  Backgroundmaterial->getTechnique(0)->getPass(0)->createTextureUnitState("BackgroundTexture");
909  mBackground->setMaterial("BackgroundMaterial"); // Attach the material to the rectangle
910  mBackground->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND); // To be rendered in Background
911 
912  // Add the background to the Scene Graph so it will be rendered
913  Ogre::SceneNode *BackgroundNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("BackgoundNode");
914  BackgroundNode->attachObject(mBackground);
915 }
916 
925 {
926 #ifdef VISP_HAVE_OIS
927  if (mInputManager) {
928  mInputManager->destroyInputObject(mKeyboard);
929 
930  OIS::InputManager::destroyInputSystem(mInputManager);
931  mInputManager = 0;
932  }
933 #endif
934 }
935 
939 // Note: equation taken from:
940 // http://strawlab.org/2011/11/05/augmented-reality-with-OpenGL/
942 {
943  if (mCamera != 0) {
944  Ogre::Real f, n, f_m_n, f_p_n, px, py, u0, v0;
945  f = (Ogre::Real)(mFarClipping); // Far clip distance
946  n = (Ogre::Real)(mNearClipping); // Near clip distance
947  f_m_n = (Ogre::Real)(f - n);
948  f_p_n = (Ogre::Real)(f + n);
949  px = (Ogre::Real)mcam.get_px();
950  py = (Ogre::Real)mcam.get_py();
951  u0 = (Ogre::Real)mcam.get_u0();
952  v0 = (Ogre::Real)mcam.get_v0();
953  Ogre::Matrix4 Projection = Ogre::Matrix4(
954  (Ogre::Real)(2.0 * px / mBackgroundWidth), 0, (Ogre::Real)(1.0 - 2.0 * (u0 / mBackgroundWidth)), 0, 0,
955  (Ogre::Real)(2.0 * py / mBackgroundHeight), (Ogre::Real)(-1.0 + 2.0 * (v0 / mBackgroundHeight)), 0, 0, 0,
956  (Ogre::Real)(-1.0 * f_p_n / f_m_n), (Ogre::Real)(-2.0 * f * n / f_m_n), 0, 0, -1.0, 0);
957  mCamera->setCustomProjectionMatrix(true, Projection);
958  }
959 }
960 
965 {
966  // Inspired from Ogre wiki :
967  // http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures Lock the pixel
968  // buffer and get a pixel box. HBL_DISCARD is to use for best performance
969  // than HBL_NORMAL
970  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); // Lock the buffer
971  const Ogre::PixelBox &pixelBox = mPixelBuffer->getCurrentLock();
972  // Buffer data
973  Ogre::uint8 *pDest = static_cast<Ogre::uint8 *>(pixelBox.data);
974  // Fill in the data in the grey level texture
975  memcpy(pDest, I.bitmap, mBackgroundHeight * mBackgroundWidth);
976 
977  // Unlock the pixel buffer
978  mPixelBuffer->unlock();
979 }
980 
985 {
986  // Inspired from Ogre wiki :
987  // http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures Lock the pixel
988  // buffer and get a pixel box. HBL_DISCARD is to use for best performance
989  // than HBL_NORMAL
990  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); // Lock the buffer
991  const Ogre::PixelBox &pixelBox = mPixelBuffer->getCurrentLock();
992  // Buffer data
993  Ogre::uint8 *pDest = static_cast<Ogre::uint8 *>(pixelBox.data);
994 // Fill in the data in the grey level texture
995 #if 1 // if texture in BGRa format
996  for (unsigned int i = 0; i < mBackgroundHeight; i++) {
997  for (unsigned int j = 0; j < mBackgroundWidth; j++) {
998  // Color Image
999  // *pDest++=I[i][mBackgroundWidth-j].B; // Blue component
1000  // *pDest++=I[i][mBackgroundWidth-j].G; // Green component
1001  // *pDest++=I[i][mBackgroundWidth-j].R; // Red component
1002 
1003  *pDest++ = I[i][j].B; // Blue component
1004  *pDest++ = I[i][j].G; // Green component
1005  *pDest++ = I[i][j].R; // Red component
1006 
1007  *pDest++ = 255; // Alpha component
1008  }
1009  }
1010 #else // if texture in RGBa format which is the format of the input image
1011  memcpy(pDest, I.bitmap, mBackgroundHeight * mBackgroundWidth * sizeof(vpRGBa));
1012 #endif
1013 
1014  // Unlock the pixel buffer
1015  mPixelBuffer->unlock();
1016 }
1017 
1022 {
1023  // The matrix is given to Ogre with some changes to fit with the world
1024  // projection
1025  Ogre::Matrix4 ModelView
1026  // = Ogre::Matrix4( (Ogre::Real)-cMo[0][0], (Ogre::Real)-cMo[0][1],
1027  // (Ogre::Real)-cMo[0][2], (Ogre::Real)-cMo[0][3],
1028  = Ogre::Matrix4((Ogre::Real)cMw[0][0], (Ogre::Real)cMw[0][1], (Ogre::Real)cMw[0][2], (Ogre::Real)cMw[0][3],
1029  (Ogre::Real)-cMw[1][0], (Ogre::Real)-cMw[1][1], (Ogre::Real)-cMw[1][2], (Ogre::Real)-cMw[1][3],
1030  (Ogre::Real)-cMw[2][0], (Ogre::Real)-cMw[2][1], (Ogre::Real)-cMw[2][2], (Ogre::Real)-cMw[2][3],
1031  (Ogre::Real)0, (Ogre::Real)0, (Ogre::Real)0, (Ogre::Real)1);
1032  mCamera->setCustomViewMatrix(true, ModelView);
1033 }
1034 
1042 {
1044  Ogre::TexturePtr dynTexPtr = Ogre::TextureManager::getSingleton().getByName("rtf");
1045  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
1046  // .dynamicCast<Ogre::Texture>();
1047  //#else
1048  // ;
1049  //#endif
1050  Ogre::RenderTexture *RTarget = dynTexPtr->getBuffer()->getRenderTarget();
1051  mWindow->update();
1052  RTarget->update();
1053  if (I.getHeight() != mWindow->getHeight() || I.getWidth() != mWindow->getWidth()) {
1054  I.resize(mWindow->getHeight(), mWindow->getWidth());
1055  }
1056  mPixelBuffer = dynTexPtr->getBuffer();
1057  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
1058  const Ogre::PixelBox &pixelBox = mPixelBuffer->getCurrentLock();
1059  dynTexPtr->getBuffer()->blitToMemory(pixelBox);
1060  Ogre::uint8 *pDest = static_cast<Ogre::uint8 *>(pixelBox.data);
1061 #if 1 // if texture in BGRa format
1062  for (unsigned int i = 0; i < I.getHeight(); i++) {
1063  for (unsigned int j = 0; j < I.getWidth(); j++) {
1064  // Color Image
1065  I[i][j].B = *pDest++; // Blue component
1066  I[i][j].G = *pDest++; // Green component
1067  I[i][j].R = *pDest++; // Red component
1068  I[i][j].A = *pDest++; // Alpha component
1069  }
1070  }
1071 #else // if texture in RGBa format which is the format of the input image
1072  memcpy(I.bitmap, pDest, I.getHeight() * I.getWidth() * sizeof(vpRGBa));
1073 #endif
1074 
1075  // Unlock the pixel buffer
1076  mPixelBuffer->unlock();
1077 }
1078 
1079 #elif !defined(VISP_BUILD_SHARED_LIBS)
1080 // Work around to avoid warning: libvisp_ar.a(vpAROgre.cpp.o) has no symbols
1081 void dummy_vpAROgre(){};
1082 #endif
OIS::InputManager * mInputManager
Definition: vpAROgre.h:366
void setCameraParameters(const vpCameraParameters &cameraP)
Definition: vpAROgre.cpp:656
bool continueRendering(void)
Definition: vpAROgre.cpp:651
virtual bool updateScene(const Ogre::FrameEvent &)
Definition: vpAROgre.h:308
virtual bool customframeEnded(const Ogre::FrameEvent &evt)
Definition: vpAROgre.cpp:564
OIS::Keyboard * mKeyboard
Definition: vpAROgre.h:367
bool keepOn
Definition: vpAROgre.h:371
virtual bool processInputEvent(const Ogre::FrameEvent &)
Definition: vpAROgre.h:315
void addRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
Definition: vpAROgre.cpp:716
unsigned int mBackgroundWidth
Definition: vpAROgre.h:378
vpCameraParameters mcam
Definition: vpAROgre.h:386
void getRenderingOutput(vpImage< vpRGBa > &I, const vpHomogeneousMatrix &cMo)
Definition: vpAROgre.cpp:1041
vpAROgre(const vpCameraParameters &cam=vpCameraParameters(), unsigned int width=0, unsigned int height=0, const char *resourcePath=VISP_HAVE_OGRE_RESOURCES_PATH, const char *pluginsPath=VISP_HAVE_OGRE_PLUGINS_PATH)
Definition: vpAROgre.cpp:73
bool windowHidden
Definition: vpAROgre.h:381
double mNearClipping
Definition: vpAROgre.h:384
Ogre::Root * mRoot
Definition: vpAROgre.h:357
Ogre::String name
Definition: vpAROgre.h:354
virtual bool destroyScene(void)
Definition: vpAROgre.h:322
virtual void updateCameraProjection(void)
Definition: vpAROgre.cpp:941
Ogre::Camera * mCamera
Definition: vpAROgre.h:358
void setRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
Definition: vpAROgre.cpp:699
virtual void closeOIS(void)
Definition: vpAROgre.cpp:924
unsigned int mBackgroundHeight
Definition: vpAROgre.h:377
virtual void windowClosed(Ogre::RenderWindow *rw)
Definition: vpAROgre.cpp:576
virtual bool customframeStarted(const Ogre::FrameEvent &evt)
Definition: vpAROgre.cpp:544
Ogre::String mPluginsPath
Definition: vpAROgre.h:362
Ogre::Rectangle2D * mBackground
Definition: vpAROgre.h:376
double mFarClipping
Definition: vpAROgre.h:385
vpTranslationVector getPosition(const std::string &sceneName) const
Definition: vpAROgre.cpp:688
virtual void createScene(void)
Definition: vpAROgre.h:299
unsigned int mWindowHeight
Definition: vpAROgre.h:379
void setVisibility(const std::string &sceneName, bool isVisible)
Definition: vpAROgre.cpp:751
virtual void init(vpImage< unsigned char > &I, bool bufferedKeys=false, bool hidden=false)
Definition: vpAROgre.cpp:115
virtual void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMw)
Definition: vpAROgre.cpp:622
bool renderOneFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMw)
Definition: vpAROgre.cpp:588
void load(const std::string &entityName, const std::string &model)
Definition: vpAROgre.cpp:663
virtual void createCamera(void)
Definition: vpAROgre.cpp:774
virtual void updateCameraParameters(const vpHomogeneousMatrix &cMo)
Definition: vpAROgre.cpp:1021
std::list< std::string > mOptionalResourceLocation
Definition: vpAROgre.h:391
Ogre::SceneManager * mSceneMgr
Definition: vpAROgre.h:359
Ogre::HardwarePixelBufferSharedPtr mPixelBuffer
Definition: vpAROgre.h:375
virtual ~vpAROgre(void)
Definition: vpAROgre.cpp:458
bool mshowConfigDialog
Definition: vpAROgre.h:388
Ogre::String mResourcePath
Definition: vpAROgre.h:361
void setPosition(const std::string &sceneName, const vpTranslationVector &wTo)
Definition: vpAROgre.cpp:676
Ogre::RenderWindow * mWindow
Definition: vpAROgre.h:360
unsigned int mWindowWidth
Definition: vpAROgre.h:380
virtual void updateBackgroundTexture(const vpImage< unsigned char > &I)
Definition: vpAROgre.cpp:964
void setScale(const std::string &sceneName, float factorx, float factory, float factorz)
Definition: vpAROgre.cpp:763
Generic class defining intrinsic camera parameters.
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ ioError
I/O error.
Definition: vpException.h:79
Implementation of an homogeneous matrix and operations on such kind of matrices.
void extract(vpRotationMatrix &R) const
unsigned int getWidth() const
Definition: vpImage.h:245
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:783
Type * bitmap
points toward the bitmap
Definition: vpImage.h:139
unsigned int getHeight() const
Definition: vpImage.h:184
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:2386
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:1213
Definition: vpRGBa.h:61
Implementation of a rotation matrix and operations on such kind of matrices.
Class that consider the case of a translation vector.