root/OpenSceneGraph/trunk/include/osgParticle/ParticleSystem @ 11018

Revision 11018, 13.5 kB (checked in by robert, 5 years ago)

From Wang Rui, "Changes:

1. Rewrite the reading/writing exception handlers to work like the ive
plugin exceptions.
2. Write a header writing/checking function in ReaderWriterOSG2.cpp,
which may help decide if the stream is ascii or binary. The
readInputIterator() function will return null pointer if the input
file is nither osgb nor osgt format, which indicates that the old .osg
format could be used here, in case we've merged the two plugins
together.
3. Add a new ForceReadingImage? option in the InputStream?, which will
allocate an empty image object with the filename if specifed external
image file is missed. It may be useful for format converting in some
cases.
4. Add new osgParticle wrappers, as well as some modification to the
osgParticle headers, for instance, change isEnabled() to getEnabled().
5. Some fixes to the osg serialization wrappers."

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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//osgParticle - Copyright (C) 2002 Marco Jez
14
15#ifndef OSGPARTICLE_PARTICLESYSTEM
16#define OSGPARTICLE_PARTICLESYSTEM 1
17
18#include <osgParticle/Export>
19#include <osgParticle/Particle>
20
21#include <vector>
22#include <stack>
23#include <algorithm>
24#include <string>
25
26#include <osg/Object>
27#include <osg/Drawable>
28#include <osg/CopyOp>
29#include <osg/State>
30#include <osg/Vec3>
31#include <osg/BoundingBox>
32
33// 9th Febrary 2009, disabled the use of ReadWriteMutex as it looks like this
34// is introducing threading problems due to threading problems in OpenThreads::ReadWriteMutex.
35// #define OSGPARTICLE_USE_ReadWriteMutex
36
37#ifdef OSGPARTICLE_USE_ReadWriteMutex
38    #include <OpenThreads/ReadWriteMutex>
39#else
40    #include <OpenThreads/Mutex>
41    #include <OpenThreads/ScopedLock>
42#endif
43
44
45namespace osgParticle
46{
47
48    /** The heart of this class library; its purpose is to hold a set of particles and manage particle creation, update, rendering and destruction.
49      * You can add this drawable to any Geode as you usually do with other
50      * Drawable classes. Each instance of ParticleSystem is a separate set of
51      * particles; it provides the interface for creating particles and iterating
52      * through them (see the Emitter and Program classes).
53    */
54    class OSGPARTICLE_EXPORT ParticleSystem: public osg::Drawable {
55    public:
56   
57        enum Alignment {
58            BILLBOARD,
59            FIXED
60        };
61
62        ParticleSystem();
63        ParticleSystem(const ParticleSystem& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
64
65        META_Object(osgParticle, ParticleSystem);
66       
67        /// Get the alignment type of particles.
68        inline Alignment getParticleAlignment() const;
69       
70        /// Set the alignment type of particles.
71        inline void setParticleAlignment(Alignment a);
72       
73        /// Get the X-axis alignment vector.
74        inline const osg::Vec3& getAlignVectorX() const;
75       
76        /// Set the X-axis alignment vector.
77        inline void setAlignVectorX(const osg::Vec3& v);
78
79        /// Get the Y-axis alignment vector.
80        inline const osg::Vec3& getAlignVectorY() const;
81       
82        /// Set the Y-axis alignment vector.
83        inline void setAlignVectorY(const osg::Vec3& v);
84       
85        /// Set the alignment vectors.
86        inline void setAlignVectors(const osg::Vec3& X, const osg::Vec3& Y);
87
88
89
90        enum ParticleScaleReferenceFrame
91        {
92            LOCAL_COORDINATES,
93            WORLD_COORDINATES
94        };
95
96        /** Set whether the particles should be scaled relative to world coordaintes or local coordinates.*/
97        void setParticleScaleReferenceFrame(ParticleScaleReferenceFrame rf) { _particleScaleReferenceFrame = rf; }
98
99        /** Get whether the particles should be scaled relative to world coordaintes or local coordinates.*/
100        ParticleScaleReferenceFrame getParticleScaleReferenceFrame() const { return _particleScaleReferenceFrame; }
101
102
103
104        /// Get the default bounding box
105        inline const osg::BoundingBox& getDefaultBoundingBox() const;       
106       
107        /**    Set the default bounding box.
108            The default bounding box is used when a real bounding box cannot be computed, for example
109            because no particles has been updated yet.
110        */
111        inline void setDefaultBoundingBox(const osg::BoundingBox& bbox);
112
113        /// Get the double pass rendering flag.
114        inline bool getDoublePassRendering() const;
115       
116        /** Set the double pass rendering flag.
117            Double pass rendering avoids overdraw problems between particle systems
118            and other opaque objects. If you can render all the particle systems after
119            the opaque objects, then double pass is not necessary and can be turned off (best choice).
120            If you set the default attributes with setDefaultAttributes, then the particle
121            system will fall into a transparent bin.
122        */
123        inline void setDoublePassRendering(bool v);
124       
125        /// Return true if the particle system is frozen.
126        bool getFrozen() const { return _frozen; }
127        inline bool isFrozen() const;
128       
129        /**    Set or reset the <I>frozen</I> state.
130            When the particle system is frozen, emitters and programs won't do anything on it.
131        */
132        inline void setFrozen(bool v);
133
134        /// Get the number of allocated particles (alive + dead).
135        inline int numParticles() const;
136       
137        /// Get the number of dead particles.
138        inline int numDeadParticles() const;
139
140        /// Get whether all particles are dead       
141        inline bool areAllParticlesDead() const { return numDeadParticles()==numParticles(); }
142       
143        /// Get a pointer to the i-th particle.
144        inline Particle* getParticle(int i);
145       
146        /// Get a const pointer to the i-th particle.
147        inline const Particle* getParticle(int i) const;
148       
149        /// Create a new particle from the specified template (or the default one if <CODE>ptemplate</CODE> is null).
150        inline virtual Particle* createParticle(const Particle* ptemplate);
151       
152        /// Destroy the i-th particle.
153        inline virtual void destroyParticle(int i);
154       
155        /// Reuse the i-th particle.
156        inline virtual void reuseParticle(int i) { _deadparts.push(&(_particles[i])); }
157
158        /// Get the last frame number.
159        inline int getLastFrameNumber() const;
160
161        /// Get a reference to the default particle template.
162        inline Particle& getDefaultParticleTemplate();
163       
164        /// Get a const reference to the default particle template.
165        inline const Particle& getDefaultParticleTemplate() const;
166
167        /// Set the default particle template (particle is copied).
168        inline void setDefaultParticleTemplate(const Particle& p);
169       
170        /// Get whether the particle system can freeze when culled
171        inline bool getFreezeOnCull() const;
172       
173        /// Set whether the particle system can freeze when culled (default is true)
174        inline void setFreezeOnCull(bool v);
175       
176        /** A useful method to set the most common <CODE>StateAttribute</CODE>'s in one call.
177            If <CODE>texturefile</CODE> is empty, then texturing is turned off.
178        */
179        void setDefaultAttributes(const std::string& texturefile = "", bool emissive_particles = true, bool lighting = false, int texture_unit = 0);
180       
181        /// (<B>EXPERIMENTAL</B>) Get the level of detail.
182        inline int getLevelOfDetail() const;
183       
184        /** (<B>EXPERIMENTAL</B>) Set the level of detail. The total number of particles is divided by the detail value to
185            get the actual number of particles to be drawn. This value must be greater than zero.
186        */
187        inline void setLevelOfDetail(int v);
188
189        /// Update the particles. Don't call this directly, use a <CODE>ParticleSystemUpdater</CODE> instead.
190        virtual void update(double dt);
191
192        virtual void drawImplementation(osg::RenderInfo& renderInfo) const;
193
194        virtual osg::BoundingBox computeBound() const;
195       
196#ifdef OSGPARTICLE_USE_ReadWriteMutex
197        typedef OpenThreads::ReadWriteMutex ReadWriterMutex;
198        typedef OpenThreads::ScopedReadLock ScopedReadLock;
199        typedef OpenThreads::ScopedWriteLock ScopedWriteLock;
200#else
201        typedef OpenThreads::Mutex ReadWriterMutex;
202        typedef OpenThreads::ScopedLock<OpenThreads::Mutex> ScopedReadLock;
203        typedef OpenThreads::ScopedLock<OpenThreads::Mutex> ScopedWriteLock;
204#endif
205
206        ReadWriterMutex* getReadWriteMutex() const { return &_readWriteMutex; }
207
208    protected:
209
210        virtual ~ParticleSystem();
211
212        ParticleSystem& operator=(const ParticleSystem&) { return *this; }
213
214        inline void update_bounds(const osg::Vec3& p, float r);
215        void single_pass_render(osg::State& state, const osg::Matrix& modelview) const;
216
217        typedef std::vector<Particle> Particle_vector;
218        typedef std::stack<Particle*> Death_stack;
219
220        Particle_vector _particles;
221        Death_stack _deadparts;
222       
223        osg::BoundingBox _def_bbox;
224       
225        Alignment _alignment;
226        osg::Vec3 _align_X_axis;
227        osg::Vec3 _align_Y_axis;
228        ParticleScaleReferenceFrame _particleScaleReferenceFrame;
229       
230        bool _doublepass;
231        bool _frozen;
232
233        osg::Vec3 _bmin;
234        osg::Vec3 _bmax;
235
236        bool _reset_bounds_flag;
237        bool _bounds_computed;
238
239        Particle _def_ptemp;
240        mutable int _last_frame;
241        bool _freeze_on_cull;
242       
243        int _detail;
244        mutable int _draw_count;
245       
246        mutable ReadWriterMutex _readWriteMutex;
247    };
248   
249    // INLINE FUNCTIONS
250   
251    inline ParticleSystem::Alignment ParticleSystem::getParticleAlignment() const
252    {
253        return _alignment;
254    }
255   
256    inline void ParticleSystem::setParticleAlignment(Alignment a)
257    {
258        _alignment = a;
259    }
260   
261    inline const osg::Vec3& ParticleSystem::getAlignVectorX() const
262    {
263        return _align_X_axis;
264    }
265   
266    inline void ParticleSystem::setAlignVectorX(const osg::Vec3& v)
267    {
268        _align_X_axis = v;
269    }
270
271    inline const osg::Vec3& ParticleSystem::getAlignVectorY() const
272    {
273        return _align_Y_axis;
274    }
275   
276    inline void ParticleSystem::setAlignVectorY(const osg::Vec3& v)
277    {
278        _align_Y_axis = v;
279    }
280   
281    inline void ParticleSystem::setAlignVectors(const osg::Vec3& X, const osg::Vec3& Y)
282    {
283        _align_X_axis = X;
284        _align_Y_axis = Y;
285    }
286
287    inline bool ParticleSystem::isFrozen() const
288    {
289        return _frozen;
290    }
291   
292    inline void ParticleSystem::setFrozen(bool v)
293    {
294        _frozen = v;
295    }
296   
297    inline const osg::BoundingBox& ParticleSystem::getDefaultBoundingBox() const
298    {
299        return _def_bbox;
300    }
301   
302    inline void ParticleSystem::setDefaultBoundingBox(const osg::BoundingBox& bbox)
303    {
304        _def_bbox = bbox;
305    }
306
307    inline bool ParticleSystem::getDoublePassRendering() const
308    {
309        return _doublepass;
310    }
311
312    inline void ParticleSystem::setDoublePassRendering(bool v)
313    {
314        _doublepass = v;
315    }
316
317    inline int ParticleSystem::numParticles() const
318    {
319        return static_cast<int>(_particles.size());
320    }
321
322    inline int ParticleSystem::numDeadParticles() const
323    {
324        return static_cast<int>(_deadparts.size());
325    }
326
327    inline Particle* ParticleSystem::getParticle(int i)
328    {
329        return &_particles[i];
330    }
331
332    inline const Particle* ParticleSystem::getParticle(int i) const
333    {
334        return &_particles[i];
335    }
336
337    inline void ParticleSystem::destroyParticle(int i)
338    {
339        _particles[i].kill();
340    }
341   
342    inline int ParticleSystem::getLastFrameNumber() const
343    {
344        return _last_frame;
345    }
346
347    inline void ParticleSystem::update_bounds(const osg::Vec3& p, float r)
348    {
349        if (_reset_bounds_flag) {
350            _reset_bounds_flag = false;
351            _bmin = p - osg::Vec3(r,r,r);
352            _bmax = p + osg::Vec3(r,r,r);
353        } else {
354            if (p.x() - r < _bmin.x()) _bmin.x() = p.x() - r;
355            if (p.y() - r < _bmin.y()) _bmin.y() = p.y() - r;
356            if (p.z() - r < _bmin.z()) _bmin.z() = p.z() - r;
357            if (p.x() + r > _bmax.x()) _bmax.x() = p.x() + r;
358            if (p.y() + r > _bmax.y()) _bmax.y() = p.y() + r;
359            if (p.z() + r > _bmax.z()) _bmax.z() = p.z() + r;
360        }
361        if (!_bounds_computed)
362            _bounds_computed = true;
363    }
364
365    inline Particle& ParticleSystem::getDefaultParticleTemplate()
366    {
367        return _def_ptemp;
368    }
369
370    inline const Particle& ParticleSystem::getDefaultParticleTemplate() const
371    {
372        return _def_ptemp;
373    }
374
375    inline void ParticleSystem::setDefaultParticleTemplate(const Particle& p)
376    {
377        _def_ptemp = p;
378    }
379   
380    inline bool ParticleSystem::getFreezeOnCull() const
381    {
382        return _freeze_on_cull;
383    }
384   
385    inline void ParticleSystem::setFreezeOnCull(bool v)
386    {
387        _freeze_on_cull = v;
388    }
389   
390    inline int ParticleSystem::getLevelOfDetail() const
391    {
392        return _detail;
393    }
394   
395    inline void ParticleSystem::setLevelOfDetail(int v)
396    {
397        if (v < 1) v = 1;
398        _detail = v;
399    }
400   
401    // I'm not sure this function should be inlined...
402   
403    inline Particle* ParticleSystem::createParticle(const Particle* ptemplate)
404    {
405        // is there any dead particle?
406        if (!_deadparts.empty()) {
407
408            // retrieve a pointer to the last dead particle
409            Particle* P = _deadparts.top();
410
411            // create a new (alive) particle in the same place
412            *P = ptemplate? *ptemplate: _def_ptemp;
413
414            // remove the pointer from the death stack
415            _deadparts.pop();
416            return P;
417
418        } else {
419
420            // add a new particle to the vector
421            _particles.push_back(ptemplate? *ptemplate: _def_ptemp);
422            return &_particles.back();
423        }
424    }
425
426
427}
428
429#endif
Note: See TracBrowser for help on using the browser.