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

Revision 10660, 7.5 kB (checked in by robert, 4 years ago)

Removed remaining glBegin/glEnd usage

  • 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    _alive(true),
32    _mustdie(false),
33    _lifeTime(2),
34    _radius(0.2f),
35    _mass(0.1f),
36    _massinv(10.0f),
37    _prev_pos(0, 0, 0),
38    _position(0, 0, 0),
39    _velocity(0, 0, 0),
40    _prev_angle(0, 0, 0),
41    _angle(0, 0, 0),
42    _angul_arvel(0, 0, 0),
43    _t0(0),
44    _current_size(0),
45    _current_alpha(0),
46    _s_tile(1.0f),
47    _t_tile(1.0f),
48    _num_tile(1),
49    _cur_tile(-1),
50    _s_coord(0.0f),
51    _t_coord(0.0f),
52    _previousParticle(INVALID_INDEX),
53    _nextParticle(INVALID_INDEX)
54{
55}
56
57bool osgParticle::Particle::update(double dt)
58{
59    // this method should return false when the particle dies;
60    // so, if we were instructed to die, do it now and return.
61    if (_mustdie) {
62        _alive = false;
63        return false;
64    }
65
66    double x = 0;   
67
68    // if we don't live forever, compute our normalized age.
69    if (_lifeTime > 0) {
70        x = _t0 / _lifeTime;
71    }
72
73    _t0 += dt;
74
75    // if our age is over the lifetime limit, then die and return.
76    if (x > 1) {
77        _alive = false;
78        return false;
79    }
80
81    //Compute the current texture tile based on our normalized age
82    int currentTile = static_cast<int>(x * _num_tile);
83   
84    //If the current texture tile is different from previous, then compute new texture coords
85    if(currentTile != _cur_tile)
86    {
87   
88        _cur_tile = currentTile;
89        _s_coord = _s_tile * fmod(_cur_tile , 1.0 / _s_tile);
90        _t_coord = 1.0 - _t_tile * (static_cast<int>(_cur_tile * _t_tile) + 1);
91
92        // osg::notify(osg::NOTICE)<<this<<" setting tex coords "<<_s_coord<<" "<<_t_coord<<std::endl;
93    }
94   
95    // compute the current values for size, alpha and color.
96    if (_lifeTime <= 0) {
97       if (dt == _t0) {
98          _current_size = _sr.get_random();
99          _current_alpha = _ar.get_random();
100          _current_color = _cr.get_random();
101       }
102    } else {
103       _current_size = _si.get()->interpolate(x, _sr);
104       _current_alpha = _ai.get()->interpolate(x, _ar);
105       _current_color = _ci.get()->interpolate(x, _cr);
106    }
107
108    // update position
109    _prev_pos = _position;
110    _position += _velocity * dt;
111
112    // update angle
113    _prev_angle = _angle;
114    _angle += _angul_arvel * dt;
115
116    if (_angle.x() > osg::PI*2) _angle.x() -= osg::PI*2;
117    if (_angle.x() < -osg::PI*2) _angle.x() += osg::PI*2;
118    if (_angle.y() > osg::PI*2) _angle.y() -= osg::PI*2;
119    if (_angle.y() < -osg::PI*2) _angle.y() += osg::PI*2;
120    if (_angle.z() > osg::PI*2) _angle.z() -= osg::PI*2;
121    if (_angle.z() < -osg::PI*2) _angle.z() += osg::PI*2;
122
123    return true;
124}
125
126void osgParticle::Particle::render(osg::GLBeginEndAdapter* gl, const osg::Vec3& xpos, const osg::Vec3& px, const osg::Vec3& py, float scale) const
127{
128    gl->Color4f( _current_color.x(),
129                _current_color.y(),
130                _current_color.z(),
131                _current_color.w() * _current_alpha);
132
133    osg::Vec3 p1(px * _current_size * scale);
134    osg::Vec3 p2(py * _current_size * scale);
135
136    switch (_shape)
137    {
138    case POINT:
139        gl->Vertex3f(xpos.x(), xpos.y(), xpos.z());
140        break;
141
142    case QUAD:
143        gl->TexCoord2f(_s_coord, _t_coord);
144        gl->Vertex3fv((xpos-(p1+p2)).ptr());
145        gl->TexCoord2f(_s_coord+_s_tile, _t_coord);
146        gl->Vertex3fv((xpos+(p1-p2)).ptr());
147        gl->TexCoord2f(_s_coord+_s_tile, _t_coord+_t_tile);
148        gl->Vertex3fv((xpos+(p1+p2)).ptr());
149        gl->TexCoord2f(_s_coord, _t_coord+_t_tile);
150        gl->Vertex3fv((xpos-(p1-p2)).ptr());
151        break;
152
153    case QUAD_TRIANGLESTRIP:
154        gl->PushMatrix();
155        gl->Translatef(xpos.x(), xpos.y(), xpos.z());
156        // we must gl.Begin() and gl.End() here, because each particle is a single strip
157        gl->Begin(GL_TRIANGLE_STRIP);
158        gl->TexCoord2f(_s_coord+_s_tile, _t_coord+_t_tile);
159        gl->Vertex3fv((p1+p2).ptr());
160        gl->TexCoord2f(_s_coord, _t_coord+_t_tile);
161        gl->Vertex3fv((-p1+p2).ptr());
162        gl->TexCoord2f(_s_coord+_s_tile, _t_coord);
163        gl->Vertex3fv((p1-p2).ptr());
164        gl->TexCoord2f(_s_coord, _t_coord);
165        gl->Vertex3fv((-p1-p2).ptr());
166        gl->End();
167        gl->PopMatrix();
168        break;
169
170    case HEXAGON:
171        gl->PushMatrix();
172        gl->Translatef(xpos.x(), xpos.y(), xpos.z());
173        // we must gl.Begin() and gl.End() here, because each particle is a single fan
174        gl->Begin(GL_TRIANGLE_FAN);
175        gl->TexCoord2f(_s_coord + _s_tile * 0.5f, _t_coord + _t_tile * 0.5f);
176        gl->Vertex3f(0,0,0);
177        gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y1);
178        gl->Vertex3fv((p1*cosPI3+p2*sinPI3).ptr());
179        gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x2, _t_coord + _t_tile * hex_texcoord_y1);
180        gl->Vertex3fv((-p1*cosPI3+p2*sinPI3).ptr());
181        gl->TexCoord2f(_s_coord, _t_coord + _t_tile * 0.5f);
182        gl->Vertex3fv((-p1).ptr());
183        gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x2, _t_coord + _t_tile * hex_texcoord_y2);
184        gl->Vertex3fv((-p1*cosPI3-p2*sinPI3).ptr());
185        gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y2);
186        gl->Vertex3fv((p1*cosPI3-p2*sinPI3).ptr());
187        gl->TexCoord2f(_s_coord + _s_tile, _t_coord + _t_tile * 0.5f);
188        gl->Vertex3fv((p1).ptr());
189        gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y1);
190        gl->Vertex3fv((p1*cosPI3+p2*sinPI3).ptr());
191        gl->End();
192        break;
193
194    case LINE:
195        {
196            // Get the normalized direction of the particle, to be used in the
197            // calculation of one of the linesegment endpoints.
198            float vl = _velocity.length();
199            if (vl != 0) {
200                osg::Vec3 v = _velocity * _current_size * scale / vl;
201
202                gl->TexCoord1f(0);
203                gl->Vertex3f(xpos.x(), xpos.y(), xpos.z());
204                gl->TexCoord1f(1);
205                gl->Vertex3f(xpos.x() + v.x(), xpos.y() + v.y(), xpos.z() + v.z());
206            }
207        }
208        break;
209
210    default:
211        osg::notify(osg::WARN) << "Invalid shape for particles\n";
212    }
213}
214
215void osgParticle::Particle::setUpTexCoordsAsPartOfConnectedParticleSystem(ParticleSystem* ps)
216{
217    if (getPreviousParticle()!=Particle::INVALID_INDEX)
218    {
219        update(0.0);
220
221        Particle* previousParticle = ps->getParticle(getPreviousParticle());
222        const osg::Vec3& previousPosition = previousParticle->getPosition();
223        const osg::Vec3& newPosition = getPosition();
224        float distance = (newPosition-previousPosition).length();
225        float s_coord_delta = 0.5f*distance/getCurrentSize();
226        float s_coord = previousParticle->_s_coord + s_coord_delta;
227
228        setTextureTile(1,1,0);
229        _cur_tile = 0;
230        _s_coord = s_coord;
231        _t_coord = 0.0f;
232    }
233}
Note: See TracBrowser for help on using the browser.