Visual Servoing Platform  version 3.1.0
vpAROgre.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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 http://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(NULL), mBackgroundHeight(0), mBackgroundWidth(0),
82  mWindowHeight(height), mWindowWidth(width), windowHidden(false), mNearClipping(0.001), mFarClipping(200), mcam(cam),
83  mshowConfigDialog(true), mOptionnalResourceLocation()
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() == NULL)
250  mRoot = new Ogre::Root(pluginFile, "ogre.cfg", "Ogre.log");
251  else
252  mRoot = Ogre::Root::getSingletonPtr();
253 
254  // Load resource paths from config file
255 
256  // File format is:
257  // [ResourceGroupName]
258  // ArchiveType=Path
259  // .. repeat
260  // For example:
261  // [General]
262  // FileSystem=media/
263  // Zip=packages/level1.zip
264 
265  // mResourcePath may contain more than one folder location separated by ";"
266  bool resourcesFileExists = false;
267  std::string resourceFile;
268  std::vector<std::string> resourcesPaths = vpIoTools::splitChain(std::string(mResourcePath), std::string(";"));
269  for (size_t i = 0; i < resourcesPaths.size(); i++) {
270  resourceFile = resourcesPaths[i] + "/resources.cfg";
271  if (vpIoTools::checkFilename(resourceFile)) {
272  resourcesFileExists = true;
273  break;
274  }
275  }
276  if (!resourcesFileExists) {
277  std::string errorMsg = std::string("Error: the requested resource file \"resources.cfg\"") +
278  std::string("doesn't exist in ") + std::string(mResourcePath);
279 
280  std::cout << errorMsg << std::endl;
281 
282  throw(vpException(vpException::ioError, errorMsg));
283  }
284  std::cout << "######################### Load resource file: " << resourceFile << std::endl;
285  Ogre::ConfigFile cf;
286  cf.load(resourceFile);
287 
288  // Go through all sections & settings in the file
289  Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
290 
291  Ogre::String secName, typeName, archName;
292  while (seci.hasMoreElements()) {
293  secName = seci.peekNextKey();
294  Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
295  Ogre::ConfigFile::SettingsMultiMap::iterator i;
296  for (i = settings->begin(); i != settings->end(); ++i) {
297  typeName = i->first;
298  archName = i->second;
299  Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
300  }
301  }
302  std::cout << "##################### add resources" << std::endl;
303  // Add optionnal resources (given by the user).
304  for (std::list<std::string>::const_iterator iter = mOptionnalResourceLocation.begin();
305  iter != mOptionnalResourceLocation.end(); ++iter) {
306  Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
307  *iter, "FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
308  }
309 
310  // Create the window
311  bool canInit = true;
312  if (mshowConfigDialog) {
313  mRoot->restoreConfig();
314  if (!mRoot->showConfigDialog())
315  canInit = false;
316  } else {
317  if (!mRoot->restoreConfig())
318  canInit = false;
319  }
320 
321  if (!mRoot->isInitialised()) {
322  if (!canInit) { // We set the default renderer system
323  const Ogre::RenderSystemList &lRenderSystemList = mRoot->getAvailableRenderers();
324  if (lRenderSystemList.size() == 0)
325  throw "ConfigDialog aborted"; // Exit the application on cancel
326 
327  Ogre::RenderSystem *lRenderSystem = lRenderSystemList.at(0);
328  std::cout << "Using " << lRenderSystem->getName() << " as renderer." << std::endl;
329  mRoot->setRenderSystem(lRenderSystem);
330  }
331 
332  mRoot->initialise(false);
333  }
334 
335  bool fullscreen = false;
336  Ogre::NameValuePairList misc;
337  Ogre::ConfigOptionMap config = mRoot->getRenderSystem()->getConfigOptions();
338  Ogre::ConfigOptionMap::const_iterator it = config.begin();
339 
340  while (it != config.end()) {
341  Ogre::String leftconf = (*it).first;
342  Ogre::String rightconf = (*it).second.currentValue;
343 
344  if (leftconf == "Video Mode") {
345  if (canInit) {
346  std::stringstream ss(rightconf.c_str());
347  std::string dummy;
348  ss >> mWindowWidth >> dummy >> mWindowHeight;
349  if (ss.fail())
350  std::cout << "Cannot read Ogre video mode" << std::endl;
351  } else {
352  if (mWindowWidth == 0 && mWindowHeight == 0) {
355  }
356  }
357  } else if (leftconf == "Full Screen") {
358  if (canInit) {
359  if (rightconf == "Yes")
360  fullscreen = true;
361  }
362  } else
363  misc[leftconf] = rightconf;
364 
365  ++it;
366  }
367 
368  // With Ogre version >= 1.8.1 we hide the window
369  if (hidden) {
370 #if (OGRE_VERSION >= (1 << 16 | 8 << 8 | 1))
371  misc["hidden"] = "true";
372  windowHidden = true;
373 #endif
374  }
375  mWindow = mRoot->createRenderWindow(name, mWindowWidth, mWindowHeight, fullscreen, &misc);
376 
377  // Initialise resources
378  Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
379  //-----------------------------------------------------
380  // 4 Create the SceneManager
381  //
382  // ST_GENERIC = octree
383  // ST_EXTERIOR_CLOSE = simple terrain
384  // ST_EXTERIOR_FAR = nature terrain (depreciated)
385  // ST_EXTERIOR_REAL_FAR = paging landscape
386  // ST_INTERIOR = Quake3 BSP
387  //-----------------------------------------------------
388 
389  mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC);
390 
391  // Create the camera
392  createCamera();
393 
394  // Create a viewport
395  Ogre::Viewport *viewPort = mWindow->addViewport(mCamera);
396  // Ogre::Viewport* viewPort = mCamera->getViewport();
397  viewPort->setClearEveryFrame(true);
398  // Set the projection parameters to match the camera intrinsic parameters
400 
401  // Create the 3D scene
402  createScene();
403 
404  // Initialise and register event handlers
405  mRoot->addFrameListener(this);
406 
407  // Register as a Window listener
408  Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
409 
410 #ifdef VISP_HAVE_OIS
411  // Initialise OIS
412  Ogre::LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
413  OIS::ParamList pl;
414 
415  size_t windowHnd = 0;
416  std::ostringstream windowHndStr;
417  // Initialise window
418  mWindow->getCustomAttribute("WINDOW", &windowHnd);
419  windowHndStr << windowHnd;
420  pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
421 // Let the user use the keyboard elsewhere
422 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
423  pl.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
424 #endif
425 
426  mInputManager = OIS::InputManager::createInputSystem(pl);
427 
428  // Create all devices
429  // Here we only consider the keyboard input
430  mKeyboard = static_cast<OIS::Keyboard *>(mInputManager->createInputObject(OIS::OISKeyboard, bufferedKeys));
431  if (!bufferedKeys)
432  mKeyboard->setEventCallback(this);
433 #endif
434 
435  // Initialise a render to texture to be able to retrieve a screenshot
436  Ogre::TexturePtr Texture = Ogre::TextureManager::getSingleton().createManual(
437  "rtf", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, mWindow->getWidth(),
438  mWindow->getHeight(), 0, Ogre::PF_R8G8B8A8, Ogre::TU_RENDERTARGET);
439 
440  // Ogre::TexturePtr Texture =
441  // Ogre::TextureManager::getSingleton().createManual("rtf",
442  // Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,Ogre::TEX_TYPE_2D,
443  // 640,480, 0, Ogre::PF_R8G8B8A8,
444  // Ogre::TU_RENDERTARGET);
445  Ogre::RenderTexture *RTarget = Texture->getBuffer()->getRenderTarget();
446  /*Ogre::Viewport* Viewport =*/RTarget->addViewport(mCamera);
447  RTarget->getViewport(0)->setClearEveryFrame(true);
448  RTarget->getViewport(0)->setOverlaysEnabled(false);
449 }
450 
455 {
456  // Destroy 3D scene
457  destroyScene();
458  // Close OIS
459  closeOIS();
460 
461  if (mWindow) {
462  Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this);
464  }
465 
466  // Delete root
467  if (Ogre::Root::getSingletonPtr() && !Ogre::Root::getSingletonPtr()->getSceneManagerIterator().hasMoreElements()) {
468  if (mRoot) {
469  delete mRoot;
470  }
471  }
472  mRoot = 0;
473 }
474 
480 bool vpAROgre::stopTest(const Ogre::FrameEvent &evt)
481 {
482  // Always keep this part
483  if (keepOn) {
484  return updateScene(evt);
485  } else
486  return keepOn;
487 }
488 
498 bool vpAROgre::frameStarted(const Ogre::FrameEvent &evt)
499 {
500  // custom method telling what to do at the beginning of each frame
501  bool result = customframeStarted(evt);
502 
503  // Listen to the window
504  Ogre::WindowEventUtilities::messagePump();
505  processInputEvent(evt);
506 
507  // See if we have to stop rendering
508  if (result)
509  return stopTest(evt);
510  else
511  return result;
512 }
513 
520 bool vpAROgre::frameEnded(const Ogre::FrameEvent &evt)
521 {
522  // custom method telling what to do at the end of each frame
523  bool result = customframeEnded(evt);
524 
525  // See if we have to stop rendering
526  if (result)
527  return stopTest(evt);
528  else
529  return result;
530 }
531 
540 bool vpAROgre::customframeStarted(const Ogre::FrameEvent & /*evt*/)
541 {
542  // See if window was closed
543  if (mWindow->isClosed())
544  return false;
545 
546 #ifdef VISP_HAVE_OIS
547  // Get keyboard input
548  mKeyboard->capture();
549  if (mKeyboard->isKeyDown(OIS::KC_ESCAPE))
550  return false;
551 #endif
552  return true;
553 }
554 
560 bool vpAROgre::customframeEnded(const Ogre::FrameEvent & /*evt*/) { return true; }
561 
572 void vpAROgre::windowClosed(Ogre::RenderWindow *rw)
573 {
574  // Only close for window that created OIS (the main window in these demos)
575  if (rw == mWindow)
576  closeOIS();
577 }
578 
585 {
586  // Update the background to match the situation
588 
589  // Update the camera parameters to match the grabbed image
591 
592  // Display on Ogre Window
593  return mRoot->renderOneFrame();
594 }
595 
602 {
603  // Update the background to match the situation
605 
606  // Update the camera parameters to match the grabbed image
608 
609  // Display on Ogre Window
610  return mRoot->renderOneFrame();
611 }
612 
619 {
620  // Display on Ogre Window
621  if (renderOneFrame(I, cMw)) {
622  mWindow->update();
623  keepOn = true;
624  } else
625  keepOn = false;
626 }
627 
634 {
635  // Display on Ogre Window
636  if (renderOneFrame(I, cMw)) {
637  mWindow->update();
638  keepOn = true;
639  } else
640  keepOn = false;
641 }
642 
647 bool vpAROgre::continueRendering(void) { return keepOn; }
648 
652 void vpAROgre::setCameraParameters(const vpCameraParameters &cameraP) { mcam = cameraP; }
653 
659 void vpAROgre::load(const std::string &entityName, const std::string &model)
660 {
661  Ogre::Entity *newEntity = mSceneMgr->createEntity(entityName, model);
662  Ogre::SceneNode *newNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(entityName);
663  newNode->attachObject(newEntity);
664 }
665 
672 void vpAROgre::setPosition(const std::string &sceneName, const vpTranslationVector &wTo)
673 {
674  // Reset the position
675  Ogre::SceneNode *node = mSceneMgr->getSceneNode(sceneName);
676  node->setPosition((Ogre::Real)wTo[0], (Ogre::Real)wTo[1], (Ogre::Real)wTo[2]);
677 }
678 
684 vpTranslationVector vpAROgre::getPosition(const std::string &sceneName) const
685 {
686  Ogre::Vector3 translation = mSceneMgr->getSceneNode(sceneName)->getPosition();
687  return vpTranslationVector((Ogre::Real)translation[0], (Ogre::Real)translation[1], (Ogre::Real)translation[2]);
688 }
689 
695 void vpAROgre::setRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
696 {
697  // Get the node in its original position
698  mSceneMgr->getSceneNode(sceneName)->resetOrientation();
699  // Apply the new rotation
700  Ogre::Matrix3 rotationOgre = Ogre::Matrix3((Ogre::Real)wRo[0][0], (Ogre::Real)wRo[0][1], (Ogre::Real)wRo[0][2],
701  (Ogre::Real)wRo[1][0], (Ogre::Real)wRo[1][1], (Ogre::Real)wRo[1][2],
702  (Ogre::Real)wRo[2][0], (Ogre::Real)wRo[2][1], (Ogre::Real)wRo[2][2]);
703  Ogre::Quaternion q(rotationOgre);
704  mSceneMgr->getSceneNode(sceneName)->rotate(q);
705 }
706 
712 void vpAROgre::addRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
713 {
714  // Apply the new rotation
715  Ogre::Matrix3 rotationOgre = Ogre::Matrix3((Ogre::Real)wRo[0][0], (Ogre::Real)wRo[0][1], (Ogre::Real)wRo[0][2],
716  (Ogre::Real)wRo[1][0], (Ogre::Real)wRo[1][1], (Ogre::Real)wRo[1][2],
717  (Ogre::Real)wRo[2][0], (Ogre::Real)wRo[2][1], (Ogre::Real)wRo[2][2]);
718  Ogre::Quaternion q(rotationOgre);
719  mSceneMgr->getSceneNode(sceneName)->rotate(q);
720 }
721 
730 void vpAROgre::setPosition(const std::string &sceneName, const vpHomogeneousMatrix &wMo)
731 {
732  // Extract the position and orientation data
733  vpRotationMatrix rotations;
734  vpTranslationVector translation;
735  wMo.extract(rotations);
736  wMo.extract(translation);
737  // Apply them to the node
738  setPosition(sceneName, translation);
739  setRotation(sceneName, rotations);
740 }
741 
747 void vpAROgre::setVisibility(const std::string &sceneName, bool isVisible)
748 {
749  mSceneMgr->getSceneNode(sceneName)->setVisible(isVisible);
750 }
751 
759 void vpAROgre::setScale(const std::string &sceneName, const float factorx, const float factory, const float factorz)
760 {
761  // Reset the scale to its original value
762  mSceneMgr->getSceneNode(sceneName)->scale(Ogre::Vector3(1, 1, 1) / mSceneMgr->getSceneNode(sceneName)->getScale());
763  // Apply the new scale
764  mSceneMgr->getSceneNode(sceneName)->scale(Ogre::Vector3(factorx, factory, factorz));
765 }
766 
770 void vpAROgre::createCamera(void) { mCamera = mSceneMgr->createCamera("Camera"); }
771 
778 void vpAROgre::createBackground(vpImage<unsigned char> & /* I */)
779 {
780  // Create a rectangle to show the incoming images from the camera
781  mBackground = new Ogre::Rectangle2D(true); // true = textured
782  mBackground->setCorners(-1.0, 1.0, 1.0, -1.0); // Spread all over the window
783  mBackground->setBoundingBox(Ogre::AxisAlignedBox(-100000.0 * Ogre::Vector3::UNIT_SCALE,
784  100000.0 * Ogre::Vector3::UNIT_SCALE)); // To be shown everywhere
785 
786  // Texture options
787  Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_NONE);
788  Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(1);
789 
790  // Dynamic texture
791  // If we are using opengl we can boost a little bit performances with a
792  // dynamic texture
793  if (mRoot->getRenderSystem()->getName() == "OpenGL Rendering Subsystem") {
794  Ogre::TextureManager::getSingleton().createManual(
795  "BackgroundTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
796  mBackgroundWidth, // width
797  mBackgroundHeight, // height
798  0, // num of mip maps
799  Ogre::PF_BYTE_L, Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
800  } else {
801  Ogre::TextureManager::getSingleton().createManual(
802  "BackgroundTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
803  mBackgroundWidth, // width
804  mBackgroundHeight, // height
805  0, // num of mip maps
806  Ogre::PF_BYTE_L, Ogre::TU_DEFAULT);
807  }
808 
809  // Pointer to the dynamic texture
810  Ogre::TexturePtr dynTexPtr = Ogre::TextureManager::getSingleton().getByName("BackgroundTexture");
811  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
812  // .dynamicCast<Ogre::Texture>();// Get the pixel buffer
813  //#else
814  // ;
815  //#endif
816  mPixelBuffer = dynTexPtr->getBuffer();
817 
818  // Material to apply the texture to the background
819  Ogre::MaterialPtr Backgroundmaterial = Ogre::MaterialManager::getSingleton().create(
820  "BackgroundMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
821  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
822  // .dynamicCast<Ogre::Material>();
823  //#else
824  // ;
825  //#endif
826  Ogre::Technique *Backgroundtechnique = Backgroundmaterial->createTechnique();
827  Backgroundtechnique->createPass();
828  Backgroundmaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
829  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); // Background
830  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); // Background
831  Backgroundmaterial->getTechnique(0)->getPass(0)->createTextureUnitState("BackgroundTexture");
832  mBackground->setMaterial("BackgroundMaterial"); // Attach the material to the rectangle
833  mBackground->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND); // To be rendered in Background
834 
835  // Add the background to the Scene Graph so it will be rendered
836  Ogre::SceneNode *BackgroundNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("BackgoundNode");
837  BackgroundNode->attachObject(mBackground);
838 }
839 
846 void vpAROgre::createBackground(vpImage<vpRGBa> & /* I */)
847 {
848  // Create a rectangle to show the incoming images from the camera
849  mBackground = new Ogre::Rectangle2D(true); // true = textured
850  mBackground->setCorners(-1.0, 1.0, 1.0, -1.0); // Spread all over the window
851  mBackground->setBoundingBox(Ogre::AxisAlignedBox(-100000.0 * Ogre::Vector3::UNIT_SCALE,
852  100000.0 * Ogre::Vector3::UNIT_SCALE)); // To be shown everywhere
853 
854  // Texture options
855  Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_NONE);
856  Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(1);
857 
858  // Dynamic texture
859  // If we are using opengl we can boost a little bit performances with a
860  // dynamic texture
861  if (mRoot->getRenderSystem()->getName() == "OpenGL Rendering Subsystem") {
862  Ogre::TextureManager::getSingleton().createManual(
863  "BackgroundTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
864  mBackgroundWidth, // width
865  mBackgroundHeight, // height
866  0, // num of mip maps
867  // Ogre::PF_BYTE_RGBA,
868  Ogre::PF_BYTE_BGRA, Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
869  } else { // As that texture does not seem to work properly with direct3D we
870  // use a default texture
871  Ogre::TextureManager::getSingleton().createManual(
872  "BackgroundTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
873  mBackgroundWidth, // width
874  mBackgroundHeight, // height
875  0, // num of mip maps
876  // Ogre::PF_BYTE_RGBA,
877  Ogre::PF_BYTE_BGRA, Ogre::TU_DEFAULT);
878  }
879 
880  // Pointer to the dynamic texture
881  Ogre::TexturePtr dynTexPtr = Ogre::TextureManager::getSingleton().getByName("BackgroundTexture");
882  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
883  // .dynamicCast<Ogre::Texture>();// Get the pixel buffer
884  //#else
885  // ;
886  //#endif
887 
888  // Get the pixel buffer
889  mPixelBuffer = dynTexPtr->getBuffer();
890 
891  // Material to apply the texture to the background
892  Ogre::MaterialPtr Backgroundmaterial = Ogre::MaterialManager::getSingleton().create(
893  "BackgroundMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
894  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
895  // .dynamicCast<Ogre::Material>();
896  //#else
897  // ;
898  //#endif
899  Ogre::Technique *Backgroundtechnique = Backgroundmaterial->createTechnique();
900  Backgroundtechnique->createPass();
901  Backgroundmaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
902  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); // Background
903  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); // Background
904  Backgroundmaterial->getTechnique(0)->getPass(0)->createTextureUnitState("BackgroundTexture");
905  mBackground->setMaterial("BackgroundMaterial"); // Attach the material to the rectangle
906  mBackground->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND); // To be rendered in Background
907 
908  // Add the background to the Scene Graph so it will be rendered
909  Ogre::SceneNode *BackgroundNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("BackgoundNode");
910  BackgroundNode->attachObject(mBackground);
911 }
912 
921 {
922 #ifdef VISP_HAVE_OIS
923  if (mInputManager) {
924  mInputManager->destroyInputObject(mKeyboard);
925 
926  OIS::InputManager::destroyInputSystem(mInputManager);
927  mInputManager = 0;
928  }
929 #endif
930 }
931 
935 // Note: equation taken from:
936 // http://strawlab.org/2011/11/05/augmented-reality-with-OpenGL/
938 {
939  if (mCamera != 0) {
940  Ogre::Real f, n, f_m_n, f_p_n, px, py, u0, v0;
941  f = (Ogre::Real)(mFarClipping); // Far clip distance
942  n = (Ogre::Real)(mNearClipping); // Near clip distance
943  f_m_n = (Ogre::Real)(f - n);
944  f_p_n = (Ogre::Real)(f + n);
945  px = (Ogre::Real)mcam.get_px();
946  py = (Ogre::Real)mcam.get_py();
947  u0 = (Ogre::Real)mcam.get_u0();
948  v0 = (Ogre::Real)mcam.get_v0();
949  Ogre::Matrix4 Projection = Ogre::Matrix4(
950  (Ogre::Real)(2.0 * px / mBackgroundWidth), 0, (Ogre::Real)(1.0 - 2.0 * (u0 / mBackgroundWidth)), 0, 0,
951  (Ogre::Real)(2.0 * py / mBackgroundHeight), (Ogre::Real)(-1.0 + 2.0 * (v0 / mBackgroundHeight)), 0, 0, 0,
952  (Ogre::Real)(-1.0 * f_p_n / f_m_n), (Ogre::Real)(-2.0 * f * n / f_m_n), 0, 0, -1.0, 0);
953  mCamera->setCustomProjectionMatrix(true, Projection);
954  }
955 }
956 
961 {
962  // Inspired from Ogre wiki :
963  // http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures Lock the pixel
964  // buffer and get a pixel box. HBL_DISCARD is to use for best performance
965  // than HBL_NORMAL
966  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); // Lock the buffer
967  const Ogre::PixelBox &pixelBox = mPixelBuffer->getCurrentLock();
968  // Buffer data
969  Ogre::uint8 *pDest = static_cast<Ogre::uint8 *>(pixelBox.data);
970  // Fill in the data in the grey level texture
971  memcpy(pDest, I.bitmap, mBackgroundHeight * mBackgroundWidth);
972 
973  // Unlock the pixel buffer
974  mPixelBuffer->unlock();
975 }
976 
981 {
982  // Inspired from Ogre wiki :
983  // http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures Lock the pixel
984  // buffer and get a pixel box. HBL_DISCARD is to use for best performance
985  // than HBL_NORMAL
986  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); // Lock the buffer
987  const Ogre::PixelBox &pixelBox = mPixelBuffer->getCurrentLock();
988  // Buffer data
989  Ogre::uint8 *pDest = static_cast<Ogre::uint8 *>(pixelBox.data);
990 // Fill in the data in the grey level texture
991 #if 1 // if texture in BGRa format
992  for (unsigned int i = 0; i < mBackgroundHeight; i++) {
993  for (unsigned int j = 0; j < mBackgroundWidth; j++) {
994  // Color Image
995  // *pDest++=I[i][mBackgroundWidth-j].B; // Blue component
996  // *pDest++=I[i][mBackgroundWidth-j].G; // Green component
997  // *pDest++=I[i][mBackgroundWidth-j].R; // Red component
998 
999  *pDest++ = I[i][j].B; // Blue component
1000  *pDest++ = I[i][j].G; // Green component
1001  *pDest++ = I[i][j].R; // Red component
1002 
1003  *pDest++ = 255; // Alpha component
1004  }
1005  }
1006 #else // if texture in RGBa format which is the format of the input image
1007  memcpy(pDest, I.bitmap, mBackgroundHeight * mBackgroundWidth * sizeof(vpRGBa));
1008 #endif
1009 
1010  // Unlock the pixel buffer
1011  mPixelBuffer->unlock();
1012 }
1013 
1018 {
1019  // The matrix is given to Ogre with some changes to fit with the world
1020  // projection
1021  Ogre::Matrix4 ModelView
1022  // = Ogre::Matrix4( (Ogre::Real)-cMo[0][0], (Ogre::Real)-cMo[0][1],
1023  // (Ogre::Real)-cMo[0][2], (Ogre::Real)-cMo[0][3],
1024  = Ogre::Matrix4((Ogre::Real)cMw[0][0], (Ogre::Real)cMw[0][1], (Ogre::Real)cMw[0][2], (Ogre::Real)cMw[0][3],
1025  (Ogre::Real)-cMw[1][0], (Ogre::Real)-cMw[1][1], (Ogre::Real)-cMw[1][2], (Ogre::Real)-cMw[1][3],
1026  (Ogre::Real)-cMw[2][0], (Ogre::Real)-cMw[2][1], (Ogre::Real)-cMw[2][2], (Ogre::Real)-cMw[2][3],
1027  (Ogre::Real)0, (Ogre::Real)0, (Ogre::Real)0, (Ogre::Real)1);
1028  mCamera->setCustomViewMatrix(true, ModelView);
1029 }
1030 
1038 {
1040  Ogre::TexturePtr dynTexPtr = Ogre::TextureManager::getSingleton().getByName("rtf");
1041  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
1042  // .dynamicCast<Ogre::Texture>();
1043  //#else
1044  // ;
1045  //#endif
1046  Ogre::RenderTexture *RTarget = dynTexPtr->getBuffer()->getRenderTarget();
1047  mWindow->update();
1048  RTarget->update();
1049  if (I.getHeight() != mWindow->getHeight() || I.getWidth() != mWindow->getWidth()) {
1050  I.resize(mWindow->getHeight(), mWindow->getWidth());
1051  }
1052  Ogre::HardwarePixelBufferSharedPtr mPixelBuffer = dynTexPtr->getBuffer();
1053  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
1054  const Ogre::PixelBox &pixelBox = mPixelBuffer->getCurrentLock();
1055  dynTexPtr->getBuffer()->blitToMemory(pixelBox);
1056  Ogre::uint8 *pDest = static_cast<Ogre::uint8 *>(pixelBox.data);
1057 #if 1 // if texture in BGRa format
1058  for (unsigned int i = 0; i < I.getHeight(); i++) {
1059  for (unsigned int j = 0; j < I.getWidth(); j++) {
1060  // Color Image
1061  I[i][j].B = *pDest++; // Blue component
1062  I[i][j].G = *pDest++; // Green component
1063  I[i][j].R = *pDest++; // Red component
1064  I[i][j].A = *pDest++; // Alpha component
1065  }
1066  }
1067 #else // if texture in RGBa format which is the format of the input image
1068  memcpy(I.bitmap, pDest, I.getHeight() * I.getWidth() * sizeof(vpRGBa));
1069 #endif
1070 
1071  // Unlock the pixel buffer
1072  mPixelBuffer->unlock();
1073 }
1074 
1075 #elif !defined(VISP_BUILD_SHARED_LIBS)
1076 // Work arround to avoid warning: libvisp_ar.a(vpAROgre.cpp.o) has no symbols
1077 void dummy_vpAROgre(){};
1078 #endif
virtual void updateBackgroundTexture(const vpImage< unsigned char > &I)
Definition: vpAROgre.cpp:960
void setRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
Definition: vpAROgre.cpp:695
bool keepOn
Definition: vpAROgre.h:370
void addRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
Definition: vpAROgre.cpp:712
bool mshowConfigDialog
Definition: vpAROgre.h:387
Ogre::String name
Definition: vpAROgre.h:353
vpTranslationVector getPosition(const std::string &sceneName) const
Definition: vpAROgre.cpp:684
unsigned int mWindowWidth
Definition: vpAROgre.h:379
Ogre::String mPluginsPath
Definition: vpAROgre.h:361
unsigned int mBackgroundWidth
Definition: vpAROgre.h:377
Implementation of an homogeneous matrix and operations on such kind of matrices.
virtual bool customframeEnded(const Ogre::FrameEvent &evt)
Definition: vpAROgre.cpp:560
Type * bitmap
points toward the bitmap
Definition: vpImage.h:133
virtual bool destroyScene(void)
Definition: vpAROgre.h:322
Ogre::String mResourcePath
Definition: vpAROgre.h:360
error that can be emited by ViSP classes.
Definition: vpException.h:71
virtual void createCamera(void)
Definition: vpAROgre.cpp:770
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
OIS::Keyboard * mKeyboard
Definition: vpAROgre.h:366
bool renderOneFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMw)
Definition: vpAROgre.cpp:584
void extract(vpRotationMatrix &R) const
bool continueRendering(void)
Definition: vpAROgre.cpp:647
virtual void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMw)
Definition: vpAROgre.cpp:618
Definition: vpRGBa.h:66
Ogre::RenderWindow * mWindow
Definition: vpAROgre.h:359
OIS::InputManager * mInputManager
Definition: vpAROgre.h:365
Implementation of a rotation matrix and operations on such kind of matrices.
virtual void updateCameraParameters(const vpHomogeneousMatrix &cMo)
Definition: vpAROgre.cpp:1017
static bool checkFilename(const char *filename)
Definition: vpIoTools.cpp:573
void setVisibility(const std::string &sceneName, bool isVisible)
Definition: vpAROgre.cpp:747
virtual void init(vpImage< unsigned char > &I, bool bufferedKeys=false, bool hidden=false)
Definition: vpAROgre.cpp:115
vpCameraParameters mcam
Definition: vpAROgre.h:385
virtual bool processInputEvent(const Ogre::FrameEvent &)
Definition: vpAROgre.h:315
void setCameraParameters(const vpCameraParameters &cameraP)
Definition: vpAROgre.cpp:652
virtual ~vpAROgre(void)
Definition: vpAROgre.cpp:454
Ogre::Camera * mCamera
Definition: vpAROgre.h:357
void setScale(const std::string &sceneName, const float factorx, const float factory, const float factorz)
Definition: vpAROgre.cpp:759
Generic class defining intrinsic camera parameters.
virtual void closeOIS(void)
Definition: vpAROgre.cpp:920
virtual bool updateScene(const Ogre::FrameEvent &)
Definition: vpAROgre.h:308
virtual void windowClosed(Ogre::RenderWindow *rw)
Definition: vpAROgre.cpp:572
unsigned int mWindowHeight
Definition: vpAROgre.h:378
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:856
bool windowHidden
Definition: vpAROgre.h:380
void getRenderingOutput(vpImage< vpRGBa > &I, const vpHomogeneousMatrix &cMo)
Definition: vpAROgre.cpp:1037
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:1665
void load(const std::string &entityName, const std::string &model)
Definition: vpAROgre.cpp:659
virtual bool customframeStarted(const Ogre::FrameEvent &evt)
Definition: vpAROgre.cpp:540
unsigned int mBackgroundHeight
Definition: vpAROgre.h:376
virtual void updateCameraProjection(void)
Definition: vpAROgre.cpp:937
Ogre::Root * mRoot
Definition: vpAROgre.h:356
double mFarClipping
Definition: vpAROgre.h:384
Ogre::HardwarePixelBufferSharedPtr mPixelBuffer
Definition: vpAROgre.h:374
unsigned int getHeight() const
Definition: vpImage.h:178
Ogre::Rectangle2D * mBackground
Definition: vpAROgre.h:375
virtual void createScene(void)
Definition: vpAROgre.h:299
void setPosition(const std::string &sceneName, const vpTranslationVector &wTo)
Definition: vpAROgre.cpp:672
Ogre::SceneManager * mSceneMgr
Definition: vpAROgre.h:358
double mNearClipping
Definition: vpAROgre.h:383
std::list< std::string > mOptionnalResourceLocation
Definition: vpAROgre.h:390
unsigned int getWidth() const
Definition: vpImage.h:229
Class that consider the case of a translation vector.