Impostor 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. #ifndef OSGSIM_IMPOSTOR
  14. #define OSGSIM_IMPOSTOR 1
  15. #include <osg/LOD>
  16. #include <osg/buffered_value>
  17. #include <osgUtil/CullVisitor>
  18. #include <osgSim/ImpostorSprite>
  19. namespace osgSim {
  20. /** Impostor - is a form of Level Of Detail group node which allows both switching
  21. * between children depending on distance from eye point and image caching.
  22. *
  23. * The principle behind Imposters is that they cache an image of real geometry and then the image is drawn
  24. * in subsequent frames instead of the real geometry. It's a bit like a
  25. * Billboard *but* is updated at runtime and w.r.t view point. By drawing
  26. * just the texture mapped quad you can cut down scene complexity and
  27. * improve performance.
  28. *
  29. * For more details have a look at:
  30. *
  31. * http://grail.cs.washington.edu/projects/hic/
  32. *
  33. * The OSG doesn't implement exactly the same technique as above, but its
  34. * should be a good starting place. The OSG's impostors are much less
  35. * intrusive since you don't need to restructure your whole scene to use
  36. * them.
  37. *
  38. * All you need to do to use Impostors is to set up the visible
  39. * range values for each LOD child of the Impostor, as per osg::LOD,
  40. * and set an Impostor threshold to tell the renderer at what distance
  41. * the Impostor's image caching should cut in. The osg::CullVisitor
  42. * automatically handles all the setting of pre-rendering stages to
  43. * calculate the required ImpostorSprites (which encapsulates the image
  44. * cache and quad), and updates them as the view point changes. If you
  45. * use osg::SceneView/CullVisitor all the complexity of supporting
  46. * Impostor will be nicely hidden away.
  47. *
  48. * TODO:
  49. * Various improvements are planned for the Impostor-
  50. * 1) Estimation of how many frames an ImpostorSprite will be reused, if
  51. * it won't be used more often than a minimum threshold then do not create
  52. * ImpostorSprite - use the real geometry.
  53. * 2) Sharing of texture memory between ImpostorSprites.
  54. * 3) Simple 3D geometry for ImpostorSprite's rather than Billboarding.
  55. * 4) Shrinking of the ImpostorSprite size to more closely fit the underlying
  56. * geometry.
  57. */
  58. class OSGSIM_EXPORT Impostor : public osg::LOD
  59. {
  60. public :
  61. Impostor();
  62. Impostor(const Impostor& es, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
  63. osg::LOD(es,copyop),
  64. _impostorThreshold(es._impostorThreshold) {}
  65. META_Node(osgSim, Impostor);
  66. virtual void traverse(osg::NodeVisitor& nv);
  67. typedef std::vector< osg::ref_ptr<ImpostorSprite> > ImpostorSpriteList;
  68. /** Set the Impostor threshold distance.
  69. * For eye points further than this threshold the Imposter is used if appropriate,
  70. * otherwise the LOD children as chosen as per a standard LOD node.
  71. */
  72. inline void setImpostorThreshold(float distance) { _impostorThreshold = distance; }
  73. /* Get the Impostor threshold distance. */
  74. inline float getImpostorThreshold() const { return _impostorThreshold; }
  75. /** Set the Impostor threshold distance relative to the node's bounding
  76. * sphere's radius.
  77. */
  78. inline void setImpostorThresholdToBound(float ratio=1.0f) { _impostorThreshold = getBound().radius()*ratio; }
  79. /** Find the ImposterSprite which fits the current eye point best. */
  80. ImpostorSprite* findBestImpostorSprite(unsigned int contextID, const osg::Vec3& currLocalEyePoint) const;
  81. /** Add an ImpostorSprite to the Impostor. */
  82. void addImpostorSprite(unsigned int contextID, ImpostorSprite* is);
  83. /** Get the list of ImpostorSprites attached to this Impostor. */
  84. inline ImpostorSpriteList& getImpostorSpriteList(unsigned int contexID) { return _impostorSpriteListBuffer[contexID]; }
  85. /** Get a const list of ImpostorSprites attached to this const Impostor. */
  86. inline const ImpostorSpriteList& getImpostorSpriteList(unsigned int contexID) const { return _impostorSpriteListBuffer[contexID]; }
  87. virtual osg::BoundingSphere computeBound() const;
  88. protected :
  89. virtual ~Impostor() {}
  90. mutable osg::buffered_object<ImpostorSpriteList> _impostorSpriteListBuffer;
  91. ImpostorSprite* createImpostorSprite(osgUtil::CullVisitor* cv);
  92. float _impostorThreshold;
  93. };
  94. }
  95. #endif