ViSP  2.10.0
vpMbHiddenFaces.h
1 /****************************************************************************
2  *
3  * $Id: vpMbTracker.h 4004 2012-11-23 17:34:44Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  * Description:
34  * Generic model based tracker. This class declares the methods to implement in
35  * order to have a model based tracker.
36  *
37  * Authors:
38  * Romain Tallonneau
39  * Aurelien Yol
40  *
41  *****************************************************************************/
42 #pragma once
43 
44 #ifndef vpMbHiddenFaces_HH
45 #define vpMbHiddenFaces_HH
46 
47 #include <visp/vpHomogeneousMatrix.h>
48 #include <visp/vpMeterPixelConversion.h>
49 #include <visp/vpPixelMeterConversion.h>
50 #include <visp/vpMbtPolygon.h>
51 
52 #ifdef VISP_HAVE_OGRE
53  #include <visp/vpAROgre.h>
54 #endif
55 
56 #include <vector>
57 #include <limits>
58 
67 template<class PolygonType = vpMbtPolygon>
69 {
70  private:
72  std::vector<PolygonType *> Lpol ;
74  unsigned int nbVisiblePolygon;
75 
76 #ifdef VISP_HAVE_OGRE
77  vpImage<unsigned char> ogreBackground;
78  bool ogreInitialised;
79  vpAROgre *ogre;
80  std::vector< Ogre::ManualObject* > lOgrePolygons;
81 #endif
82 
83  unsigned int setVisiblePrivate(const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears,
84  bool &changed,
85  bool useOgre = false, bool testRoi = false,
87  const vpCameraParameters &cam = vpCameraParameters()) ;
88 
89  public :
90  vpMbHiddenFaces() ;
92 
93  void addPolygon(PolygonType *p) ;
94 
95  bool computeVisibility(const vpHomogeneousMatrix &cMo,
96  const double &angleAppears, const double &angleDisappears,
97  bool &changed, bool useOgre, bool testRoi,
98  const vpImage<unsigned char> &I,
99  const vpCameraParameters &cam,
100  const vpTranslationVector &cameraPos,
101  unsigned int index);
102 #ifdef VISP_HAVE_OGRE
103  void displayOgre(const vpHomogeneousMatrix &cMo);
104 #endif
105 
111  std::vector<PolygonType*>& getPolygon() {return Lpol;}
112 
113 #ifdef VISP_HAVE_OGRE
114  void initOgre(const vpCameraParameters &cam = vpCameraParameters());
115 #endif
116 
122  unsigned int getNbVisiblePolygon() const {return nbVisiblePolygon;}
123 
124 #ifdef VISP_HAVE_OGRE
125 
130  vpAROgre* getOgreContext(){return ogre;}
131 #endif
132 
133  bool isAppearing(const unsigned int i){ return Lpol[i]->isAppearing(); }
134 
135 
136 #ifdef VISP_HAVE_OGRE
137 
142  bool isOgreInitialised() { return ogreInitialised; }
143 #endif
144 
152  bool isVisible(const unsigned int i){ return Lpol[i]->isVisible(); }
153 
154 #ifdef VISP_HAVE_OGRE
155  bool isVisibleOgre(const vpTranslationVector &cameraPos, const unsigned int &index);
156 #endif
157 
159  inline PolygonType* operator[](const unsigned int i) { return Lpol[i];}
161  inline const PolygonType* operator[](const unsigned int i) const { return Lpol[i];}
162 
163  void reset();
164 
165 #ifdef VISP_HAVE_OGRE
166 
175  void setBackgroundSizeOgre(const unsigned int &h, const unsigned int &w) { ogreBackground = vpImage<unsigned char>(h, w, 0); }
176 #endif
177 
178  unsigned int setVisible(const vpImage<unsigned char>& I, const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo, const double &angle, bool &changed) ;
179  unsigned int setVisible(const vpImage<unsigned char>& I, const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears, bool &changed) ;
180  unsigned int setVisible(const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears, bool &changed) ;
181 
182 #ifdef VISP_HAVE_OGRE
183  unsigned int setVisibleOgre(const vpImage<unsigned char>& I, const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears, bool &changed) ;
184  unsigned int setVisibleOgre(const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears, bool &changed) ;
185 #endif
186 
191  inline unsigned int size() const { return (unsigned int)Lpol.size(); }
192 
193 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
194  bool depthTest;
196 
207  vp_deprecated bool getDepthTest(){return depthTest;}
215  vp_deprecated void setDepthTest(const bool &d){depthTest = d;}
216  unsigned int setVisible(const vpHomogeneousMatrix &cMo) ;
217 #endif
218 } ;
219 
223 template<class PolygonType>
225  : Lpol(), nbVisiblePolygon(0)
226 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
227  , depthTest(false)
228 #endif
229 
230 {
231 #ifdef VISP_HAVE_OGRE
232  ogreInitialised = false;
233  ogre = new vpAROgre();
234  ogre->setShowConfigDialog(false);
235  ogreBackground = vpImage<unsigned char>(480, 640, 0);
236 #endif
237 }
238 
242 template<class PolygonType>
244 {
245  for(unsigned int i = 0 ; i < Lpol.size() ; i++){
246  if (Lpol[i]!=NULL){
247  delete Lpol[i] ;
248  }
249  Lpol[i] = NULL ;
250  }
251  Lpol.resize(0);
252 
253 #ifdef VISP_HAVE_OGRE
254  if(ogre != NULL){
255  delete ogre;
256  ogre = NULL;
257  }
258 
259  // This is already done by calling "delete ogre"
260 // for(unsigned int i = 0 ; i < lOgrePolygons.size() ; i++){
261 // if (lOgrePolygons[i]!=NULL){
262 // delete lOgrePolygons[i] ;
263 // }
264 // lOgrePolygons[i] = NULL ;
265 // }
266 
267  lOgrePolygons.resize(0);
268 #endif
269 }
270 
276 template<class PolygonType>
277 void
279 {
280  PolygonType *p_new = new PolygonType;
281  p_new->index = p->index;
282  p_new->setNbPoint(p->nbpt);
283  p_new->isvisible = p->isvisible;
284  p_new->useLod = p->useLod;
285  p_new->minLineLengthThresh = p->minLineLengthThresh;
286  p_new->minPolygonAreaThresh = p->minPolygonAreaThresh;
287  p_new->setName(p->name);
288 
289  for(unsigned int i = 0; i < p->nbpt; i++)
290  p_new->p[i]= p->p[i];
291  Lpol.push_back(p_new);
292 }
293 
297 template<class PolygonType>
298 void
300 {
301  nbVisiblePolygon = 0;
302  for(unsigned int i = 0 ; i < Lpol.size() ; i++){
303  if (Lpol[i]!=NULL){
304  delete Lpol[i] ;
305  }
306  Lpol[i] = NULL ;
307  }
308  Lpol.resize(0);
309 
310 #ifdef VISP_HAVE_OGRE
311  if(ogre != NULL){
312  delete ogre;
313  ogre = NULL;
314  }
315 
316  // This is already done by calling "delete ogre"
317 // for(unsigned int i = 0 ; i < lOgrePolygons.size() ; i++){
318 // if (lOgrePolygons[i]!=NULL){
319 // delete lOgrePolygons[i] ;
320 // }
321 // lOgrePolygons[i] = NULL ;
322 // }
323 
324  lOgrePolygons.resize(0);
325 
326  ogreInitialised = false;
327  ogre = new vpAROgre();
328  ogre->setShowConfigDialog(false);
329  ogreBackground = vpImage<unsigned char>(480, 640);
330 #endif
331 }
332 
347 template<class PolygonType>
348 unsigned int
350  const double &angleAppears, const double &angleDisappears,
351  bool &changed, bool useOgre, bool testRoi,
352  const vpImage<unsigned char> &I,
353  const vpCameraParameters &cam)
354 {
355  nbVisiblePolygon = 0;
356  changed = false;
357 
358  vpTranslationVector cameraPos;
359 
360  if(useOgre){
361 #ifdef VISP_HAVE_OGRE
362  cMo.inverse().extract(cameraPos);
363  ogre->renderOneFrame(ogreBackground, cMo);
364 #else
365  vpTRACE("ViSP doesn't have Ogre3D, simple visibility test used");
366 #endif
367  }
368 
369  for (unsigned int i = 0; i < Lpol.size(); i++){
370  if (computeVisibility(cMo, angleAppears, angleDisappears, changed, useOgre, testRoi, I, cam, cameraPos, i))
371  nbVisiblePolygon ++;
372  }
373  return nbVisiblePolygon;
374 }
375 
392 template<class PolygonType>
393 bool
395  const double &angleAppears, const double &angleDisappears,
396  bool &changed, bool useOgre, bool /* testRoi */,
397  const vpImage<unsigned char> & I,
398  const vpCameraParameters & cam,
399  const vpTranslationVector &
400  #ifdef VISP_HAVE_OGRE
401  cameraPos
402  #endif
403  ,
404  unsigned int index)
405 {
406  unsigned int i = index;
407  Lpol[i]->changeFrame(cMo);
408  Lpol[i]->isappearing = false;
409 
410  //Commented because we need to compute visibility
411  // even when dealing with line in level of detail case
412  /*if(Lpol[i]->getNbPoint() <= 2)
413  {
414  Lpol[i]->isvisible = true;
415  }
416  else*/{
417  if(Lpol[i]->isVisible())
418  {
419  bool testDisappear = false;
420  unsigned int nbCornerInsidePrev = 0;
421 
422 // if(testRoi){
423 // nbCornerInsidePrev = Lpol[i]->getNbCornerInsidePrevImage();
424 // if(Lpol[i]->getNbCornerInsideImage(I, cam) == 0)
425 // testDisappear = true;
426 // }
427 
428  if(!testDisappear){
429  if(useOgre)
430 #ifdef VISP_HAVE_OGRE
431  testDisappear = ((!Lpol[i]->isVisible(cMo, angleDisappears, true, cam, I)) || !isVisibleOgre(cameraPos,i));
432 #else
433  testDisappear = (!Lpol[i]->isVisible(cMo, angleDisappears, false, cam, I));
434 #endif
435  else
436  testDisappear = (!Lpol[i]->isVisible(cMo, angleDisappears, false, cam, I));
437  }
438 
439  // test if the face is still visible
440  if(testDisappear){
441 // std::cout << "Face " << i << " disappears" << std::endl;
442  changed = true;
443  Lpol[i]->isvisible = false;
444  }
445  else {
446  //nbVisiblePolygon++;
447  Lpol[i]->isvisible = true;
448 
449  if(nbCornerInsidePrev > Lpol[i]->getNbCornerInsidePrevImage())
450  changed = true;
451  }
452  }
453  else
454  {
455  bool testAppear = true;
456 
457 // if(testRoi && Lpol[i]->getNbCornerInsideImage(I, cam) == 0)
458 // testAppear = false;
459 
460  if(testAppear){
461  if(useOgre)
462 #ifdef VISP_HAVE_OGRE
463  testAppear = ((Lpol[i]->isVisible(cMo, angleAppears, true, cam, I)) && isVisibleOgre(cameraPos,i));
464 #else
465  testAppear = (Lpol[i]->isVisible(cMo, angleAppears, false, cam, I));
466 #endif
467  else
468  testAppear = (Lpol[i]->isVisible(cMo, angleAppears, false, cam, I));
469  }
470 
471  if(testAppear){
472 // std::cout << "Face " << i << " appears" << std::endl;
473  Lpol[i]->isvisible = true;
474  changed = true;
475  //nbVisiblePolygon++;
476  }
477  else{
478 // std::cout << "Problem" << std::endl;
479  Lpol[i]->isvisible = false;
480  }
481  }
482  }
483  // std::cout << "Nombre de polygones visibles: " << nbVisiblePolygon << std::endl;
484  return Lpol[i]->isvisible;
485 }
486 
498 template<class PolygonType>
499 unsigned int
500 vpMbHiddenFaces<PolygonType>::setVisible(const vpImage<unsigned char>& I, const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo, const double &angle, bool &changed)
501 {
502  return setVisible(I, cam, cMo, angle, angle, changed);
503 }
504 
517 template<class PolygonType>
518 unsigned int
519 vpMbHiddenFaces<PolygonType>::setVisible(const vpImage<unsigned char>& I, const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears, bool &changed)
520 {
521  return setVisiblePrivate(cMo,angleAppears,angleDisappears,changed,false,true,I,cam);
522 }
523 
534 template<class PolygonType>
535 unsigned int
536 vpMbHiddenFaces<PolygonType>::setVisible(const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears, bool &changed)
537 {
538  return setVisiblePrivate(cMo,angleAppears,angleDisappears,changed,false);
539 }
540 
541 #ifdef VISP_HAVE_OGRE
542 
547 template<class PolygonType>
548 void
550 {
551  ogreInitialised = true;
552  ogre->setCameraParameters(cam);
553  ogre->init(ogreBackground, false, true);
554 
555  for(unsigned int n = 0 ; n < Lpol.size(); n++){
556  Ogre::ManualObject* manual = ogre->getSceneManager()->createManualObject(Ogre::StringConverter::toString(n));
557 
558  manual->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_STRIP);
559  for(unsigned int i = 0; i < Lpol[n]->nbpt; i++){
560  manual->position( (Ogre::Real)Lpol[n]->p[i].get_oX(), (Ogre::Real)Lpol[n]->p[i].get_oY(), (Ogre::Real)Lpol[n]->p[i].get_oZ());
561  manual->colour(1.0, 1.0, 1.0);
562  manual->index(i);
563  }
564 
565  manual->index(0);
566  manual->end();
567 
568  ogre->getSceneManager()->getRootSceneNode()->createChildSceneNode()->attachObject(manual);
569 
570  lOgrePolygons.push_back(manual);
571  }
572 }
573 
579 template<class PolygonType>
580 void
582 {
583  if(ogreInitialised && !ogre->isWindowHidden()){
584  for(unsigned int i = 0 ; i < Lpol.size() ; i++){
585  if(Lpol[i]->isVisible()){
586  lOgrePolygons[i]->setVisible(true);
587  }
588  else
589  lOgrePolygons[i]->setVisible(false);
590  }
591  ogre->display(ogreBackground, cMo);
592  }
593 }
594 
607 template<class PolygonType>
608 unsigned int
609 vpMbHiddenFaces<PolygonType>::setVisibleOgre(const vpImage<unsigned char>& I, const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears, bool &changed)
610 {
611  return setVisiblePrivate(cMo,angleAppears,angleDisappears,changed,true,true,I,cam);
612 }
613 
624 template<class PolygonType>
625 unsigned int
626 vpMbHiddenFaces<PolygonType>::setVisibleOgre(const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears, bool &changed)
627 {
628  return setVisiblePrivate(cMo,angleAppears,angleDisappears,changed,true);
629 }
630 
639 template<class PolygonType>
640 bool
641 vpMbHiddenFaces<PolygonType>::isVisibleOgre(const vpTranslationVector &cameraPos, const unsigned int &index)
642 {
643 // std::cout << "visible" << std::endl;
644  // A line is always visible
645  if(Lpol[index]->getNbPoint() <= 2){
646  lOgrePolygons[index]->setVisible(true);
647  Lpol[index]->isvisible = true;
648  return true;
649  }
650 
651  Ogre::Vector3 camera((Ogre::Real)cameraPos[0],(Ogre::Real)cameraPos[1],(Ogre::Real)cameraPos[2]);
652  if(!ogre->getCamera()->isVisible(lOgrePolygons[index]->getBoundingBox())){
653  lOgrePolygons[index]->setVisible(false);
654  Lpol[index]->isvisible = false;
655  return false;
656  }
657 
658  //Get the center of gravity
659  Ogre::Vector3 origin(0,0,0);
660  for(unsigned int j = 0 ; j < Lpol[index]->getNbPoint() ; j++){
661  Ogre::Vector3 tmp((Ogre::Real)Lpol[index]->getPoint(j).get_oX(), (Ogre::Real)Lpol[index]->getPoint(j).get_oY(), (Ogre::Real)Lpol[index]->getPoint(j).get_oZ());
662  origin += tmp;
663  }
664  origin /= (Ogre::Real)Lpol[index]->getNbPoint();
665  Ogre::Vector3 direction = origin - camera;
666 
667  Ogre::RaySceneQuery *mRaySceneQuery = ogre->getSceneManager()->createRayQuery(Ogre::Ray(camera, direction));
668  mRaySceneQuery->setSortByDistance(true);
669 
670  Ogre::RaySceneQueryResult &result = mRaySceneQuery->execute();
671  Ogre::RaySceneQueryResult::iterator it = result.begin();
672 
673  bool visible = false;
674  double distance, distancePrev;
675  if(it != result.end()){
676  if(it->movable->getName().find("SimpleRenderable") != Ogre::String::npos) //Test if the ogreBackground is intersect in first
677  it++;
678 
679  if(it != result.end()){
680  distance = it->distance;
681  distancePrev = distance;
682  if(it->movable->getName() == Ogre::StringConverter::toString(index)){
683  visible = true;
684  }
685  else{
686  it++;
687  while(!visible && it != result.end()){
688  distance = it->distance;
689  //if(distance == distancePrev){
690  if(std::fabs(distance - distancePrev) < distance * std::numeric_limits<double>::epsilon()){
691  if(it->movable->getName() == Ogre::StringConverter::toString(index)){
692  visible = true;
693  break;
694  }
695  it++;
696  distancePrev = distance;
697  }
698  else
699  break;
700  }
701  }
702  }
703  }
704 
705  if(visible){
706  lOgrePolygons[index]->setVisible(true);
707  Lpol[index]->isvisible = true;
708  }
709  else{
710  lOgrePolygons[index]->setVisible(false);
711  Lpol[index]->isvisible = false;
712  }
713 
714  ogre->getSceneManager()->destroyQuery(mRaySceneQuery);
715 
716  return Lpol[index]->isvisible;
717 }
718 #endif //VISP_HAVE_OGRE
719 
720 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
721 
730 template<class PolygonType>
731 unsigned int
733 {
734  nbVisiblePolygon = 0 ;
735 
736  for(unsigned int i = 0 ; i < Lpol.size() ; i++){
737  if (Lpol[i]->isVisible(cMo, depthTest)){
738  nbVisiblePolygon++;
739  }
740  }
741  return nbVisiblePolygon ;
742 }
743 #endif //VISP_BUILD_DEPRECATED_FUNCTIONS
744 
745 #endif // vpMbHiddenFaces
746 
const PolygonType * operator[](const unsigned int i) const
operator[] as reader.
bool isAppearing(const unsigned int i)
Implementation of the polygons management for the model-based trackers.
Ogre::Camera * getCamera()
Definition: vpAROgre.h:142
The class provides a data structure for the homogeneous matrices as well as a set of operations on th...
#define vpTRACE
Definition: vpDebug.h:418
unsigned int getNbVisiblePolygon() const
void setShowConfigDialog(const bool showConfigDialog)
Definition: vpAROgre.h:255
void setBackgroundSizeOgre(const unsigned int &h, const unsigned int &w)
PolygonType * operator[](const unsigned int i)
operator[] as modifier.
Implementation of an augmented reality viewer.
Definition: vpAROgre.h:90
bool renderOneFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMw)
Definition: vpAROgre.cpp:552
unsigned int setVisibleOgre(const vpImage< unsigned char > &I, const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears, bool &changed)
vp_deprecated void setDepthTest(const bool &d)
Ogre::SceneManager * getSceneManager()
Definition: vpAROgre.h:162
virtual void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMw)
Definition: vpAROgre.cpp:588
bool depthTest
Boolean specifying if a polygon has to be entirely in front of the camera or not. ...
unsigned int setVisible(const vpImage< unsigned char > &I, const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo, const double &angle, bool &changed)
void initOgre(const vpCameraParameters &cam=vpCameraParameters())
bool isVisibleOgre(const vpTranslationVector &cameraPos, const unsigned int &index)
vpAROgre * getOgreContext()
virtual void init(vpImage< unsigned char > &I, bool bufferedKeys=false, bool hidden=false)
Definition: vpAROgre.cpp:119
void setCameraParameters(const vpCameraParameters &cameraP)
Definition: vpAROgre.cpp:628
Generic class defining intrinsic camera parameters.
bool computeVisibility(const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears, bool &changed, bool useOgre, bool testRoi, const vpImage< unsigned char > &I, const vpCameraParameters &cam, const vpTranslationVector &cameraPos, unsigned int index)
void extract(vpRotationMatrix &R) const
void addPolygon(PolygonType *p)
unsigned int size() const
vp_deprecated bool getDepthTest()
vpHomogeneousMatrix inverse() const
bool isWindowHidden()
Definition: vpAROgre.h:172
bool isVisible(const unsigned int i)
void displayOgre(const vpHomogeneousMatrix &cMo)
Class that consider the case of a translation vector.
std::vector< PolygonType * > & getPolygon()