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