ImpostorSprite 9.32 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSG_ImpostorSprite
#define OSG_ImpostorSprite 1

#include <osg/Vec2>
#include <osg/BoundingSphere>
#include <osg/Drawable>
#include <osg/AlphaFunc>
#include <osg/TexEnv>
#include <osg/Texture2D>
#include <osg/Camera>

#include <osgSim/Export>

namespace osgSim {

class Impostor;
class ImpostorSpriteManager;

/** An ImposterSprite is a textured quad which is rendered in place of
  * 3D geometry. The ImposterSprite is generated by rendering the original
  * 3D geometry to a texture as an image cache. The ImpostorSprite is
  * automatically generated by the osgUtil::CullVisitor so it not
  * necessary to deal with it directly.
*/
class OSGSIM_EXPORT ImpostorSprite : public osg::Drawable
{
    public:

        ImpostorSprite();

        /** Clone an object of the same type as an ImpostorSprite. */
        virtual osg::Object* cloneType() const { return new ImpostorSprite(); }

        /** Clone on ImpostorSprite just returns a clone of type, 
          * since it is not appropriate to share data of an ImpostorSprite.
        */
        virtual osg::Object* clone(const osg::CopyOp&) const { return new ImpostorSprite(); }
        virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const ImpostorSprite*>(obj)!=NULL; }
        virtual const char* libraryName() const { return "osgSim"; }
        virtual const char* className() const { return "ImpostorSprite"; }

        /** Set the parent, which must be an Impostor. 
          * Unlike conventional Drawables, ImpostorSprites can only ever have
          * one parent.
        */
        void setParent(Impostor* parent) { _parent = parent; }

        /** Get the parent, which is an Impostor. */
        Impostor* getParent() { return _parent; }

        /** Get the const parent, which is an Impostor. */
        const Impostor* getParent() const { return _parent; }

        /** Set the eye point for when the ImpostorSprite was snapped. */
        inline void setStoredLocalEyePoint(const osg::Vec3& v) { _storedLocalEyePoint=v; }

        /** Get the eye point for when the ImpostorSprite was snapped. */
        inline const osg::Vec3& getStoredLocalEyePoint() const { return _storedLocalEyePoint; }
        
        /** Set the frame number for when the ImpostorSprite was last used in rendering. */
        inline void setLastFrameUsed(unsigned int frameNumber) { _lastFrameUsed = frameNumber; }
        
        /** Get the frame number for when the ImpostorSprite was last used in rendering. */
        inline unsigned int getLastFrameUsed() const { return _lastFrameUsed; }
        

        /** Get the coordinates of the corners of the quad.
          * Stored in the order, [0] - top_left, [1] - bottom_left, [2] - bottom_right, [3] - top_left.
        */
        inline osg::Vec3* getCoords() { return _coords; }
        
        /** Get the const coordinates of the corners of the quad. */
        inline const osg::Vec3* getCoords() const { return _coords; }



        /** Get the texture coordinates of the corners of the quad.
          * Stored in the order, [0] - top_left, [1] - bottom_left, [2] - bottom_right, [3] - top_left.
        */
        inline osg::Vec2* getTexCoords() { return _texcoords; }
        
        /** Get the const texture coordinates of the corners of the quad. */
        inline const osg::Vec2* getTexCoords() const { return _texcoords; }

        /** Get the control coordinates of the corners of the quad.
          * The control coordinates are the corners of the quad projected
          * out onto the front face of bounding box which enclosed the impostor
          * geometry when it was pre-rendered into the impostor sprite's texture.
          * At the point of creation/or update of the impostor sprite the control
          * coords will lie on top of the corners of the quad in screen space - with a pixel error
          * of zero. Once the camera moves relative to the impostor sprite the
          * control coords will no longer lie on top of the corners of the quad in
          * screen space - a pixel error will have accumulated. This pixel error
          * can then be used to determine whether the impostor needs to be updated.
          * Stored in the order, [0] - top_left, [1] - bottom_left, [2] - bottom_right, [3] - top_left.
        */
        inline osg::Vec3* getControlCoords() { return _controlcoords; }
        
        /** Get the const control coordinates of the corners of the quad. */
        inline const osg::Vec3* getControlCoords() const { return _controlcoords; }


        /** Calculate the pixel error value for passing in the ModelViewProjectionWindow transform,
          * which transform local coords into screen space.
        */
        float calcPixelError(const osg::Matrix& MVPW) const;

        void setTexture(osg::Texture2D* tex,int s,int t);
        osg::Texture2D* getTexture() { return _texture; }
        const osg::Texture2D* getTexture() const { return _texture; }
    
        int s() const { return _s; }
        int t() const { return _t; }

        /** Draw ImpostorSprite directly. */
        virtual void drawImplementation(osg::RenderInfo& renderInfo) const;

        /** Return true, osg::ImpostorSprite does support accept(Drawable::AttributeFunctor&). */
        virtual bool supports(const Drawable::AttributeFunctor&) const { return true; }

        /** Accept an Drawable::AttributeFunctor and call its methods to tell it about the internal attributes that this Drawable has. */
        virtual void accept(Drawable::AttributeFunctor& af);

        /** Return true, osg::ImpostorSprite does support accept(Drawable::ConstAttributeFunctor&). */
        virtual bool supports(const Drawable::ConstAttributeFunctor&) const { return true; }

        /** Accept a Drawable::ConstAttributeFunctor and call its methods to tell it about the internal attributes that this Drawable has. */
        virtual void accept(Drawable::ConstAttributeFunctor& af) const;

        /** Return true, osg::ImpostorSprite does support accept(PrimitiveFunctor&). */
        virtual bool supports(const osg::PrimitiveFunctor&) const { return true; }

        /** Accept a PrimtiveFunctor and call its methods to tell it about the internal primitives that this Drawable has. */
        virtual void accept(osg::PrimitiveFunctor& pf) const;

        // for debugging purposes.
        osg::Vec4 _color;

        virtual osg::BoundingBox computeBound() const;
        
        /** Set the camera node to use for pre rendering the impostor sprite's texture.*/
        void setCamera(osg::Camera* camera) { _camera = camera; }

        /** Get the camera node to use for pre rendering the impostor sprite's texture.*/
        osg::Camera* getCamera() { return _camera.get(); }

        /** Get the const camera node to use for pre rendering the impostor sprite's texture.*/
        const osg::Camera* getCamera() const { return _camera.get(); }

    protected:

        ImpostorSprite(const ImpostorSprite&);
        ImpostorSprite& operator = (const ImpostorSprite&) { return *this;}

        virtual ~ImpostorSprite();

        Impostor* _parent;

        friend class osgSim::ImpostorSpriteManager;
        
        // camera node for doing the pre rendering.
        osg::ref_ptr<osg::Camera> _camera;

        // support for a double linked list managed by the
        // ImposotorSpriteManager.
        ImpostorSpriteManager*  _ism;
        ImpostorSprite*         _previous;
        ImpostorSprite*         _next;
        
        unsigned int _lastFrameUsed;

        osg::Vec3 _storedLocalEyePoint;
        
        osg::Vec3 _coords[4];
        osg::Vec2 _texcoords[4];
        osg::Vec3 _controlcoords[4];
        
        osg::Texture2D* _texture;
        int _s;
        int _t;
        
        
};

/** Helper class for managing the reuse of ImpostorSprite resources. */
class OSGSIM_EXPORT ImpostorSpriteManager : public osg::Referenced
{
    public:
    
        ImpostorSpriteManager();
        
        bool empty() const { return _first==0; }

        ImpostorSprite* first() { return _first; }
        
        ImpostorSprite* last() { return _last; }
        
        void push_back(ImpostorSprite* is);
        
        void remove(ImpostorSprite* is);
        
        ImpostorSprite* createOrReuseImpostorSprite(int s,int t,unsigned int frameNumber);

        osg::StateSet* createOrReuseStateSet();

        void reset();
    
    protected:


        ~ImpostorSpriteManager();

        osg::ref_ptr<osg::TexEnv>       _texenv;
        osg::ref_ptr<osg::AlphaFunc>    _alphafunc;

        ImpostorSprite*                 _first;
        ImpostorSprite*                 _last;
        
        typedef std::vector< osg::ref_ptr<osg::StateSet> > StateSetList;
        StateSetList                    _stateSetList;
        unsigned int                    _reuseStateSetIndex;


};

}

#endif