Visual Servoing Platform  version 3.0.0
vpAROgre.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
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 http://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  * Authors:
34  * Bertrand Delabarre
35  *
36  *****************************************************************************/
37 
48 #include "visp3/core/vpConfig.h"
49 
50 #ifdef VISP_HAVE_OGRE
51 
52 #include "visp3/ar/vpAROgre.h"
53 #include "visp3/core/vpIoTools.h"
54 
55 
72  unsigned int width, unsigned int height,
73  const char *resourcePath, const char *pluginsPath)
74  : name("ViSP - Augmented Reality"),mRoot(0), mCamera(0), mSceneMgr(0), mWindow(0),
75  mResourcePath(resourcePath), mPluginsPath(pluginsPath),
76 #ifdef VISP_HAVE_OIS
77  mInputManager(0), mKeyboard(0),
78 #endif
79  keepOn(true), // When created no reason to stop displaying
80  mImageRGBA(), mImage(), mPixelBuffer(NULL), mBackground(NULL), mBackgroundHeight(0),
81  mBackgroundWidth(0), mWindowHeight(height), mWindowWidth(width), windowHidden(false),
82  mNearClipping(0.001), mFarClipping(200), mcam(cam), mshowConfigDialog(true),
83  mOptionnalResourceLocation()
84 {
85 }
86 
116  bool
117 #ifdef VISP_HAVE_OIS
118  bufferedKeys
119 #endif
120  ,bool hidden
121  )
122 {
125 
126  init(
127 #ifdef VISP_HAVE_OIS
128  bufferedKeys,
129 #else
130  false,
131 #endif
132  hidden
133  );
134  // Create the background image which will come from the grabber
135  createBackground(I);
136 }
137 
167  bool
168 #ifdef VISP_HAVE_OIS
169  bufferedKeys
170 #endif
171  ,bool hidden
172  )
173 {
176 
177  init(
178 #ifdef VISP_HAVE_OIS
179  bufferedKeys,
180 #else
181  false,
182 #endif
183  hidden
184  );
185  // Create the background image which will come from the grabber
186  createBackground(I);
187 }
188 
213 void vpAROgre::init(bool
214 #ifdef VISP_HAVE_OIS
215  bufferedKeys
216 #endif
217  ,bool hidden
218  )
219 {
220  // Create the root
221  // mPluginsPath may contain more than one folder location separated by ";"
222  bool pluginsFileExists = false;
223  std::string pluginFile;
224  std::vector<std::string> plugingsPaths = vpIoTools::splitChain(std::string(mPluginsPath), std::string(";"));
225  for (size_t i=0; i<plugingsPaths.size(); i++) {
226 #if defined(NDEBUG) || !defined(_WIN32)
227  pluginFile = plugingsPaths[i]+"/plugins.cfg";
228 #else
229  pluginFile = plugingsPaths[i]+"/plugins_d.cfg";
230 #endif
231 
232  if(vpIoTools::checkFilename(pluginFile)) {
233  pluginsFileExists = true;
234  break;
235  }
236  }
237  if (! pluginsFileExists) {
238  std::string errorMsg = std::string("Error: the requested plugins file \"")
239 #if defined(NDEBUG) || !defined(_WIN32)
240  + std::string("plugins.cfg")
241 #else
242  + std::string("plugins_d.cfg")
243 #endif
244  + std::string("\" doesn't exist in ")
245  + std::string(mPluginsPath);
246  std::cout << errorMsg << std::endl;
247 
248  throw (vpException(vpException::ioError, errorMsg));
249  }
250  std::cout << "######################### Load plugin file: " << pluginFile << std::endl;
251 
252  if(Ogre::Root::getSingletonPtr() == NULL)
253  mRoot = new Ogre::Root(pluginFile, "ogre.cfg", "Ogre.log");
254  else
255  mRoot = Ogre::Root::getSingletonPtr();
256 
257  // Load resource paths from config file
258 
259  // File format is:
260  // [ResourceGroupName]
261  // ArchiveType=Path
262  // .. repeat
263  // For example:
264  // [General]
265  // FileSystem=media/
266  // Zip=packages/level1.zip
267 
268  // mResourcePath may contain more than one folder location separated by ";"
269  bool resourcesFileExists = false;
270  std::string resourceFile;
271  std::vector<std::string> resourcesPaths = vpIoTools::splitChain(std::string(mResourcePath), std::string(";"));
272  for (size_t i=0; i<resourcesPaths.size(); i++) {
273  resourceFile = resourcesPaths[i]+"/resources.cfg";
274  if(vpIoTools::checkFilename(resourceFile)) {
275  resourcesFileExists = true;
276  break;
277  }
278  }
279  if (! resourcesFileExists) {
280  std::string errorMsg = std::string("Error: the requested resource file \"resources.cfg\"")
281  + std::string("doesn't exist in ")
282  + std::string(mResourcePath);
283 
284  std::cout << errorMsg << std::endl;
285 
286  throw (vpException(vpException::ioError, errorMsg));
287  }
288  std::cout << "######################### Load resource file: " << resourceFile << std::endl;
289  Ogre::ConfigFile cf;
290  cf.load(resourceFile);
291 
292  // Go through all sections & settings in the file
293  Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
294 
295  Ogre::String secName, typeName, archName;
296  while (seci.hasMoreElements())
297  {
298  secName = seci.peekNextKey();
299  Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
300  Ogre::ConfigFile::SettingsMultiMap::iterator i;
301  for (i = settings->begin(); i != settings->end(); ++i)
302  {
303  typeName = i->first;
304  archName = i->second;
305  Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
306  archName, typeName, secName);
307  }
308  }
309  std::cout << "##################### add resources" << std::endl;
310  //Add optionnal resources (given by the user).
311  for(std::list<std::string>::const_iterator iter = mOptionnalResourceLocation.begin(); iter != mOptionnalResourceLocation.end(); ++iter){
312  Ogre::ResourceGroupManager::getSingleton().addResourceLocation(*iter, "FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
313  }
314 
315  // Create the window
316  bool canInit = true;
317  if(mshowConfigDialog){
318  mRoot->restoreConfig();
319  if(!mRoot->showConfigDialog())
320  canInit = false;
321  }
322  else{
323  if(!mRoot->restoreConfig())
324  canInit = false;
325  }
326 
327  if(!mRoot->isInitialised()){
328  if(!canInit){ //We set the default renderer system
329  const Ogre::RenderSystemList& lRenderSystemList = mRoot->getAvailableRenderers();
330  if( lRenderSystemList.size() == 0 )
331  throw "ConfigDialog aborted"; // Exit the application on cancel
332 
333  Ogre::RenderSystem *lRenderSystem = lRenderSystemList.at(0);
334  std::cout << "Using " << lRenderSystem->getName() << " as renderer." << std::endl;
335  mRoot->setRenderSystem(lRenderSystem);
336  }
337 
338  mRoot->initialise(false);
339  }
340 
341  bool fullscreen = false;
342  Ogre::NameValuePairList misc;
343  Ogre::ConfigOptionMap config = mRoot->getRenderSystem()->getConfigOptions();
344  Ogre::ConfigOptionMap::const_iterator it = config.begin();
345 
346  while( it != config.end() ){
347  Ogre::String leftconf = (*it).first;
348  Ogre::String rightconf = (*it).second.currentValue;
349 
350  if(leftconf == "Video Mode"){
351  if(canInit) {
352  int ret = sscanf(rightconf.c_str(), "%d %*s %d", &mWindowWidth, &mWindowHeight);
353  if (ret == 0)
354  std::cout << "Cannot read Ogre video mode" << std::endl;
355  }
356  else{
357  if(mWindowWidth == 0 && mWindowHeight == 0){
360  }
361  }
362  }
363  else if( leftconf == "Full Screen" ){
364  if(canInit){
365  if(rightconf == "Yes") fullscreen = true;
366  }
367  }
368  else
369  misc[leftconf] = rightconf;
370 
371  it++;
372  }
373 
374  // With Ogre version >= 1.8.1 we hide the window
375  if( hidden ){
376 #if ( OGRE_VERSION >= (1 << 16 | 8 << 8 | 1) )
377  misc["hidden"] = "true";
378  windowHidden = true;
379 #endif
380  }
381  mWindow = mRoot->createRenderWindow(name, mWindowWidth, mWindowHeight, fullscreen, &misc);
382 
383  // Initialise resources
384  Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
385  //-----------------------------------------------------
386  // 4 Create the SceneManager
387  //
388  // ST_GENERIC = octree
389  // ST_EXTERIOR_CLOSE = simple terrain
390  // ST_EXTERIOR_FAR = nature terrain (depreciated)
391  // ST_EXTERIOR_REAL_FAR = paging landscape
392  // ST_INTERIOR = Quake3 BSP
393  //-----------------------------------------------------
394 
395  mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC);
396 
397  // Create the camera
398  createCamera();
399 
400  // Create a viewport
401  Ogre::Viewport* viewPort = mWindow->addViewport(mCamera);
402 // Ogre::Viewport* viewPort = mCamera->getViewport();
403  viewPort->setClearEveryFrame(true);
404  // Set the projection parameters to match the camera intrinsic parameters
406 
407  // Create the 3D scene
408  createScene();
409 
410  // Initialise and register event handlers
411  mRoot->addFrameListener(this);
412 
413  // Register as a Window listener
414  Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
415 
416 #ifdef VISP_HAVE_OIS
417  // Initialise OIS
418  Ogre::LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
419  OIS::ParamList pl;
420 
421  size_t windowHnd = 0;
422  std::ostringstream windowHndStr;
423  // Initialise window
424  mWindow->getCustomAttribute("WINDOW", &windowHnd);
425  windowHndStr << windowHnd;
426  pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
427  // Let the user use the keyboard elsewhere
428 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
429  pl.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
430 #endif
431 
432  mInputManager = OIS::InputManager::createInputSystem( pl );
433 
434  //Create all devices
435  // Here we only consider the keyboard input
436  mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, bufferedKeys ));
437  if ( !bufferedKeys ) mKeyboard->setEventCallback ( this);
438 #endif
439 
440  // Initialise a render to texture to be able to retrieve a screenshot
441  Ogre::TexturePtr Texture = Ogre::TextureManager::getSingleton().createManual("rtf", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,Ogre::TEX_TYPE_2D,
442  mWindow->getWidth(),mWindow->getHeight(), 0, Ogre::PF_R8G8B8A8, Ogre::TU_RENDERTARGET);
443 
444 
445 
446 // Ogre::TexturePtr Texture = Ogre::TextureManager::getSingleton().createManual("rtf", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,Ogre::TEX_TYPE_2D,
447 // 640,480, 0, Ogre::PF_R8G8B8A8, Ogre::TU_RENDERTARGET);
448  Ogre::RenderTexture* RTarget = Texture->getBuffer()->getRenderTarget();
449  /*Ogre::Viewport* Viewport =*/ RTarget->addViewport(mCamera);
450  RTarget->getViewport(0)->setClearEveryFrame(true);
451  RTarget->getViewport(0)->setOverlaysEnabled(false);
452 }
453 
458 {
459  // Destroy 3D scene
460  destroyScene();
461  // Close OIS
462  closeOIS();
463 
464  if ( mWindow) {
465  Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this);
467  }
468  // Delete root
469  if (mRoot) delete mRoot;
470 }
471 
477 bool vpAROgre::stopTest(const Ogre::FrameEvent& evt)
478 {
479  // Always keep this part
480  if(keepOn){
481  return updateScene(evt);
482  }
483  else
484  return keepOn;
485 }
486 
496 bool vpAROgre::frameStarted(const Ogre::FrameEvent& evt)
497 {
498  // custom method telling what to do at the beginning of each frame
499  bool result = customframeStarted(evt);
500 
501  // Listen to the window
502  Ogre::WindowEventUtilities::messagePump();
503  processInputEvent(evt);
504 
505  // See if we have to stop rendering
506  if(result) return stopTest(evt);
507  else return result;
508 }
509 
510 
517 bool vpAROgre::frameEnded(const Ogre::FrameEvent& evt)
518 {
519  // custom method telling what to do at the end of each frame
520  bool result = customframeEnded(evt);
521 
522  // See if we have to stop rendering
523  if(result) return stopTest(evt);
524  else return result;
525 }
526 
535 bool vpAROgre::customframeStarted(const Ogre::FrameEvent& /*evt*/)
536 {
537  // See if window was closed
538  if(mWindow->isClosed()) return false;
539 
540 #ifdef VISP_HAVE_OIS
541  // Get keyboard input
542  mKeyboard->capture();
543  if(mKeyboard->isKeyDown(OIS::KC_ESCAPE))
544  return false;
545 #endif
546  return true;
547 }
548 
549 
555 bool vpAROgre::customframeEnded(const Ogre::FrameEvent& /*evt*/){return true;}
556 
567 void vpAROgre::windowClosed(Ogre::RenderWindow* rw)
568 {
569  //Only close for window that created OIS (the main window in these demos)
570  if( rw == mWindow ) closeOIS();
571 }
572 
579  const vpHomogeneousMatrix &cMw)
580 {
581  // Update the background to match the situation
583 
584  // Update the camera parameters to match the grabbed image
586 
587  // Display on Ogre Window
588  return mRoot->renderOneFrame();
589 }
590 
597  const vpHomogeneousMatrix &cMw)
598 {
599  // Update the background to match the situation
601 
602  // Update the camera parameters to match the grabbed image
604 
605  // Display on Ogre Window
606  return mRoot->renderOneFrame();
607 }
608 
615  const vpHomogeneousMatrix &cMw)
616 {
617  // Display on Ogre Window
618  if(renderOneFrame(I,cMw)){
619  mWindow->update();
620  keepOn = true;
621  }
622  else
623  keepOn = false;
624 }
625 
632 {
633  // Display on Ogre Window
634  if(renderOneFrame(I,cMw)){
635  mWindow->update();
636  keepOn = true;
637  }
638  else
639  keepOn = false;
640 }
641 
647 {
648  return keepOn;
649 }
650 
655 {
656  mcam = cameraP;
657 }
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,
678  const vpTranslationVector &wTo)
679 {
680  // Reset the position
681  Ogre::SceneNode *node = mSceneMgr->getSceneNode(sceneName);
682  node->setPosition((Ogre::Real)wTo[0], (Ogre::Real)wTo[1], (Ogre::Real)wTo[2]);
683 }
684 
690 vpTranslationVector vpAROgre::getPosition(const std::string &sceneName)const
691 {
692  Ogre::Vector3 translation = mSceneMgr->getSceneNode(sceneName)->getPosition();
693  return vpTranslationVector((Ogre::Real)translation[0], (Ogre::Real)translation[1], (Ogre::Real)translation[2]);
694 }
695 
701 void vpAROgre::setRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
702 {
703  // Get the node in its original position
704  mSceneMgr->getSceneNode(sceneName)->resetOrientation();
705  // Apply the new rotation
706  Ogre::Matrix3 rotationOgre
707  = 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
723  = Ogre::Matrix3( (Ogre::Real)wRo[0][0], (Ogre::Real)wRo[0][1], (Ogre::Real)wRo[0][2],
724  (Ogre::Real)wRo[1][0], (Ogre::Real)wRo[1][1], (Ogre::Real)wRo[1][2],
725  (Ogre::Real)wRo[2][0], (Ogre::Real)wRo[2][1], (Ogre::Real)wRo[2][2]);
726  Ogre::Quaternion q(rotationOgre);
727  mSceneMgr->getSceneNode(sceneName)->rotate(q);
728 }
729 
738 void vpAROgre::setPosition(const std::string &sceneName, const vpHomogeneousMatrix &wMo)
739 {
740  // Extract the position and orientation data
741  vpRotationMatrix rotations;
742  vpTranslationVector translation;
743  wMo.extract(rotations);
744  wMo.extract(translation);
745  // Apply them to the node
746  setPosition(sceneName, translation);
747  setRotation(sceneName, rotations);
748 }
749 
755 void vpAROgre::setVisibility(const std::string &sceneName, bool isVisible)
756 {
757  mSceneMgr->getSceneNode(sceneName)->setVisible(isVisible);
758 }
759 
767 void vpAROgre::setScale(const std::string &sceneName, const float factorx, const float factory, const float factorz)
768 {
769  // Reset the scale to its original value
770  mSceneMgr->getSceneNode(sceneName)->scale(Ogre::Vector3(1,1,1)/mSceneMgr->getSceneNode(sceneName)->getScale());
771  // Apply the new scale
772  mSceneMgr->getSceneNode(sceneName)->scale(Ogre::Vector3(factorx, factory, factorz));
773 }
774 
779 {
780  mCamera = mSceneMgr->createCamera("Camera");
781 }
782 
788 void vpAROgre::createBackground(vpImage<unsigned char> & /* I */)
789 {
790  // Create a rectangle to show the incoming images from the camera
791  mBackground = new Ogre::Rectangle2D(true); // true = textured
792  mBackground->setCorners(-1.0, 1.0, 1.0, -1.0); // Spread all over the window
793  mBackground->setBoundingBox(Ogre::AxisAlignedBox(-100000.0*Ogre::Vector3::UNIT_SCALE, 100000.0*Ogre::Vector3::UNIT_SCALE)); // To be shown everywhere
794 
795  // Texture options
796  Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_NONE);
797  Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(1);
798 
799  // Dynamic texture
800  // If we are using opengl we can boost a little bit performances with a dynamic texture
801  if(mRoot->getRenderSystem()->getName() == "OpenGL Rendering Subsystem") {
802  Ogre::TextureManager::getSingleton().createManual("BackgroundTexture",
803  Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
804  Ogre::TEX_TYPE_2D,
805  mBackgroundWidth,//width
806  mBackgroundHeight,//height
807  0, // num of mip maps
808  Ogre::PF_BYTE_L,
809  Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
810  }
811  else{
812  Ogre::TextureManager::getSingleton().createManual("BackgroundTexture",
813  Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
814  Ogre::TEX_TYPE_2D,
815  mBackgroundWidth,//width
816  mBackgroundHeight,//height
817  0, // num of mip maps
818  Ogre::PF_BYTE_L,
819  Ogre::TU_DEFAULT);
820  }
821 
822  // Pointer to the dynamic texture
823  Ogre::TexturePtr dynTexPtr = Ogre::TextureManager::getSingleton().getByName("BackgroundTexture");
824 //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
825 // .dynamicCast<Ogre::Texture>();// Get the pixel buffer
826 //#else
827 // ;
828 //#endif
829  mPixelBuffer = dynTexPtr->getBuffer();
830 
831  // Material to apply the texture to the background
832  Ogre::MaterialPtr Backgroundmaterial
833  = Ogre::MaterialManager::getSingleton().create("BackgroundMaterial",
834  Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
835 //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
836 // .dynamicCast<Ogre::Material>();
837 //#else
838 // ;
839 //#endif
840  Ogre::Technique *Backgroundtechnique = Backgroundmaterial->createTechnique();
841  Backgroundtechnique->createPass();
842  Backgroundmaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
843  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); // Background
844  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); // Background
845  Backgroundmaterial->getTechnique(0)->getPass(0)->createTextureUnitState("BackgroundTexture");
846  mBackground->setMaterial("BackgroundMaterial"); // Attach the material to the rectangle
847  mBackground->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND); // To be rendered in Background
848 
849  // Add the background to the Scene Graph so it will be rendered
850  Ogre::SceneNode *BackgroundNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("BackgoundNode");
851  BackgroundNode->attachObject(mBackground);
852 }
853 
859 void vpAROgre::createBackground(vpImage<vpRGBa> & /* I */)
860 {
861  // Create a rectangle to show the incoming images from the camera
862  mBackground = new Ogre::Rectangle2D(true); // true = textured
863  mBackground->setCorners(-1.0, 1.0, 1.0, -1.0); // Spread all over the window
864  mBackground->setBoundingBox(Ogre::AxisAlignedBox(-100000.0*Ogre::Vector3::UNIT_SCALE, 100000.0*Ogre::Vector3::UNIT_SCALE)); // To be shown everywhere
865 
866  // Texture options
867  Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_NONE);
868  Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(1);
869 
870  // Dynamic texture
871  // If we are using opengl we can boost a little bit performances with a dynamic texture
872  if(mRoot->getRenderSystem()->getName() == "OpenGL Rendering Subsystem") {
873  Ogre::TextureManager::getSingleton().createManual("BackgroundTexture",
874  Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
875  Ogre::TEX_TYPE_2D,
876  mBackgroundWidth,//width
877  mBackgroundHeight,//height
878  0, // num of mip maps
879  //Ogre::PF_BYTE_RGBA,
880  Ogre::PF_BYTE_BGRA,
881  Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
882  }
883  else{ // As that texture does not seem to work properly with direct3D we use a default texture
884  Ogre::TextureManager::getSingleton().createManual("BackgroundTexture",
885  Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
886  Ogre::TEX_TYPE_2D,
887  mBackgroundWidth,//width
888  mBackgroundHeight,//height
889  0, // num of mip maps
890  //Ogre::PF_BYTE_RGBA,
891  Ogre::PF_BYTE_BGRA,
892  Ogre::TU_DEFAULT);
893  }
894 
895 
896  // Pointer to the dynamic texture
897  Ogre::TexturePtr dynTexPtr =
898  Ogre::TextureManager::getSingleton().getByName("BackgroundTexture");
899 //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
900 // .dynamicCast<Ogre::Texture>();// Get the pixel buffer
901 //#else
902 // ;
903 //#endif
904 
905  // Get the pixel buffer
906  mPixelBuffer = dynTexPtr->getBuffer();
907 
908  // Material to apply the texture to the background
909  Ogre::MaterialPtr Backgroundmaterial
910  = Ogre::MaterialManager::getSingleton().create("BackgroundMaterial",
911  Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
912 //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
913 // .dynamicCast<Ogre::Material>();
914 //#else
915 // ;
916 //#endif
917  Ogre::Technique *Backgroundtechnique = Backgroundmaterial->createTechnique();
918  Backgroundtechnique->createPass();
919  Backgroundmaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
920  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); // Background
921  Backgroundmaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); // Background
922  Backgroundmaterial->getTechnique(0)->getPass(0)->createTextureUnitState("BackgroundTexture");
923  mBackground->setMaterial("BackgroundMaterial"); // Attach the material to the rectangle
924  mBackground->setRenderQueueGroup(Ogre::RENDER_QUEUE_BACKGROUND); // To be rendered in Background
925 
926  // Add the background to the Scene Graph so it will be rendered
927  Ogre::SceneNode *BackgroundNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("BackgoundNode");
928  BackgroundNode->attachObject(mBackground);
929 }
930 
939 {
940 #ifdef VISP_HAVE_OIS
941  if( mInputManager )
942  {
943  mInputManager->destroyInputObject( mKeyboard );
944 
945  OIS::InputManager::destroyInputSystem(mInputManager);
946  mInputManager = 0;
947  }
948 #endif
949 }
950 
954 // Note: equation taken from:
955 // http://strawlab.org/2011/11/05/augmented-reality-with-OpenGL/
957 {
958  if(mCamera != 0){
959  Ogre::Real f,n,f_m_n,f_p_n,px,py,u0,v0;
960  f = (Ogre::Real)(mFarClipping); // Far clip distance
961  n = (Ogre::Real)(mNearClipping); // Near clip distance
962  f_m_n = (Ogre::Real)(f-n);
963  f_p_n = (Ogre::Real)(f+n);
964  px = (Ogre::Real)mcam.get_px();
965  py = (Ogre::Real)mcam.get_py();
966  u0 = (Ogre::Real)mcam.get_u0();
967  v0 = (Ogre::Real)mcam.get_v0();
968  Ogre::Matrix4 Projection
969  = Ogre::Matrix4( (Ogre::Real)(2.0*px/mBackgroundWidth), 0, (Ogre::Real)(1.0 - 2.0*(u0/mBackgroundWidth)), 0,
970  0, (Ogre::Real)(2.0*py/mBackgroundHeight), (Ogre::Real)(-1.0 + 2.0*(v0/mBackgroundHeight)),0,
971  0, 0, (Ogre::Real)(-1.0*f_p_n/f_m_n), (Ogre::Real)(-2.0*f*n/f_m_n),
972  0, 0, -1.0, 0);
973  mCamera->setCustomProjectionMatrix(true, Projection);
974  }
975 }
976 
981 {
982  // Inspired from Ogre wiki : http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures
983  // Lock the pixel buffer and get a pixel box. HBL_DISCARD is to use for best
984  // performance than HBL_NORMAL
985  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); // Lock the buffer
986  const Ogre::PixelBox& pixelBox = mPixelBuffer->getCurrentLock();
987  // Buffer data
988  Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);
989  // Fill in the data in the grey level texture
990  memcpy(pDest, I.bitmap, mBackgroundHeight*mBackgroundWidth);
991 
992  // Unlock the pixel buffer
993  mPixelBuffer->unlock();
994 }
995 
1000 {
1001  // Inspired from Ogre wiki : http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures
1002  // Lock the pixel buffer and get a pixel box. HBL_DISCARD is to use for best
1003  // performance than HBL_NORMAL
1004  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); // Lock the buffer
1005  const Ogre::PixelBox& pixelBox = mPixelBuffer->getCurrentLock();
1006  // Buffer data
1007  Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);
1008  // Fill in the data in the grey level texture
1009 #if 1 // if texture in BGRa format
1010  for(unsigned int i=0; i<mBackgroundHeight; i++){
1011  for(unsigned int j=0; j<mBackgroundWidth; j++){
1012  // Color Image
1013 // *pDest++=I[i][mBackgroundWidth-j].B; // Blue component
1014 // *pDest++=I[i][mBackgroundWidth-j].G; // Green component
1015 // *pDest++=I[i][mBackgroundWidth-j].R; // Red component
1016 
1017  *pDest++=I[i][j].B; // Blue component
1018  *pDest++=I[i][j].G; // Green component
1019  *pDest++=I[i][j].R; // Red component
1020 
1021  *pDest++ = 255; // Alpha component
1022  }
1023  }
1024 #else // if texture in RGBa format which is the format of the input image
1025  memcpy(pDest, I.bitmap, mBackgroundHeight*mBackgroundWidth*sizeof(vpRGBa));
1026 #endif
1027 
1028  // Unlock the pixel buffer
1029  mPixelBuffer->unlock();
1030 }
1031 
1036 {
1037  // The matrix is given to Ogre with some changes to fit with the world projection
1038  Ogre::Matrix4 ModelView
1039 // = Ogre::Matrix4( (Ogre::Real)-cMo[0][0], (Ogre::Real)-cMo[0][1], (Ogre::Real)-cMo[0][2], (Ogre::Real)-cMo[0][3],
1040  = Ogre::Matrix4( (Ogre::Real)cMw[0][0], (Ogre::Real)cMw[0][1], (Ogre::Real)cMw[0][2], (Ogre::Real)cMw[0][3],
1041  (Ogre::Real)-cMw[1][0], (Ogre::Real)-cMw[1][1], (Ogre::Real)-cMw[1][2], (Ogre::Real)-cMw[1][3],
1042  (Ogre::Real)-cMw[2][0], (Ogre::Real)-cMw[2][1], (Ogre::Real)-cMw[2][2], (Ogre::Real)-cMw[2][3],
1043  (Ogre::Real)0, (Ogre::Real)0, (Ogre::Real)0, (Ogre::Real)1);
1044  mCamera->setCustomViewMatrix(true, ModelView);
1045 }
1046 
1054 {
1056  Ogre::TexturePtr dynTexPtr = Ogre::TextureManager::getSingleton().getByName("rtf");
1057 //#if ( OGRE_VERSION >= (1 << 16 | 9 << 8 | 0) )
1058 // .dynamicCast<Ogre::Texture>();
1059 //#else
1060 // ;
1061 //#endif
1062  Ogre::RenderTexture* RTarget = dynTexPtr->getBuffer()->getRenderTarget();
1063  mWindow->update();
1064  RTarget->update();
1065  if(I.getHeight() != mWindow->getHeight() || I.getWidth() != mWindow->getWidth()){
1066  I.resize(mWindow->getHeight(), mWindow->getWidth());
1067  }
1068  Ogre::HardwarePixelBufferSharedPtr mPixelBuffer = dynTexPtr->getBuffer();
1069  mPixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
1070  const Ogre::PixelBox& pixelBox = mPixelBuffer->getCurrentLock();
1071  dynTexPtr->getBuffer()->blitToMemory(pixelBox);
1072  Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);
1073 #if 1 // if texture in BGRa format
1074  for(unsigned int i=0; i<I.getHeight(); i++){
1075  for(unsigned int j=0; j<I.getWidth(); j++){
1076  // Color Image
1077  I[i][j].B = *pDest++; // Blue component
1078  I[i][j].G = *pDest++; // Green component
1079  I[i][j].R = *pDest++; // Red component
1080  I[i][j].A = *pDest++; // Alpha component
1081  }
1082  }
1083 #else // if texture in RGBa format which is the format of the input image
1084  memcpy(I.bitmap, pDest, I.getHeight()*I.getWidth()*sizeof(vpRGBa));
1085 #endif
1086 
1087  // Unlock the pixel buffer
1088  mPixelBuffer->unlock();
1089 
1090 }
1091 
1092 
1093 #elif !defined(VISP_BUILD_SHARED_LIBS)
1094 // Work arround to avoid warning: libvisp_ar.a(vpAROgre.cpp.o) has no symbols
1095 void dummy_vpAROgre() {};
1096 #endif
1097 
virtual void updateBackgroundTexture(const vpImage< unsigned char > &I)
Definition: vpAROgre.cpp:980
void setRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
Definition: vpAROgre.cpp:701
bool keepOn
Definition: vpAROgre.h:368
void addRotation(const std::string &sceneName, const vpRotationMatrix &wRo)
Definition: vpAROgre.cpp:719
bool mshowConfigDialog
Definition: vpAROgre.h:384
double get_u0() const
Ogre::String name
Definition: vpAROgre.h:351
unsigned int getWidth() const
Definition: vpImage.h:161
vpTranslationVector getPosition(const std::string &sceneName) const
Definition: vpAROgre.cpp:690
unsigned int mWindowWidth
Definition: vpAROgre.h:376
Ogre::String mPluginsPath
Definition: vpAROgre.h:359
unsigned int mBackgroundWidth
Definition: vpAROgre.h:374
Implementation of an homogeneous matrix and operations on such kind of matrices.
virtual bool customframeEnded(const Ogre::FrameEvent &evt)
Definition: vpAROgre.cpp:555
Type * bitmap
points toward the bitmap
Definition: vpImage.h:116
virtual bool destroyScene(void)
Definition: vpAROgre.h:319
Ogre::String mResourcePath
Definition: vpAROgre.h:358
error that can be emited by ViSP classes.
Definition: vpException.h:73
virtual void createCamera(void)
Definition: vpAROgre.cpp:778
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:71
OIS::Keyboard * mKeyboard
Definition: vpAROgre.h:364
double get_py() const
bool renderOneFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMw)
Definition: vpAROgre.cpp:578
bool continueRendering(void)
Definition: vpAROgre.cpp:646
virtual void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMw)
Definition: vpAROgre.cpp:614
Class that defines a RGB 32 bits structure.
Definition: vpRGBa.h:64
Ogre::RenderWindow * mWindow
Definition: vpAROgre.h:357
OIS::InputManager * mInputManager
Definition: vpAROgre.h:363
Implementation of a rotation matrix and operations on such kind of matrices.
virtual void updateCameraParameters(const vpHomogeneousMatrix &cMo)
Definition: vpAROgre.cpp:1035
static bool checkFilename(const char *filename)
Definition: vpIoTools.cpp:485
void setVisibility(const std::string &sceneName, bool isVisible)
Definition: vpAROgre.cpp:755
double get_v0() const
virtual void init(vpImage< unsigned char > &I, bool bufferedKeys=false, bool hidden=false)
Definition: vpAROgre.cpp:115
vpCameraParameters mcam
Definition: vpAROgre.h:382
virtual bool processInputEvent(const Ogre::FrameEvent &)
Definition: vpAROgre.h:312
void setCameraParameters(const vpCameraParameters &cameraP)
Definition: vpAROgre.cpp:654
virtual ~vpAROgre(void)
Definition: vpAROgre.cpp:457
Ogre::Camera * mCamera
Definition: vpAROgre.h:355
void setScale(const std::string &sceneName, const float factorx, const float factory, const float factorz)
Definition: vpAROgre.cpp:767
Generic class defining intrinsic camera parameters.
virtual void closeOIS(void)
Definition: vpAROgre.cpp:938
virtual bool updateScene(const Ogre::FrameEvent &)
Definition: vpAROgre.h:305
virtual void windowClosed(Ogre::RenderWindow *rw)
Definition: vpAROgre.cpp:567
unsigned int mWindowHeight
Definition: vpAROgre.h:375
void resize(const unsigned int h, const unsigned int w)
set the size of the image without initializing it.
Definition: vpImage.h:616
bool windowHidden
Definition: vpAROgre.h:377
void extract(vpRotationMatrix &R) const
void getRenderingOutput(vpImage< vpRGBa > &I, const vpHomogeneousMatrix &cMo)
Definition: vpAROgre.cpp:1053
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:1477
void load(const std::string &entityName, const std::string &model)
Definition: vpAROgre.cpp:664
virtual bool customframeStarted(const Ogre::FrameEvent &evt)
Definition: vpAROgre.cpp:535
unsigned int mBackgroundHeight
Definition: vpAROgre.h:373
double get_px() const
virtual void updateCameraProjection(void)
Definition: vpAROgre.cpp:956
Ogre::Root * mRoot
Definition: vpAROgre.h:354
double mFarClipping
Definition: vpAROgre.h:381
Ogre::HardwarePixelBufferSharedPtr mPixelBuffer
Definition: vpAROgre.h:371
Ogre::Rectangle2D * mBackground
Definition: vpAROgre.h:372
virtual void createScene(void)
Definition: vpAROgre.h:296
void setPosition(const std::string &sceneName, const vpTranslationVector &wTo)
Definition: vpAROgre.cpp:677
Ogre::SceneManager * mSceneMgr
Definition: vpAROgre.h:356
unsigned int getHeight() const
Definition: vpImage.h:152
double mNearClipping
Definition: vpAROgre.h:380
std::list< std::string > mOptionnalResourceLocation
Definition: vpAROgre.h:386
Class that consider the case of a translation vector.