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

Revision 13041, 8.7 kB (checked in by robert, 2 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#include <osgParticle/Particle>
2#include <osgParticle/LinearInterpolator>
3#include <osgParticle/ParticleSystem>
4
5#include <osg/Vec3>
6#include <osg/Vec4>
7#include <osg/Matrix>
8#include <osg/GL>
9#include <osg/Notify>
10
11namespace
12{
13
14    const float cosPI3 = cosf(osg::PI / 3.0f);
15    const float sinPI3 = sinf(osg::PI / 3.0f);
16    const float hex_texcoord_x1 = 0.5f + 0.5f * cosPI3;
17    const float hex_texcoord_x2 = 0.5f - 0.5f * cosPI3;
18    const float hex_texcoord_y1 = 0.5f + 0.5f * sinPI3;
19    const float hex_texcoord_y2 = 0.5f - 0.5f * sinPI3;
20
21}
22
23osgParticle::Particle::Particle()
24:   _shape(QUAD),
25    _sr(0.2f, 0.2f),
26    _ar(1, 0),
27    _cr(osg::Vec4(1, 1, 1, 1), osg::Vec4(1, 1, 1, 1)),
28    _si(new LinearInterpolator),
29    _ai(new LinearInterpolator),
30    _ci(new LinearInterpolator),
31    _mustdie(false),
32    _lifeTime(2),
33    _radius(0.2f),
34    _mass(0.1f),
35    _massinv(10.0f),
36    _prev_pos(0, 0, 0),
37    _position(0, 0, 0),
38    _velocity(0, 0, 0),
39    _prev_angle(0, 0, 0),
40    _angle(0, 0, 0),
41    _angul_arvel(0, 0, 0),
42    _t0(0),
43    _alive(1.0f),
44    _current_size(0.0f),
45    _current_alpha(0.0f),
46    _s_tile(1.0f),
47    _t_tile(1.0f),
48    _start_tile(0),
49    _end_tile(0),
50    _cur_tile(-1),
51    _s_coord(0.0f),
52    _t_coord(0.0f),
53    _previousParticle(INVALID_INDEX),
54    _nextParticle(INVALID_INDEX),
55    _depth(0.0)
56{
57}
58
59bool osgParticle::Particle::update(double dt, bool onlyTimeStamp)
60{
61    // this method should return false when the particle dies;
62    // so, if we were instructed to die, do it now and return.
63    if (_mustdie) {
64        _alive = -1.0;
65        return false;
66    }
67
68    double x = 0;
69
70    // if we don't live forever, compute our normalized age.
71    if (_lifeTime > 0) {
72        x = _t0 / _lifeTime;
73    }
74
75    _t0 += dt;
76
77    // if our age is over the lifetime limit, then die and return.
78    if (x > 1) {
79        _alive = -1.0;
80        return false;
81    }
82
83    // compute the current values for size, alpha and color.
84    if (_lifeTime <= 0) {
85       if (dt == _t0) {
86          _current_size = _sr.get_random();
87          _current_alpha = _ar.get_random();
88          _current_color = _cr.get_random();
89       }
90    } else {
91       _current_size = _si.get()->interpolate(x, _sr);
92       _current_alpha = _ai.get()->interpolate(x, _ar);
93       _current_color = _ci.get()->interpolate(x, _cr);
94    }
95
96    // update position
97    _prev_pos = _position;
98    _position += _velocity * dt;
99
100    // return now if we indicate that only time stamp should be updated
101    // the shader will handle remain properties in this case
102    if (onlyTimeStamp) return true;
103
104    //Compute the current texture tile based on our normalized age
105    int currentTile = _start_tile + static_cast<int>(x * getNumTiles());
106
107    //If the current texture tile is different from previous, then compute new texture coords
108    if(currentTile != _cur_tile)
109    {
110
111        _cur_tile = currentTile;
112        _s_coord = _s_tile * fmod(_cur_tile , 1.0 / _s_tile);
113        _t_coord = 1.0 - _t_tile * (static_cast<int>(_cur_tile * _t_tile) + 1);
114
115        // OSG_NOTICE<<this<<" setting tex coords "<<_s_coord<<" "<<_t_coord<<std::endl;
116    }
117
118    // update angle
119    _prev_angle = _angle;
120    _angle += _angul_arvel * dt;
121
122    if (_angle.x() > osg::PI*2) _angle.x() -= osg::PI*2;
123    if (_angle.x() < -osg::PI*2) _angle.x() += osg::PI*2;
124    if (_angle.y() > osg::PI*2) _angle.y() -= osg::PI*2;
125    if (_angle.y() < -osg::PI*2) _angle.y() += osg::PI*2;
126    if (_angle.z() > osg::PI*2) _angle.z() -= osg::PI*2;
127    if (_angle.z() < -osg::PI*2) _angle.z() += osg::PI*2;
128
129    return true;
130}
131
132void osgParticle::Particle::render(osg::GLBeginEndAdapter* gl, const osg::Vec3& xpos, const osg::Vec3& px, const osg::Vec3& py, float scale) const
133{
134    gl->Color4f( _current_color.x(),
135                _current_color.y(),
136                _current_color.z(),
137                _current_color.w() * _current_alpha);
138
139    osg::Vec3 p1(px * _current_size * scale);
140    osg::Vec3 p2(py * _current_size * scale);
141
142    switch (_shape)
143    {
144    case POINT:
145        gl->Vertex3f(xpos.x(), xpos.y(), xpos.z());
146        break;
147
148    case QUAD:
149        gl->TexCoord2f(_s_coord, _t_coord);
150        gl->Vertex3fv((xpos-(p1+p2)).ptr());
151        gl->TexCoord2f(_s_coord+_s_tile, _t_coord);
152        gl->Vertex3fv((xpos+(p1-p2)).ptr());
153        gl->TexCoord2f(_s_coord+_s_tile, _t_coord+_t_tile);
154        gl->Vertex3fv((xpos+(p1+p2)).ptr());
155        gl->TexCoord2f(_s_coord, _t_coord+_t_tile);
156        gl->Vertex3fv((xpos-(p1-p2)).ptr());
157        break;
158
159    case QUAD_TRIANGLESTRIP:
160        gl->PushMatrix();
161        gl->Translatef(xpos.x(), xpos.y(), xpos.z());
162        // we must gl.Begin() and gl.End() here, because each particle is a single strip
163        gl->Begin(GL_TRIANGLE_STRIP);
164        gl->TexCoord2f(_s_coord+_s_tile, _t_coord+_t_tile);
165        gl->Vertex3fv((p1+p2).ptr());
166        gl->TexCoord2f(_s_coord, _t_coord+_t_tile);
167        gl->Vertex3fv((-p1+p2).ptr());
168        gl->TexCoord2f(_s_coord+_s_tile, _t_coord);
169        gl->Vertex3fv((p1-p2).ptr());
170        gl->TexCoord2f(_s_coord, _t_coord);
171        gl->Vertex3fv((-p1-p2).ptr());
172        gl->End();
173        gl->PopMatrix();
174        break;
175
176    case HEXAGON:
177        gl->PushMatrix();
178        gl->Translatef(xpos.x(), xpos.y(), xpos.z());
179        // we must gl.Begin() and gl.End() here, because each particle is a single fan
180        gl->Begin(GL_TRIANGLE_FAN);
181        gl->TexCoord2f(_s_coord + _s_tile * 0.5f, _t_coord + _t_tile * 0.5f);
182        gl->Vertex3f(0,0,0);
183        gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y1);
184        gl->Vertex3fv((p1*cosPI3+p2*sinPI3).ptr());
185        gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x2, _t_coord + _t_tile * hex_texcoord_y1);
186        gl->Vertex3fv((-p1*cosPI3+p2*sinPI3).ptr());
187        gl->TexCoord2f(_s_coord, _t_coord + _t_tile * 0.5f);
188        gl->Vertex3fv((-p1).ptr());
189        gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x2, _t_coord + _t_tile * hex_texcoord_y2);
190        gl->Vertex3fv((-p1*cosPI3-p2*sinPI3).ptr());
191        gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y2);
192        gl->Vertex3fv((p1*cosPI3-p2*sinPI3).ptr());
193        gl->TexCoord2f(_s_coord + _s_tile, _t_coord + _t_tile * 0.5f);
194        gl->Vertex3fv((p1).ptr());
195        gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y1);
196        gl->Vertex3fv((p1*cosPI3+p2*sinPI3).ptr());
197        gl->End();
198        gl->PopMatrix();
199        break;
200
201    case LINE:
202        {
203            // Get the normalized direction of the particle, to be used in the
204            // calculation of one of the linesegment endpoints.
205            float vl = _velocity.length();
206            if (vl != 0) {
207                osg::Vec3 v = _velocity * _current_size * scale / vl;
208
209                gl->TexCoord1f(0);
210                gl->Vertex3f(xpos.x(), xpos.y(), xpos.z());
211                gl->TexCoord1f(1);
212                gl->Vertex3f(xpos.x() + v.x(), xpos.y() + v.y(), xpos.z() + v.z());
213            }
214        }
215        break;
216
217    default:
218        OSG_WARN << "Invalid shape for particles\n";
219    }
220}
221
222void osgParticle::Particle::render(osg::RenderInfo& renderInfo, const osg::Vec3& xpos, const osg::Vec3& xrot) const
223{
224#if defined(OSG_GL_MATRICES_AVAILABLE)
225    if (_drawable.valid())
226    {
227        bool requiresRotation = (xrot.x()!=0.0f || xrot.y()!=0.0f || xrot.z()!=0.0f);
228        glColor4f(_current_color.x(),
229                  _current_color.y(),
230                  _current_color.z(),
231                  _current_color.w() * _current_alpha);
232        glPushMatrix();
233        glTranslatef(xpos.x(), xpos.y(), xpos.z());
234        if (requiresRotation)
235        {
236            osg::Quat rotation(xrot.x(), osg::X_AXIS, xrot.y(), osg::Y_AXIS, xrot.z(), osg::Z_AXIS);
237#if defined(OSG_GLES1_AVAILABLE)
238            glMultMatrixf(osg::Matrixf(rotation).ptr());
239#else
240            glMultMatrixd(osg::Matrixd(rotation).ptr());
241#endif
242        }
243        _drawable->draw(renderInfo);
244        glPopMatrix();
245    }
246#else
247    OSG_NOTICE<<"Warning: Particle::render(..) not supported for user-defined shape."<<std::endl;
248#endif
249}
250
251void osgParticle::Particle::setUpTexCoordsAsPartOfConnectedParticleSystem(ParticleSystem* ps)
252{
253    if (getPreviousParticle()!=Particle::INVALID_INDEX)
254    {
255        update(0.0, false);
256
257        Particle* previousParticle = ps->getParticle(getPreviousParticle());
258        const osg::Vec3& previousPosition = previousParticle->getPosition();
259        const osg::Vec3& newPosition = getPosition();
260        float distance = (newPosition-previousPosition).length();
261        float s_coord_delta = 0.5f*distance/getCurrentSize();
262        float s_coord = previousParticle->_s_coord + s_coord_delta;
263
264        setTextureTile(1,1,0);
265        _cur_tile = 0;
266        _s_coord = s_coord;
267        _t_coord = 0.0f;
268    }
269}
Note: See TracBrowser for help on using the browser.