root/OpenSceneGraph/trunk/src/osgParticle/ConnectedParticleSystem.cpp @ 13041

Revision 13041, 8.0 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • 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
14#include <osg/Notify>
15#include <osg/CullingSet>
16#include <osg/io_utils>
17#include <osgParticle/ConnectedParticleSystem>
18
19using namespace osgParticle;
20
21ConnectedParticleSystem::ConnectedParticleSystem():
22    _lastParticleCreated(Particle::INVALID_INDEX),
23    _maxNumberOfParticlesToSkip(200),
24    _startParticle(Particle::INVALID_INDEX)
25{
26}
27
28ConnectedParticleSystem::ConnectedParticleSystem(const ConnectedParticleSystem& copy, const osg::CopyOp& copyop):
29    ParticleSystem(copy,copyop),
30    _lastParticleCreated(copy._lastParticleCreated),
31    _maxNumberOfParticlesToSkip(200),
32    _startParticle(copy._startParticle)
33{
34}
35
36ConnectedParticleSystem::~ConnectedParticleSystem()
37{
38}
39
40Particle* ConnectedParticleSystem::createParticle(const Particle* ptemplate)
41{
42    // OSG_NOTICE<<this<< " Creating particle "<<std::endl;
43
44    Particle* particle = ParticleSystem::createParticle(ptemplate);
45    int particleIndex = (int)(particle - &_particles[0]);
46
47    if (particle)
48    {
49
50        if (_startParticle == Particle::INVALID_INDEX)
51        {
52            // we are the fisrt particle create, so start the connect particle list
53            _startParticle = particleIndex;
54        }
55
56        if (_lastParticleCreated != Particle::INVALID_INDEX)
57        {
58            // OSG_NOTICE<<this<< " Connecting "<<_lastParticleCreated<<" to "<<particleIndex<<std::endl;
59
60            // write up the last created particle to this new particle
61            _particles[_lastParticleCreated].setNextParticle(particleIndex);
62            particle->setPreviousParticle(_lastParticleCreated);
63        }
64
65        // set the new particle as the last particle created.
66        _lastParticleCreated = particleIndex;
67
68    }
69
70    return particle;
71}
72
73void ConnectedParticleSystem::reuseParticle(int particleIndex)
74{
75    // OSG_NOTICE<<this<< " Reusing particle "<<particleIndex<<std::endl;
76
77    if (particleIndex<0 || particleIndex>=(int)_particles.size()) return;
78
79    Particle* particle = &_particles[particleIndex];
80    int previous = particle->getPreviousParticle();
81    int next = particle->getNextParticle();
82
83    // update start and last entries
84    if (_startParticle == particleIndex)
85    {
86        _startParticle = particle->getNextParticle();
87    }
88
89    if (_lastParticleCreated == particleIndex)
90    {
91        _lastParticleCreated = Particle::INVALID_INDEX;
92    }
93
94    // join up the previous and next particles to account for
95    // the deletion of the this particle
96    if (previous != Particle::INVALID_INDEX)
97    {
98        _particles[previous].setNextParticle(next);
99    }
100
101    if (next != Particle::INVALID_INDEX)
102    {
103        _particles[next].setPreviousParticle(previous);
104    }
105
106    // reset the next and previous particle entries of this particle
107    particle->setPreviousParticle(Particle::INVALID_INDEX);
108    particle->setNextParticle(Particle::INVALID_INDEX);
109
110    // put the particle on the death stack
111    ParticleSystem::reuseParticle(particleIndex);
112
113}
114
115void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) const
116{
117    osg::State& state = *renderInfo.getState();
118    osg::GLBeginEndAdapter& gl = state.getGLBeginEndAdapter();
119
120    ScopedReadLock lock(_readWriteMutex);
121
122    const Particle* particle = (_startParticle != Particle::INVALID_INDEX) ? &_particles[_startParticle] : 0;
123    if (!particle) return;
124
125
126    osg::Vec4 pixelSizeVector = osg::CullingSet::computePixelSizeVector(*state.getCurrentViewport(),state.getProjectionMatrix(),state.getModelViewMatrix());
127    float unitPixelSize = fabs(1.0/(particle->getPosition()*pixelSizeVector));
128    float pixelSizeOfFirstParticle = unitPixelSize * particle->getCurrentSize();
129    //float desiredGapBetweenDrawnParticles = 50.0f/unitPixelSize;
130    //float desiredGapBetweenDrawnParticles2 = desiredGapBetweenDrawnParticles*desiredGapBetweenDrawnParticles;
131
132    float maxPixelError2 = osg::square(1.0f/unitPixelSize);
133
134    if (pixelSizeOfFirstParticle<1.0)
135    {
136        // draw the connected particles as a line
137        gl.Begin(GL_LINE_STRIP);
138        while(particle != 0)
139        {
140
141            const osg::Vec4& color = particle->getCurrentColor();
142            const osg::Vec3& pos = particle->getPosition();
143            gl.Color4f( color.r(), color.g(), color.b(), color.a() * particle->getCurrentAlpha());
144            gl.TexCoord2f( particle->getSTexCoord(), 0.5f );
145            gl.Vertex3fv(pos.ptr());
146
147            const Particle* nextParticle = (particle->getNextParticle() != Particle::INVALID_INDEX) ? &_particles[particle->getNextParticle()] : 0;
148            if (nextParticle)
149            {
150                const osg::Vec3& nextPos = nextParticle->getPosition();
151                osg::Vec3 startDelta = nextPos-pos;
152                startDelta.normalize();
153                float distance2 = 0.0;
154
155                // now skip particles of required
156                for(unsigned int i=0;
157                    i<_maxNumberOfParticlesToSkip && ((distance2<maxPixelError2) && (nextParticle->getNextParticle()!=Particle::INVALID_INDEX));
158                    ++i)
159                {
160                    nextParticle = &_particles[nextParticle->getNextParticle()];
161                    const osg::Vec3& nextPos = nextParticle->getPosition();
162                    osg::Vec3 delta = nextPos-pos;
163                    distance2 = (delta^startDelta).length2();
164                }
165            }
166            particle = nextParticle;
167        }
168        gl.End();
169    }
170    else
171    {
172
173        // draw the connected particles as a quad stripped aligned to be orthogonal to the eye
174        osg::Matrix eyeToLocalTransform;
175        eyeToLocalTransform.invert(state.getModelViewMatrix());
176        osg::Vec3 eyeLocal = osg::Vec3(0.0f,0.0,0.0f)*eyeToLocalTransform;
177
178        osg::Vec3 delta(0.0f,0.0f,1.0f);
179
180        gl.Begin(GL_QUAD_STRIP);
181        while(particle != 0)
182        {
183            const osg::Vec4& color = particle->getCurrentColor();
184            const osg::Vec3& pos = particle->getPosition();
185
186            const Particle* nextParticle = (particle->getNextParticle() != Particle::INVALID_INDEX) ? &_particles[particle->getNextParticle()] : 0;
187
188            if (nextParticle)
189            {
190                const osg::Vec3& nextPos = nextParticle->getPosition();
191                osg::Vec3 startDelta = nextPos-pos;
192                startDelta.normalize();
193                float distance2 = 0.0;
194
195                // now skip particles of required
196                for(unsigned int i=0;
197                    i<_maxNumberOfParticlesToSkip && ((distance2<maxPixelError2) && (nextParticle->getNextParticle()!=Particle::INVALID_INDEX));
198                    ++i)
199                {
200                    nextParticle = &_particles[nextParticle->getNextParticle()];
201                    const osg::Vec3& nextPos = nextParticle->getPosition();
202                    delta = nextPos-pos;
203                    distance2 = (delta^startDelta).length2();
204                }
205
206                delta = nextPos-pos;
207            }
208
209            osg::Vec3 normal( delta ^ (pos-eyeLocal));
210            normal.normalize();
211            normal *= particle->getCurrentSize();
212
213            osg::Vec3 bottom(pos-normal);
214            osg::Vec3 top(pos+normal);
215
216            gl.Color4f( color.r(), color.g(), color.b(), color.a() * particle->getCurrentAlpha());
217
218            gl.TexCoord2f( particle->getSTexCoord(), 0.0f );
219            gl.Vertex3fv(bottom.ptr());
220
221            gl.TexCoord2f( particle->getSTexCoord(), 1.0f );
222            gl.Vertex3fv(top.ptr());
223
224            particle = nextParticle;
225        }
226        gl.End();
227    }
228}
Note: See TracBrowser for help on using the browser.