| 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 OSG_ImpostorSprite |
|---|
| 15 | #define OSG_ImpostorSprite 1 |
|---|
| 16 | |
|---|
| 17 | #include <osg/Vec2> |
|---|
| 18 | #include <osg/BoundingSphere> |
|---|
| 19 | #include <osg/Drawable> |
|---|
| 20 | #include <osg/AlphaFunc> |
|---|
| 21 | #include <osg/TexEnv> |
|---|
| 22 | #include <osg/Texture2D> |
|---|
| 23 | #include <osg/Camera> |
|---|
| 24 | |
|---|
| 25 | #include <osgSim/Export> |
|---|
| 26 | |
|---|
| 27 | namespace osgSim { |
|---|
| 28 | |
|---|
| 29 | class Impostor; |
|---|
| 30 | class ImpostorSpriteManager; |
|---|
| 31 | |
|---|
| 32 | /** An ImposterSprite is a textured quad which is rendered in place of |
|---|
| 33 | * 3D geometry. The ImposterSprite is generated by rendering the original |
|---|
| 34 | * 3D geometry to a texture as an image cache. The ImpostorSprite is |
|---|
| 35 | * automatically generated by the osgUtil::CullVisitor so it not |
|---|
| 36 | * necessary to deal with it directly. |
|---|
| 37 | */ |
|---|
| 38 | class OSGSIM_EXPORT ImpostorSprite : public osg::Drawable |
|---|
| 39 | { |
|---|
| 40 | public: |
|---|
| 41 | |
|---|
| 42 | ImpostorSprite(); |
|---|
| 43 | |
|---|
| 44 | /** Clone an object of the same type as an ImpostorSprite. */ |
|---|
| 45 | virtual osg::Object* cloneType() const { return new ImpostorSprite(); } |
|---|
| 46 | |
|---|
| 47 | /** Clone on ImpostorSprite just returns a clone of type, |
|---|
| 48 | * since it is not appropriate to share data of an ImpostorSprite. |
|---|
| 49 | */ |
|---|
| 50 | virtual osg::Object* clone(const osg::CopyOp&) const { return new ImpostorSprite(); } |
|---|
| 51 | virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const ImpostorSprite*>(obj)!=NULL; } |
|---|
| 52 | virtual const char* libraryName() const { return "osgSim"; } |
|---|
| 53 | virtual const char* className() const { return "ImpostorSprite"; } |
|---|
| 54 | |
|---|
| 55 | /** Set the parent, which must be an Impostor. |
|---|
| 56 | * Unlike conventional Drawables, ImpostorSprites can only ever have |
|---|
| 57 | * one parent. |
|---|
| 58 | */ |
|---|
| 59 | void setParent(Impostor* parent) { _parent = parent; } |
|---|
| 60 | |
|---|
| 61 | /** Get the parent, which is an Impostor. */ |
|---|
| 62 | Impostor* getParent() { return _parent; } |
|---|
| 63 | |
|---|
| 64 | /** Get the const parent, which is an Impostor. */ |
|---|
| 65 | const Impostor* getParent() const { return _parent; } |
|---|
| 66 | |
|---|
| 67 | /** Set the eye point for when the ImpostorSprite was snapped. */ |
|---|
| 68 | inline void setStoredLocalEyePoint(const osg::Vec3& v) { _storedLocalEyePoint=v; } |
|---|
| 69 | |
|---|
| 70 | /** Get the eye point for when the ImpostorSprite was snapped. */ |
|---|
| 71 | inline const osg::Vec3& getStoredLocalEyePoint() const { return _storedLocalEyePoint; } |
|---|
| 72 | |
|---|
| 73 | /** Set the frame number for when the ImpostorSprite was last used in rendering. */ |
|---|
| 74 | inline void setLastFrameUsed(unsigned int frameNumber) { _lastFrameUsed = frameNumber; } |
|---|
| 75 | |
|---|
| 76 | /** Get the frame number for when the ImpostorSprite was last used in rendering. */ |
|---|
| 77 | inline unsigned int getLastFrameUsed() const { return _lastFrameUsed; } |
|---|
| 78 | |
|---|
| 79 | |
|---|
| 80 | /** Get the coordinates of the corners of the quad. |
|---|
| 81 | * Stored in the order, [0] - top_left, [1] - bottom_left, [2] - bottom_right, [3] - top_left. |
|---|
| 82 | */ |
|---|
| 83 | inline osg::Vec3* getCoords() { return _coords; } |
|---|
| 84 | |
|---|
| 85 | /** Get the const coordinates of the corners of the quad. */ |
|---|
| 86 | inline const osg::Vec3* getCoords() const { return _coords; } |
|---|
| 87 | |
|---|
| 88 | |
|---|
| 89 | |
|---|
| 90 | /** Get the texture coordinates of the corners of the quad. |
|---|
| 91 | * Stored in the order, [0] - top_left, [1] - bottom_left, [2] - bottom_right, [3] - top_left. |
|---|
| 92 | */ |
|---|
| 93 | inline osg::Vec2* getTexCoords() { return _texcoords; } |
|---|
| 94 | |
|---|
| 95 | /** Get the const texture coordinates of the corners of the quad. */ |
|---|
| 96 | inline const osg::Vec2* getTexCoords() const { return _texcoords; } |
|---|
| 97 | |
|---|
| 98 | /** Get the control coordinates of the corners of the quad. |
|---|
| 99 | * The control coordinates are the corners of the quad projected |
|---|
| 100 | * out onto the front face of bounding box which enclosed the impostor |
|---|
| 101 | * geometry when it was pre-rendered into the impostor sprite's texture. |
|---|
| 102 | * At the point of creation/or update of the impostor sprite the control |
|---|
| 103 | * coords will lie on top of the corners of the quad in screen space - with a pixel error |
|---|
| 104 | * of zero. Once the camera moves relative to the impostor sprite the |
|---|
| 105 | * control coords will no longer lie on top of the corners of the quad in |
|---|
| 106 | * screen space - a pixel error will have accumulated. This pixel error |
|---|
| 107 | * can then be used to determine whether the impostor needs to be updated. |
|---|
| 108 | * Stored in the order, [0] - top_left, [1] - bottom_left, [2] - bottom_right, [3] - top_left. |
|---|
| 109 | */ |
|---|
| 110 | inline osg::Vec3* getControlCoords() { return _controlcoords; } |
|---|
| 111 | |
|---|
| 112 | /** Get the const control coordinates of the corners of the quad. */ |
|---|
| 113 | inline const osg::Vec3* getControlCoords() const { return _controlcoords; } |
|---|
| 114 | |
|---|
| 115 | |
|---|
| 116 | /** Calculate the pixel error value for passing in the ModelViewProjectionWindow transform, |
|---|
| 117 | * which transform local coords into screen space. |
|---|
| 118 | */ |
|---|
| 119 | float calcPixelError(const osg::Matrix& MVPW) const; |
|---|
| 120 | |
|---|
| 121 | void setTexture(osg::Texture2D* tex,int s,int t); |
|---|
| 122 | osg::Texture2D* getTexture() { return _texture; } |
|---|
| 123 | const osg::Texture2D* getTexture() const { return _texture; } |
|---|
| 124 | |
|---|
| 125 | int s() const { return _s; } |
|---|
| 126 | int t() const { return _t; } |
|---|
| 127 | |
|---|
| 128 | /** Draw ImpostorSprite directly. */ |
|---|
| 129 | virtual void drawImplementation(osg::RenderInfo& renderInfo) const; |
|---|
| 130 | |
|---|
| 131 | /** Return true, osg::ImpostorSprite does support accept(Drawable::AttributeFunctor&). */ |
|---|
| 132 | virtual bool supports(const Drawable::AttributeFunctor&) const { return true; } |
|---|
| 133 | |
|---|
| 134 | /** Accept an Drawable::AttributeFunctor and call its methods to tell it about the internal attributes that this Drawable has. */ |
|---|
| 135 | virtual void accept(Drawable::AttributeFunctor& af); |
|---|
| 136 | |
|---|
| 137 | /** Return true, osg::ImpostorSprite does support accept(Drawable::ConstAttributeFunctor&). */ |
|---|
| 138 | virtual bool supports(const Drawable::ConstAttributeFunctor&) const { return true; } |
|---|
| 139 | |
|---|
| 140 | /** Accept a Drawable::ConstAttributeFunctor and call its methods to tell it about the internal attributes that this Drawable has. */ |
|---|
| 141 | virtual void accept(Drawable::ConstAttributeFunctor& af) const; |
|---|
| 142 | |
|---|
| 143 | /** Return true, osg::ImpostorSprite does support accept(PrimitiveFunctor&). */ |
|---|
| 144 | virtual bool supports(const osg::PrimitiveFunctor&) const { return true; } |
|---|
| 145 | |
|---|
| 146 | /** Accept a PrimtiveFunctor and call its methods to tell it about the internal primitives that this Drawable has. */ |
|---|
| 147 | virtual void accept(osg::PrimitiveFunctor& pf) const; |
|---|
| 148 | |
|---|
| 149 | // for debugging purposes. |
|---|
| 150 | osg::Vec4 _color; |
|---|
| 151 | |
|---|
| 152 | virtual osg::BoundingBox computeBound() const; |
|---|
| 153 | |
|---|
| 154 | /** Set the camera node to use for pre rendering the impostor sprite's texture.*/ |
|---|
| 155 | void setCamera(osg::Camera* camera) { _camera = camera; } |
|---|
| 156 | |
|---|
| 157 | /** Get the camera node to use for pre rendering the impostor sprite's texture.*/ |
|---|
| 158 | osg::Camera* getCamera() { return _camera.get(); } |
|---|
| 159 | |
|---|
| 160 | /** Get the const camera node to use for pre rendering the impostor sprite's texture.*/ |
|---|
| 161 | const osg::Camera* getCamera() const { return _camera.get(); } |
|---|
| 162 | |
|---|
| 163 | protected: |
|---|
| 164 | |
|---|
| 165 | ImpostorSprite(const ImpostorSprite&); |
|---|
| 166 | ImpostorSprite& operator = (const ImpostorSprite&) { return *this;} |
|---|
| 167 | |
|---|
| 168 | virtual ~ImpostorSprite(); |
|---|
| 169 | |
|---|
| 170 | Impostor* _parent; |
|---|
| 171 | |
|---|
| 172 | friend class osgSim::ImpostorSpriteManager; |
|---|
| 173 | |
|---|
| 174 | // camera node for doing the pre rendering. |
|---|
| 175 | osg::ref_ptr<osg::Camera> _camera; |
|---|
| 176 | |
|---|
| 177 | // support for a double linked list managed by the |
|---|
| 178 | // ImposotorSpriteManager. |
|---|
| 179 | ImpostorSpriteManager* _ism; |
|---|
| 180 | ImpostorSprite* _previous; |
|---|
| 181 | ImpostorSprite* _next; |
|---|
| 182 | |
|---|
| 183 | unsigned int _lastFrameUsed; |
|---|
| 184 | |
|---|
| 185 | osg::Vec3 _storedLocalEyePoint; |
|---|
| 186 | |
|---|
| 187 | osg::Vec3 _coords[4]; |
|---|
| 188 | osg::Vec2 _texcoords[4]; |
|---|
| 189 | osg::Vec3 _controlcoords[4]; |
|---|
| 190 | |
|---|
| 191 | osg::Texture2D* _texture; |
|---|
| 192 | int _s; |
|---|
| 193 | int _t; |
|---|
| 194 | |
|---|
| 195 | |
|---|
| 196 | }; |
|---|
| 197 | |
|---|
| 198 | /** Helper class for managing the reuse of ImpostorSprite resources. */ |
|---|
| 199 | class OSGSIM_EXPORT ImpostorSpriteManager : public osg::Referenced |
|---|
| 200 | { |
|---|
| 201 | public: |
|---|
| 202 | |
|---|
| 203 | ImpostorSpriteManager(); |
|---|
| 204 | |
|---|
| 205 | bool empty() const { return _first==0; } |
|---|
| 206 | |
|---|
| 207 | ImpostorSprite* first() { return _first; } |
|---|
| 208 | |
|---|
| 209 | ImpostorSprite* last() { return _last; } |
|---|
| 210 | |
|---|
| 211 | void push_back(ImpostorSprite* is); |
|---|
| 212 | |
|---|
| 213 | void remove(ImpostorSprite* is); |
|---|
| 214 | |
|---|
| 215 | ImpostorSprite* createOrReuseImpostorSprite(int s,int t,unsigned int frameNumber); |
|---|
| 216 | |
|---|
| 217 | osg::StateSet* createOrReuseStateSet(); |
|---|
| 218 | |
|---|
| 219 | void reset(); |
|---|
| 220 | |
|---|
| 221 | protected: |
|---|
| 222 | |
|---|
| 223 | |
|---|
| 224 | ~ImpostorSpriteManager(); |
|---|
| 225 | |
|---|
| 226 | osg::ref_ptr<osg::TexEnv> _texenv; |
|---|
| 227 | osg::ref_ptr<osg::AlphaFunc> _alphafunc; |
|---|
| 228 | |
|---|
| 229 | ImpostorSprite* _first; |
|---|
| 230 | ImpostorSprite* _last; |
|---|
| 231 | |
|---|
| 232 | typedef std::vector< osg::ref_ptr<osg::StateSet> > StateSetList; |
|---|
| 233 | StateSetList _stateSetList; |
|---|
| 234 | unsigned int _reuseStateSetIndex; |
|---|
| 235 | |
|---|
| 236 | |
|---|
| 237 | }; |
|---|
| 238 | |
|---|
| 239 | } |
|---|
| 240 | |
|---|
| 241 | #endif |
|---|