| 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 | |
|---|
| 14 | #ifndef OSGSIM_IMPOSTOR |
|---|
| 15 | #define OSGSIM_IMPOSTOR 1 |
|---|
| 16 | |
|---|
| 17 | #include <osg/LOD> |
|---|
| 18 | #include <osg/buffered_value> |
|---|
| 19 | |
|---|
| 20 | #include <osgUtil/CullVisitor> |
|---|
| 21 | |
|---|
| 22 | #include <osgSim/ImpostorSprite> |
|---|
| 23 | |
|---|
| 24 | namespace osgSim { |
|---|
| 25 | |
|---|
| 26 | /** Impostor - is a form of Level Of Detail group node which allows both switching |
|---|
| 27 | * between children depending on distance from eye point and image caching. |
|---|
| 28 | * |
|---|
| 29 | * The principle behind Imposters is that they cache an image of real geometry and then the image is drawn |
|---|
| 30 | * in subsequent frames instead of the real geometry. It's a bit like a |
|---|
| 31 | * Billboard *but* is updated at runtime and w.r.t view point. By drawing |
|---|
| 32 | * just the texture mapped quad you can cut down scene complexity and |
|---|
| 33 | * improve performance. |
|---|
| 34 | * |
|---|
| 35 | * For more details have a look at: |
|---|
| 36 | * |
|---|
| 37 | * http://grail.cs.washington.edu/projects/hic/ |
|---|
| 38 | * |
|---|
| 39 | * The OSG doesn't implement exactly the same technique as above, but its |
|---|
| 40 | * should be a good starting place. The OSG's impostors are much less |
|---|
| 41 | * intrusive since you don't need to restructure your whole scene to use |
|---|
| 42 | * them. |
|---|
| 43 | * |
|---|
| 44 | * All you need to do to use Impostors is to set up the visible |
|---|
| 45 | * range values for each LOD child of the Impostor, as per osg::LOD, |
|---|
| 46 | * and set an Impostor threshold to tell the renderer at what distance |
|---|
| 47 | * the Impostor's image caching should cut in. The osg::CullVisitor |
|---|
| 48 | * automatically handles all the setting of pre-rendering stages to |
|---|
| 49 | * calculate the required ImpostorSprites (which encapsulates the image |
|---|
| 50 | * cache and quad), and updates them as the view point changes. If you |
|---|
| 51 | * use osg::SceneView/CullVisitor all the complexity of supporting |
|---|
| 52 | * Impostor will be nicely hidden away. |
|---|
| 53 | * |
|---|
| 54 | * TODO: |
|---|
| 55 | * Various improvements are planned for the Impostor- |
|---|
| 56 | * 1) Estimation of how many frames an ImpostorSprite will be reused, if |
|---|
| 57 | * it won't be used more often than a minimum threshold then do not create |
|---|
| 58 | * ImpostorSprite - use the real geometry. |
|---|
| 59 | * 2) Sharing of texture memory between ImpostorSprites. |
|---|
| 60 | * 3) Simple 3D geometry for ImpostorSprite's rather than Billboarding. |
|---|
| 61 | * 4) Shrinking of the ImpostorSprite size to more closely fit the underlying |
|---|
| 62 | * geometry. |
|---|
| 63 | */ |
|---|
| 64 | class OSGSIM_EXPORT Impostor : public osg::LOD |
|---|
| 65 | { |
|---|
| 66 | public : |
|---|
| 67 | Impostor(); |
|---|
| 68 | |
|---|
| 69 | Impostor(const Impostor& es, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): |
|---|
| 70 | osg::LOD(es,copyop), |
|---|
| 71 | _impostorThreshold(es._impostorThreshold) {} |
|---|
| 72 | |
|---|
| 73 | META_Node(osgSim, Impostor); |
|---|
| 74 | |
|---|
| 75 | virtual void traverse(osg::NodeVisitor& nv); |
|---|
| 76 | |
|---|
| 77 | typedef std::vector< osg::ref_ptr<ImpostorSprite> > ImpostorSpriteList; |
|---|
| 78 | |
|---|
| 79 | /** Set the Impostor threshold distance. |
|---|
| 80 | * For eye points further than this threshold the Imposter is used if appropriate, |
|---|
| 81 | * otherwise the LOD children as chosen as per a standard LOD node. |
|---|
| 82 | */ |
|---|
| 83 | inline void setImpostorThreshold(float distance) { _impostorThreshold = distance; } |
|---|
| 84 | |
|---|
| 85 | /* Get the Impostor threshold distance. */ |
|---|
| 86 | inline float getImpostorThreshold() const { return _impostorThreshold; } |
|---|
| 87 | |
|---|
| 88 | /** Set the Impostor threshold distance relative to the node's bounding |
|---|
| 89 | * sphere's radius. |
|---|
| 90 | */ |
|---|
| 91 | inline void setImpostorThresholdToBound(float ratio=1.0f) { _impostorThreshold = getBound().radius()*ratio; } |
|---|
| 92 | |
|---|
| 93 | /** Find the ImposterSprite which fits the current eye point best. */ |
|---|
| 94 | ImpostorSprite* findBestImpostorSprite(unsigned int contextID, const osg::Vec3& currLocalEyePoint) const; |
|---|
| 95 | |
|---|
| 96 | /** Add an ImpostorSprite to the Impostor. */ |
|---|
| 97 | void addImpostorSprite(unsigned int contextID, ImpostorSprite* is); |
|---|
| 98 | |
|---|
| 99 | /** Get the list of ImpostorSprites attached to this Impostor. */ |
|---|
| 100 | inline ImpostorSpriteList& getImpostorSpriteList(unsigned int contexID) { return _impostorSpriteListBuffer[contexID]; } |
|---|
| 101 | |
|---|
| 102 | /** Get a const list of ImpostorSprites attached to this const Impostor. */ |
|---|
| 103 | inline const ImpostorSpriteList& getImpostorSpriteList(unsigned int contexID) const { return _impostorSpriteListBuffer[contexID]; } |
|---|
| 104 | |
|---|
| 105 | virtual osg::BoundingSphere computeBound() const; |
|---|
| 106 | |
|---|
| 107 | protected : |
|---|
| 108 | |
|---|
| 109 | virtual ~Impostor() {} |
|---|
| 110 | |
|---|
| 111 | mutable osg::buffered_object<ImpostorSpriteList> _impostorSpriteListBuffer; |
|---|
| 112 | |
|---|
| 113 | ImpostorSprite* createImpostorSprite(osgUtil::CullVisitor* cv); |
|---|
| 114 | |
|---|
| 115 | float _impostorThreshold; |
|---|
| 116 | |
|---|
| 117 | }; |
|---|
| 118 | |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | #endif |
|---|