Visual Servoing Platform  version 3.6.1 under development (2024-11-14)
vpAROgre.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Augmented Reality viewer using Ogre3D.
32  */
33 
44 #include <visp3/core/vpConfig.h>
45 
46 #ifdef VISP_HAVE_OGRE
47 
48 #include <visp3/ar/vpAROgre.h>
49 #include <visp3/core/vpIoTools.h>
50 
51 #include <OgreRectangle2D.h>
52 
53 BEGIN_VISP_NAMESPACE
69 vpAROgre::vpAROgre(const vpCameraParameters &cam, unsigned int width, unsigned int height, const char *resourcePath,
70  const char *pluginsPath)
71  : name("ViSP - Augmented Reality"), mRoot(0), mCamera(0), mSceneMgr(0), mWindow(0), mResourcePath(resourcePath),
72  mPluginsPath(pluginsPath),
73 #ifdef VISP_HAVE_OIS
74  mInputManager(0), mKeyboard(0),
75 #endif
76  keepOn(true), // When created no reason to stop displaying
77  mImageRGBA(), mImage(), mPixelBuffer(), mBackground(nullptr), mBackgroundHeight(0), mBackgroundWidth(0),
78  mWindowHeight(height), mWindowWidth(width), windowHidden(false), mNearClipping(0.001), mFarClipping(200), mcam(cam),
79  mshowConfigDialog(true), mOptionalResourceLocation()
80 { }
81 
111  bool
112 #ifdef VISP_HAVE_OIS
113  bufferedKeys
114 #endif
115  ,
116  bool hidden)
117 {
120 
121  init(
122 #ifdef VISP_HAVE_OIS
123  bufferedKeys,
124 #else
125  false,
126 #endif
127  hidden);
128  // Create the background image which will come from the grabber
129  createBackground(I);
130 }
131 
161  bool
162 #ifdef VISP_HAVE_OIS
163  bufferedKeys
164 #endif
165  ,
166  bool hidden)
167 {
170 
171  init(
172 #ifdef VISP_HAVE_OIS
173  bufferedKeys,
174 #else
175  false,
176 #endif
177  hidden);
178  // Create the background image which will come from the grabber
179  createBackground(I);
180 }
181 
206 void vpAROgre::init(bool
207 #ifdef VISP_HAVE_OIS
208  bufferedKeys
209 #endif
210  ,
211  bool hidden)
212 {
213  // Create the root
214  // mPluginsPath may contain more than one folder location separated by ";"
215  bool pluginsFileExists = false;
216  std::string pluginFile;
217  std::vector<std::string> plugingsPaths = vpIoTools::splitChain(std::string(mPluginsPath), std::string(";"));
218  for (size_t i = 0; i < plugingsPaths.size(); i++) {
219 #if defined(NDEBUG) || !defined(_WIN32)
220  pluginFile = plugingsPaths[i] + "/plugins.cfg";
221 #else
222  pluginFile = plugingsPaths[i] + "/plugins_d.cfg";
223 #endif
224 
225  if (vpIoTools::checkFilename(pluginFile)) {
226  pluginsFileExists = true;
227  break;
228  }
229  }
230  if (!pluginsFileExists) {
231  std::string errorMsg = std::string("Error: the requested plugins file \"")
232 #if defined(NDEBUG) || !defined(_WIN32)
233  +std::string("plugins.cfg")
234 #else
235  + std::string("plugins_d.cfg")
236 #endif
237  + std::string("\" doesn't exist in ") + std::string(mPluginsPath);
238  std::cout << errorMsg << std::endl;
239 
240  throw(vpException(vpException::ioError, errorMsg));
241  }
242  std::cout << "######################### Load plugin file: " << pluginFile << std::endl;
243 
244  if (Ogre::Root::getSingletonPtr() == nullptr) {
245  mRoot = new Ogre::Root(pluginFile, "ogre.cfg", "Ogre.log");
246  }
247  else {
248  mRoot = Ogre::Root::getSingletonPtr();
249  }
250 
251  // Load resource paths from config file
252 
253  // File format is:
254  // [ResourceGroupName]
255  // ArchiveType=Path
256  // .. repeat
257  // For example:
258  // [General]
259  // FileSystem=media/
260  // Zip=packages/level1.zip
261 
262  // mResourcePath may contain more than one folder location separated by ";"
263  bool resourcesFileExists = false;
264  std::string resourceFile;
265  std::vector<std::string> resourcesPaths = vpIoTools::splitChain(std::string(mResourcePath), std::string(";"));
266  for (size_t i = 0; i < resourcesPaths.size(); i++) {
267  resourceFile = resourcesPaths[i] + "/resources.cfg";
268  if (vpIoTools::checkFilename(resourceFile)) {
269  resourcesFileExists = true;
270  break;
271  }
272  }
273  if (!resourcesFileExists) {
274  std::string errorMsg = std::string("Error: the requested resource file \"resources.cfg\"") +
275  std::string("doesn't exist in ") + std::string(mResourcePath);
276 
277  std::cout << errorMsg << std::endl;
278 
279  throw(vpException(vpException::ioError, errorMsg));
280  }
281  std::cout << "######################### Load resource file: " << resourceFile << std::endl;
282  Ogre::ConfigFile cf;
283  cf.load(resourceFile);
284 
285  // Go through all sections & settings in the file
286  Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
287 
288  Ogre::String secName, typeName, archName;
289  while (seci.hasMoreElements()) {
290  secName = seci.peekNextKey();
291  Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
292  Ogre::ConfigFile::SettingsMultiMap::iterator i;
293  for (i = settings->begin(); i != settings->end(); ++i) {
294  typeName = i->first;
295  archName = i->second;
296  Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
297  }
298  }
299  std::cout << "##################### add resources" << std::endl;
300  // Add Optional resources (given by the user).
301  for (std::list<std::string>::const_iterator iter = mOptionalResourceLocation.begin();
302  iter != mOptionalResourceLocation.end(); ++iter) {
303  Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
304  *iter, "FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
305  }
306 
307  // Create the window
308  bool canInit = true;
309  if (mshowConfigDialog) {
310  mRoot->restoreConfig();
311  if (!mRoot->showConfigDialog()) {
312  canInit = false;
313  }
314  }
315  else {
316  if (!mRoot->restoreConfig()) {
317  canInit = false;
318  }
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 
328  Ogre::RenderSystem *lRenderSystem = lRenderSystemList.at(0);
329  std::cout << "Using " << lRenderSystem->getName() << " as renderer." << std::endl;
330  mRoot->setRenderSystem(lRenderSystem);
331  }
332 
333  mRoot->initialise(false);
334  }
335 
336  bool fullscreen = false;
337  Ogre::NameValuePairList misc;
338  Ogre::ConfigOptionMap config = mRoot->getRenderSystem()->getConfigOptions();
339  Ogre::ConfigOptionMap::const_iterator it = config.begin();
340 
341  while (it != config.end()) {
342  Ogre::String leftconf = (*it).first;
343  Ogre::String rightconf = (*it).second.currentValue;
344 
345  if (leftconf == "Video Mode") {
346  if (canInit) {
347  std::stringstream ss(rightconf.c_str());
348  std::string dummy;
349  ss >> mWindowWidth >> dummy >> mWindowHeight;
350  if (ss.fail()) {
351  std::cout << "Cannot read Ogre video mode" << std::endl;
352  }
353  }
354  else if (mWindowWidth == 0 && mWindowHeight == 0) {
357  }
358  }
359  else if (leftconf == "Full Screen") {
360  if (canInit && (rightconf == "Yes")) {
361  fullscreen = true;
362  }
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  }
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  }
630  else
631  keepOn = false;
632 }
633 
640 {
641  // Display on Ogre Window
642  if (renderOneFrame(I, cMw)) {
643  mWindow->update();
644  keepOn = true;
645  }
646  else
647  keepOn = false;
648 }
649 
654 bool vpAROgre::continueRendering(void) { return keepOn; }
655 
659 void vpAROgre::setCameraParameters(const vpCameraParameters &cameraP) { mcam = cameraP; }
660 
666 void vpAROgre::load(const std::string &entityName, const std::string &model)
667 {
668  Ogre::Entity *newEntity = mSceneMgr->createEntity(entityName, model);
669  Ogre::SceneNode *newNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(entityName);
670  newNode->attachObject(newEntity);
671 }
672 
679 void vpAROgre::setPosition(const std::string &sceneName, const vpTranslationVector &wTo)
680 {
681  // Reset the position
682  Ogre::SceneNode *node = mSceneMgr->getSceneNode(sceneName);
683  node->setPosition((Ogre::Real)wTo[0], (Ogre::Real)wTo[1], (Ogre::Real)wTo[2]);
684 }
685 
691 vpTranslationVector vpAROgre::getPosition(const std::string &sceneName) const
692 {
693  Ogre::Vector3 translation = mSceneMgr->getSceneNode(sceneName)->getPosition();
694  return vpTranslationVector((Ogre::Real)translation[0], (Ogre::Real)translation[1], (Ogre::Real)translation[2]);
695 }
696 
702 void vpAROgre::setRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
703 {
704  // Get the node in its original position
705  mSceneMgr->getSceneNode(sceneName)->resetOrientation();
706  // Apply the new rotation
707  Ogre::Matrix3 rotationOgre = Ogre::Matrix3((Ogre::Real)wRo[0][0], (Ogre::Real)wRo[0][1], (Ogre::Real)wRo[0][2],
708  (Ogre::Real)wRo[1][0], (Ogre::Real)wRo[1][1], (Ogre::Real)wRo[1][2],
709  (Ogre::Real)wRo[2][0], (Ogre::Real)wRo[2][1], (Ogre::Real)wRo[2][2]);
710  Ogre::Quaternion q(rotationOgre);
711  mSceneMgr->getSceneNode(sceneName)->rotate(q);
712 }
713 
719 void vpAROgre::addRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
720 {
721  // Apply the new rotation
722  Ogre::Matrix3 rotationOgre = Ogre::Matrix3((Ogre::Real)wRo[0][0], (Ogre::Real)wRo[0][1], (Ogre::Real)wRo[0][2],
723  (Ogre::Real)wRo[1][0], (Ogre::Real)wRo[1][1], (Ogre::Real)wRo[1][2],
724  (Ogre::Real)wRo[2][0], (Ogre::Real)wRo[2][1], (Ogre::Real)wRo[2][2]);
725  Ogre::Quaternion q(rotationOgre);
726  mSceneMgr->getSceneNode(sceneName)->rotate(q);
727 }
728 
737 void vpAROgre::setPosition(const std::string &sceneName, const vpHomogeneousMatrix &wMo)
738 {
739  // Extract the position and orientation data
740  vpRotationMatrix rotations;
741  vpTranslationVector translation;
742  wMo.extract(rotations);
743  wMo.extract(translation);
744  // Apply them to the node
745  setPosition(sceneName, translation);
746  setRotation(sceneName, rotations);
747 }
748 
754 void vpAROgre::setVisibility(const std::string &sceneName, bool isVisible)
755 {
756  mSceneMgr->getSceneNode(sceneName)->setVisible(isVisible);
757 }
758 
766 void vpAROgre::setScale(const std::string &sceneName, float factorx, float factory, float factorz)
767 {
768  // Reset the scale to its original value
769  mSceneMgr->getSceneNode(sceneName)->scale(Ogre::Vector3(1, 1, 1) / mSceneMgr->getSceneNode(sceneName)->getScale());
770  // Apply the new scale
771  mSceneMgr->getSceneNode(sceneName)->scale(Ogre::Vector3(factorx, factory, factorz));
772 }
773 
777 void vpAROgre::createCamera(void) { mCamera = mSceneMgr->createCamera("Camera"); }
778 
785 void vpAROgre::createBackground(vpImage<unsigned char> & /* I */)
786 {
787  // Create a rectangle to show the incoming images from the camera
788  mBackground = new Ogre::Rectangle2D(true); // true = textured
789  mBackground->setCorners(-1.0, 1.0, 1.0, -1.0); // Spread all over the window
790  mBackground->setBoundingBox(Ogre::AxisAlignedBox(-100000.0 * Ogre::Vector3::UNIT_SCALE,
791  100000.0 * Ogre::Vector3::UNIT_SCALE)); // To be shown everywhere
792 
793  // Texture options
794  Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_NONE);
795  Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(1);
796 
797  // Dynamic texture
798  // If we are using opengl we can boost a little bit performances with a
799  // dynamic texture
800  if (mRoot->getRenderSystem()->getName() == "OpenGL Rendering Subsystem") {
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_DYNAMIC_WRITE_ONLY_DISCARDABLE);
807  }
808  else {
809  Ogre::TextureManager::getSingleton().createManual(
810  "BackgroundTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
811  mBackgroundWidth, // width
812  mBackgroundHeight, // height
813  0, // num of mip maps
814  Ogre::PF_BYTE_L, Ogre::TU_DEFAULT);
815  }
816 
817  // Pointer to the dynamic texture
818  Ogre::TexturePtr dynTexPtr = Ogre::TextureManager::getSingleton().getByName("BackgroundTexture");
819  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
820  // .dynamicCast<Ogre::Texture>();// Get the pixel buffer
821  //#else
822  // ;
823  //#endif
824  mPixelBuffer = dynTexPtr->getBuffer();
825 
826  // Material to apply the texture to the background
827  Ogre::MaterialPtr Backgroundmaterial = Ogre::MaterialManager::getSingleton().create(
828  "BackgroundMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
829  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
830  // .dynamicCast<Ogre::Material>();
831  //#else
832  // ;
833  //#endif
834  Ogre::Technique *Backgroundtechnique = Backgroundmaterial->createTechnique();
835  Backgroundtechnique->createPass();
836  Backgroundmaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
837  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); // Background
838  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); // Background
839  Backgroundmaterial->getTechnique(0)->getPass(0)->createTextureUnitState("BackgroundTexture");
840  mBackground->setMaterial("BackgroundMaterial"); // Attach the material to the rectangle
841  mBackground->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND); // To be rendered in Background
842 
843  // Add the background to the Scene Graph so it will be rendered
844  Ogre::SceneNode *BackgroundNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("BackgoundNode");
845  BackgroundNode->attachObject(mBackground);
846 }
847 
854 void vpAROgre::createBackground(vpImage<vpRGBa> & /* I */)
855 {
856  // Create a rectangle to show the incoming images from the camera
857  mBackground = new Ogre::Rectangle2D(true); // true = textured
858  mBackground->setCorners(-1.0, 1.0, 1.0, -1.0); // Spread all over the window
859  mBackground->setBoundingBox(Ogre::AxisAlignedBox(-100000.0 * Ogre::Vector3::UNIT_SCALE,
860  100000.0 * Ogre::Vector3::UNIT_SCALE)); // To be shown everywhere
861 
862  // Texture options
863  Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_NONE);
864  Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(1);
865 
866  // Dynamic texture
867  // If we are using opengl we can boost a little bit performances with a
868  // dynamic texture
869  if (mRoot->getRenderSystem()->getName() == "OpenGL Rendering Subsystem") {
870  Ogre::TextureManager::getSingleton().createManual(
871  "BackgroundTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
872  mBackgroundWidth, // width
873  mBackgroundHeight, // height
874  0, // num of mip maps
875  // Ogre::PF_BYTE_RGBA,
876  Ogre::PF_BYTE_BGRA, Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
877  }
878  else { // As that texture does not seem to work properly with direct3D we
879  // use a default texture
880  Ogre::TextureManager::getSingleton().createManual(
881  "BackgroundTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
882  mBackgroundWidth, // width
883  mBackgroundHeight, // height
884  0, // num of mip maps
885  // Ogre::PF_BYTE_RGBA,
886  Ogre::PF_BYTE_BGRA, Ogre::TU_DEFAULT);
887  }
888 
889  // Pointer to the dynamic texture
890  Ogre::TexturePtr dynTexPtr = Ogre::TextureManager::getSingleton().getByName("BackgroundTexture");
891  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
892  // .dynamicCast<Ogre::Texture>();// Get the pixel buffer
893  //#else
894  // ;
895  //#endif
896 
897  // Get the pixel buffer
898  mPixelBuffer = dynTexPtr->getBuffer();
899 
900  // Material to apply the texture to the background
901  Ogre::MaterialPtr Backgroundmaterial = Ogre::MaterialManager::getSingleton().create(
902  "BackgroundMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
903  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
904  // .dynamicCast<Ogre::Material>();
905  //#else
906  // ;
907  //#endif
908  Ogre::Technique *Backgroundtechnique = Backgroundmaterial->createTechnique();
909  Backgroundtechnique->createPass();
910  Backgroundmaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
911  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); // Background
912  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); // Background
913  Backgroundmaterial->getTechnique(0)->getPass(0)->createTextureUnitState("BackgroundTexture");
914  mBackground->setMaterial("BackgroundMaterial"); // Attach the material to the rectangle
915  mBackground->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND); // To be rendered in Background
916 
917  // Add the background to the Scene Graph so it will be rendered
918  Ogre::SceneNode *BackgroundNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("BackgoundNode");
919  BackgroundNode->attachObject(mBackground);
920 }
921 
930 {
931 #ifdef VISP_HAVE_OIS
932  if (mInputManager) {
933  mInputManager->destroyInputObject(mKeyboard);
934 
935  OIS::InputManager::destroyInputSystem(mInputManager);
936  mInputManager = 0;
937  }
938 #endif
939 }
940 
944 // Note: equation taken from:
945 // http://strawlab.org/2011/11/05/augmented-reality-with-OpenGL/
947 {
948  if (mCamera != 0) {
949  Ogre::Real f, n, f_m_n, f_p_n, px, py, u0, v0;
950  f = (Ogre::Real)(mFarClipping); // Far clip distance
951  n = (Ogre::Real)(mNearClipping); // Near clip distance
952  f_m_n = (Ogre::Real)(f - n);
953  f_p_n = (Ogre::Real)(f + n);
954  px = (Ogre::Real)mcam.get_px();
955  py = (Ogre::Real)mcam.get_py();
956  u0 = (Ogre::Real)mcam.get_u0();
957  v0 = (Ogre::Real)mcam.get_v0();
958  Ogre::Matrix4 Projection = Ogre::Matrix4(
959  (Ogre::Real)(2.0 * px / mBackgroundWidth), 0, (Ogre::Real)(1.0 - 2.0 * (u0 / mBackgroundWidth)), 0, 0,
960  (Ogre::Real)(2.0 * py / mBackgroundHeight), (Ogre::Real)(-1.0 + 2.0 * (v0 / mBackgroundHeight)), 0, 0, 0,
961  (Ogre::Real)(-1.0 * f_p_n / f_m_n), (Ogre::Real)(-2.0 * f * n / f_m_n), 0, 0, -1.0, 0);
962  mCamera->setCustomProjectionMatrix(true, Projection);
963  }
964 }
965 
970 {
971  // Inspired from Ogre wiki :
972  // http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures Lock the pixel
973  // buffer and get a pixel box. HBL_DISCARD is to use for best performance
974  // than HBL_NORMAL
975  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); // Lock the buffer
976  const Ogre::PixelBox &pixelBox = mPixelBuffer->getCurrentLock();
977  // Buffer data
978  Ogre::uint8 *pDest = static_cast<Ogre::uint8 *>(pixelBox.data);
979  // Fill in the data in the grey level texture
980  memcpy(pDest, I.bitmap, mBackgroundHeight * mBackgroundWidth);
981 
982  // Unlock the pixel buffer
983  mPixelBuffer->unlock();
984 }
985 
990 {
991  // Inspired from Ogre wiki :
992  // http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures Lock the pixel
993  // buffer and get a pixel box. HBL_DISCARD is to use for best performance
994  // than HBL_NORMAL
995  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); // Lock the buffer
996  const Ogre::PixelBox &pixelBox = mPixelBuffer->getCurrentLock();
997  // Buffer data
998  Ogre::uint8 *pDest = static_cast<Ogre::uint8 *>(pixelBox.data);
999 // Fill in the data in the grey level texture
1000 #if 1 // if texture in BGRa format
1001  for (unsigned int i = 0; i < mBackgroundHeight; i++) {
1002  for (unsigned int j = 0; j < mBackgroundWidth; j++) {
1003  // Color Image
1004  // *pDest++=I[i][mBackgroundWidth-j].B; // Blue component
1005  // *pDest++=I[i][mBackgroundWidth-j].G; // Green component
1006  // *pDest++=I[i][mBackgroundWidth-j].R; // Red component
1007 
1008  *pDest++ = I[i][j].B; // Blue component
1009  *pDest++ = I[i][j].G; // Green component
1010  *pDest++ = I[i][j].R; // Red component
1011 
1012  *pDest++ = 255; // Alpha component
1013  }
1014  }
1015 #else // if texture in RGBa format which is the format of the input image
1016  memcpy(pDest, I.bitmap, mBackgroundHeight * mBackgroundWidth * sizeof(vpRGBa));
1017 #endif
1018 
1019  // Unlock the pixel buffer
1020  mPixelBuffer->unlock();
1021 }
1022 
1027 {
1028  // The matrix is given to Ogre with some changes to fit with the world
1029  // projection
1030  Ogre::Matrix4 ModelView
1031  // = Ogre::Matrix4( (Ogre::Real)-cMo[0][0], (Ogre::Real)-cMo[0][1],
1032  // (Ogre::Real)-cMo[0][2], (Ogre::Real)-cMo[0][3],
1033  = Ogre::Matrix4((Ogre::Real)cMw[0][0], (Ogre::Real)cMw[0][1], (Ogre::Real)cMw[0][2], (Ogre::Real)cMw[0][3],
1034  (Ogre::Real)-cMw[1][0], (Ogre::Real)-cMw[1][1], (Ogre::Real)-cMw[1][2], (Ogre::Real)-cMw[1][3],
1035  (Ogre::Real)-cMw[2][0], (Ogre::Real)-cMw[2][1], (Ogre::Real)-cMw[2][2], (Ogre::Real)-cMw[2][3],
1036  (Ogre::Real)0, (Ogre::Real)0, (Ogre::Real)0, (Ogre::Real)1);
1037  mCamera->setCustomViewMatrix(true, ModelView);
1038 }
1039 
1047 {
1049  Ogre::TexturePtr dynTexPtr = Ogre::TextureManager::getSingleton().getByName("rtf");
1050  //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
1051  // .dynamicCast<Ogre::Texture>();
1052  //#else
1053  // ;
1054  //#endif
1055  Ogre::RenderTexture *RTarget = dynTexPtr->getBuffer()->getRenderTarget();
1056  mWindow->update();
1057  RTarget->update();
1058  if (I.getHeight() != mWindow->getHeight() || I.getWidth() != mWindow->getWidth()) {
1059  I.resize(mWindow->getHeight(), mWindow->getWidth());
1060  }
1061  mPixelBuffer = dynTexPtr->getBuffer();
1062  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
1063  const Ogre::PixelBox &pixelBox = mPixelBuffer->getCurrentLock();
1064  dynTexPtr->getBuffer()->blitToMemory(pixelBox);
1065  Ogre::uint8 *pDest = static_cast<Ogre::uint8 *>(pixelBox.data);
1066 #if 1 // if texture in BGRa format
1067  for (unsigned int i = 0; i < I.getHeight(); i++) {
1068  for (unsigned int j = 0; j < I.getWidth(); j++) {
1069  // Color Image
1070  I[i][j].B = *pDest++; // Blue component
1071  I[i][j].G = *pDest++; // Green component
1072  I[i][j].R = *pDest++; // Red component
1073  I[i][j].A = *pDest++; // Alpha component
1074  }
1075  }
1076 #else // if texture in RGBa format which is the format of the input image
1077  memcpy(I.bitmap, pDest, I.getHeight() * I.getWidth() * sizeof(vpRGBa));
1078 #endif
1079 
1080  // Unlock the pixel buffer
1081  mPixelBuffer->unlock();
1082 }
1083 END_VISP_NAMESPACE
1084 #elif !defined(VISP_BUILD_SHARED_LIBS)
1085 // Work around to avoid warning: libvisp_ar.a(vpAROgre.cpp.o) has no symbols
1086 void dummy_vpAROgre() { };
1087 #endif
OIS::InputManager * mInputManager
Definition: vpAROgre.h:362
void setCameraParameters(const vpCameraParameters &cameraP)
Definition: vpAROgre.cpp:659
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:69
bool continueRendering(void)
Definition: vpAROgre.cpp:654
virtual bool updateScene(const Ogre::FrameEvent &)
Definition: vpAROgre.h:304
virtual bool customframeEnded(const Ogre::FrameEvent &evt)
Definition: vpAROgre.cpp:565
OIS::Keyboard * mKeyboard
Definition: vpAROgre.h:363
bool keepOn
Definition: vpAROgre.h:367
virtual bool processInputEvent(const Ogre::FrameEvent &)
Definition: vpAROgre.h:311
void addRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
Definition: vpAROgre.cpp:719
unsigned int mBackgroundWidth
Definition: vpAROgre.h:374
vpCameraParameters mcam
Definition: vpAROgre.h:382
void getRenderingOutput(vpImage< vpRGBa > &I, const vpHomogeneousMatrix &cMo)
Definition: vpAROgre.cpp:1046
bool windowHidden
Definition: vpAROgre.h:377
double mNearClipping
Definition: vpAROgre.h:380
Ogre::Root * mRoot
Definition: vpAROgre.h:353
Ogre::String name
Definition: vpAROgre.h:350
virtual bool destroyScene(void)
Definition: vpAROgre.h:318
virtual void updateCameraProjection(void)
Definition: vpAROgre.cpp:946
Ogre::Camera * mCamera
Definition: vpAROgre.h:354
void setRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
Definition: vpAROgre.cpp:702
virtual void closeOIS(void)
Definition: vpAROgre.cpp:929
unsigned int mBackgroundHeight
Definition: vpAROgre.h:373
virtual void windowClosed(Ogre::RenderWindow *rw)
Definition: vpAROgre.cpp:577
virtual bool customframeStarted(const Ogre::FrameEvent &evt)
Definition: vpAROgre.cpp:545
Ogre::String mPluginsPath
Definition: vpAROgre.h:358
Ogre::Rectangle2D * mBackground
Definition: vpAROgre.h:372
double mFarClipping
Definition: vpAROgre.h:381
vpTranslationVector getPosition(const std::string &sceneName) const
Definition: vpAROgre.cpp:691
virtual void createScene(void)
Definition: vpAROgre.h:295
unsigned int mWindowHeight
Definition: vpAROgre.h:375
void setVisibility(const std::string &sceneName, bool isVisible)
Definition: vpAROgre.cpp:754
virtual void init(vpImage< unsigned char > &I, bool bufferedKeys=false, bool hidden=false)
Definition: vpAROgre.cpp:110
virtual void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMw)
Definition: vpAROgre.cpp:623
bool renderOneFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMw)
Definition: vpAROgre.cpp:589
void load(const std::string &entityName, const std::string &model)
Definition: vpAROgre.cpp:666
virtual void createCamera(void)
Definition: vpAROgre.cpp:777
virtual void updateCameraParameters(const vpHomogeneousMatrix &cMo)
Definition: vpAROgre.cpp:1026
std::list< std::string > mOptionalResourceLocation
Definition: vpAROgre.h:387
Ogre::SceneManager * mSceneMgr
Definition: vpAROgre.h:355
Ogre::HardwarePixelBufferSharedPtr mPixelBuffer
Definition: vpAROgre.h:371
virtual ~vpAROgre(void)
Definition: vpAROgre.cpp:458
bool mshowConfigDialog
Definition: vpAROgre.h:384
Ogre::String mResourcePath
Definition: vpAROgre.h:357
void setPosition(const std::string &sceneName, const vpTranslationVector &wTo)
Definition: vpAROgre.cpp:679
Ogre::RenderWindow * mWindow
Definition: vpAROgre.h:356
unsigned int mWindowWidth
Definition: vpAROgre.h:376
virtual void updateBackgroundTexture(const vpImage< unsigned char > &I)
Definition: vpAROgre.cpp:969
void setScale(const std::string &sceneName, float factorx, float factory, float factorz)
Definition: vpAROgre.cpp:766
Generic class defining intrinsic camera parameters.
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ ioError
I/O error.
Definition: vpException.h:67
Implementation of an homogeneous matrix and operations on such kind of matrices.
void extract(vpRotationMatrix &R) const
unsigned int getWidth() const
Definition: vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:542
Type * bitmap
points toward the bitmap
Definition: vpImage.h:135
unsigned int getHeight() const
Definition: vpImage.h:181
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:1661
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:786
Definition: vpRGBa.h:65
Implementation of a rotation matrix and operations on such kind of matrices.
Class that consider the case of a translation vector.