| 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 | |
|---|
| 11 | namespace |
|---|
| 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 | |
|---|
| 23 | osgParticle::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 | _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 | { |
|---|
| 56 | } |
|---|
| 57 | |
|---|
| 58 | bool osgParticle::Particle::update(double dt) |
|---|
| 59 | { |
|---|
| 60 | |
|---|
| 61 | |
|---|
| 62 | if (_mustdie) { |
|---|
| 63 | _alive = false; |
|---|
| 64 | return false; |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | double x = 0; |
|---|
| 68 | |
|---|
| 69 | |
|---|
| 70 | if (_lifeTime > 0) { |
|---|
| 71 | x = _t0 / _lifeTime; |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | _t0 += dt; |
|---|
| 75 | |
|---|
| 76 | |
|---|
| 77 | if (x > 1) { |
|---|
| 78 | _alive = false; |
|---|
| 79 | return false; |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | |
|---|
| 83 | int currentTile = _start_tile + static_cast<int>(x * getNumTiles()); |
|---|
| 84 | |
|---|
| 85 | |
|---|
| 86 | if(currentTile != _cur_tile) |
|---|
| 87 | { |
|---|
| 88 | |
|---|
| 89 | _cur_tile = currentTile; |
|---|
| 90 | _s_coord = _s_tile * fmod(_cur_tile , 1.0 / _s_tile); |
|---|
| 91 | _t_coord = 1.0 - _t_tile * (static_cast<int>(_cur_tile * _t_tile) + 1); |
|---|
| 92 | |
|---|
| 93 | |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | |
|---|
| 97 | if (_lifeTime <= 0) { |
|---|
| 98 | if (dt == _t0) { |
|---|
| 99 | _current_size = _sr.get_random(); |
|---|
| 100 | _current_alpha = _ar.get_random(); |
|---|
| 101 | _current_color = _cr.get_random(); |
|---|
| 102 | } |
|---|
| 103 | } else { |
|---|
| 104 | _current_size = _si.get()->interpolate(x, _sr); |
|---|
| 105 | _current_alpha = _ai.get()->interpolate(x, _ar); |
|---|
| 106 | _current_color = _ci.get()->interpolate(x, _cr); |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | |
|---|
| 110 | _prev_pos = _position; |
|---|
| 111 | _position += _velocity * dt; |
|---|
| 112 | |
|---|
| 113 | |
|---|
| 114 | _prev_angle = _angle; |
|---|
| 115 | _angle += _angul_arvel * dt; |
|---|
| 116 | |
|---|
| 117 | if (_angle.x() > osg::PI*2) _angle.x() -= osg::PI*2; |
|---|
| 118 | if (_angle.x() < -osg::PI*2) _angle.x() += osg::PI*2; |
|---|
| 119 | if (_angle.y() > osg::PI*2) _angle.y() -= osg::PI*2; |
|---|
| 120 | if (_angle.y() < -osg::PI*2) _angle.y() += osg::PI*2; |
|---|
| 121 | if (_angle.z() > osg::PI*2) _angle.z() -= osg::PI*2; |
|---|
| 122 | if (_angle.z() < -osg::PI*2) _angle.z() += osg::PI*2; |
|---|
| 123 | |
|---|
| 124 | return true; |
|---|
| 125 | } |
|---|
| 126 | |
|---|
| 127 | void osgParticle::Particle::render(osg::GLBeginEndAdapter* gl, const osg::Vec3& xpos, const osg::Vec3& px, const osg::Vec3& py, float scale) const |
|---|
| 128 | { |
|---|
| 129 | gl->Color4f( _current_color.x(), |
|---|
| 130 | _current_color.y(), |
|---|
| 131 | _current_color.z(), |
|---|
| 132 | _current_color.w() * _current_alpha); |
|---|
| 133 | |
|---|
| 134 | osg::Vec3 p1(px * _current_size * scale); |
|---|
| 135 | osg::Vec3 p2(py * _current_size * scale); |
|---|
| 136 | |
|---|
| 137 | switch (_shape) |
|---|
| 138 | { |
|---|
| 139 | case POINT: |
|---|
| 140 | gl->Vertex3f(xpos.x(), xpos.y(), xpos.z()); |
|---|
| 141 | break; |
|---|
| 142 | |
|---|
| 143 | case QUAD: |
|---|
| 144 | gl->TexCoord2f(_s_coord, _t_coord); |
|---|
| 145 | gl->Vertex3fv((xpos-(p1+p2)).ptr()); |
|---|
| 146 | gl->TexCoord2f(_s_coord+_s_tile, _t_coord); |
|---|
| 147 | gl->Vertex3fv((xpos+(p1-p2)).ptr()); |
|---|
| 148 | gl->TexCoord2f(_s_coord+_s_tile, _t_coord+_t_tile); |
|---|
| 149 | gl->Vertex3fv((xpos+(p1+p2)).ptr()); |
|---|
| 150 | gl->TexCoord2f(_s_coord, _t_coord+_t_tile); |
|---|
| 151 | gl->Vertex3fv((xpos-(p1-p2)).ptr()); |
|---|
| 152 | break; |
|---|
| 153 | |
|---|
| 154 | case QUAD_TRIANGLESTRIP: |
|---|
| 155 | gl->PushMatrix(); |
|---|
| 156 | gl->Translatef(xpos.x(), xpos.y(), xpos.z()); |
|---|
| 157 | |
|---|
| 158 | gl->Begin(GL_TRIANGLE_STRIP); |
|---|
| 159 | gl->TexCoord2f(_s_coord+_s_tile, _t_coord+_t_tile); |
|---|
| 160 | gl->Vertex3fv((p1+p2).ptr()); |
|---|
| 161 | gl->TexCoord2f(_s_coord, _t_coord+_t_tile); |
|---|
| 162 | gl->Vertex3fv((-p1+p2).ptr()); |
|---|
| 163 | gl->TexCoord2f(_s_coord+_s_tile, _t_coord); |
|---|
| 164 | gl->Vertex3fv((p1-p2).ptr()); |
|---|
| 165 | gl->TexCoord2f(_s_coord, _t_coord); |
|---|
| 166 | gl->Vertex3fv((-p1-p2).ptr()); |
|---|
| 167 | gl->End(); |
|---|
| 168 | gl->PopMatrix(); |
|---|
| 169 | break; |
|---|
| 170 | |
|---|
| 171 | case HEXAGON: |
|---|
| 172 | gl->PushMatrix(); |
|---|
| 173 | gl->Translatef(xpos.x(), xpos.y(), xpos.z()); |
|---|
| 174 | |
|---|
| 175 | gl->Begin(GL_TRIANGLE_FAN); |
|---|
| 176 | gl->TexCoord2f(_s_coord + _s_tile * 0.5f, _t_coord + _t_tile * 0.5f); |
|---|
| 177 | gl->Vertex3f(0,0,0); |
|---|
| 178 | gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y1); |
|---|
| 179 | gl->Vertex3fv((p1*cosPI3+p2*sinPI3).ptr()); |
|---|
| 180 | gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x2, _t_coord + _t_tile * hex_texcoord_y1); |
|---|
| 181 | gl->Vertex3fv((-p1*cosPI3+p2*sinPI3).ptr()); |
|---|
| 182 | gl->TexCoord2f(_s_coord, _t_coord + _t_tile * 0.5f); |
|---|
| 183 | gl->Vertex3fv((-p1).ptr()); |
|---|
| 184 | gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x2, _t_coord + _t_tile * hex_texcoord_y2); |
|---|
| 185 | gl->Vertex3fv((-p1*cosPI3-p2*sinPI3).ptr()); |
|---|
| 186 | gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y2); |
|---|
| 187 | gl->Vertex3fv((p1*cosPI3-p2*sinPI3).ptr()); |
|---|
| 188 | gl->TexCoord2f(_s_coord + _s_tile, _t_coord + _t_tile * 0.5f); |
|---|
| 189 | gl->Vertex3fv((p1).ptr()); |
|---|
| 190 | gl->TexCoord2f(_s_coord + _s_tile * hex_texcoord_x1, _t_coord + _t_tile * hex_texcoord_y1); |
|---|
| 191 | gl->Vertex3fv((p1*cosPI3+p2*sinPI3).ptr()); |
|---|
| 192 | gl->End(); |
|---|
| 193 | break; |
|---|
| 194 | |
|---|
| 195 | case LINE: |
|---|
| 196 | { |
|---|
| 197 | |
|---|
| 198 | |
|---|
| 199 | float vl = _velocity.length(); |
|---|
| 200 | if (vl != 0) { |
|---|
| 201 | osg::Vec3 v = _velocity * _current_size * scale / vl; |
|---|
| 202 | |
|---|
| 203 | gl->TexCoord1f(0); |
|---|
| 204 | gl->Vertex3f(xpos.x(), xpos.y(), xpos.z()); |
|---|
| 205 | gl->TexCoord1f(1); |
|---|
| 206 | gl->Vertex3f(xpos.x() + v.x(), xpos.y() + v.y(), xpos.z() + v.z()); |
|---|
| 207 | } |
|---|
| 208 | } |
|---|
| 209 | break; |
|---|
| 210 | |
|---|
| 211 | default: |
|---|
| 212 | osg::notify(osg::WARN) << "Invalid shape for particles\n"; |
|---|
| 213 | } |
|---|
| 214 | } |
|---|
| 215 | |
|---|
| 216 | void osgParticle::Particle::setUpTexCoordsAsPartOfConnectedParticleSystem(ParticleSystem* ps) |
|---|
| 217 | { |
|---|
| 218 | if (getPreviousParticle()!=Particle::INVALID_INDEX) |
|---|
| 219 | { |
|---|
| 220 | update(0.0); |
|---|
| 221 | |
|---|
| 222 | Particle* previousParticle = ps->getParticle(getPreviousParticle()); |
|---|
| 223 | const osg::Vec3& previousPosition = previousParticle->getPosition(); |
|---|
| 224 | const osg::Vec3& newPosition = getPosition(); |
|---|
| 225 | float distance = (newPosition-previousPosition).length(); |
|---|
| 226 | float s_coord_delta = 0.5f*distance/getCurrentSize(); |
|---|
| 227 | float s_coord = previousParticle->_s_coord + s_coord_delta; |
|---|
| 228 | |
|---|
| 229 | setTextureTile(1,1,0); |
|---|
| 230 | _cur_tile = 0; |
|---|
| 231 | _s_coord = s_coord; |
|---|
| 232 | _t_coord = 0.0f; |
|---|
| 233 | } |
|---|
| 234 | } |
|---|