diff --git a/include/osgParticle/ConstantRateCounter b/include/osgParticle/ConstantRateCounter index 6ea677514..41ef51dbd 100644 --- a/include/osgParticle/ConstantRateCounter +++ b/include/osgParticle/ConstantRateCounter @@ -63,6 +63,15 @@ namespace osgParticle return osg::maximum(_minimumNumberOfParticlesToCreate, i); } + + virtual int getEstimatedMaxNumOfParticles(double lifeTime) const + { + int minNumParticles = static_cast(_minimumNumberOfParticlesToCreate*60.0f*lifeTime); + int baseNumPartciles = static_cast(_numberOfParticlesPerSecondToCreate * lifeTime); + return osg::maximum(minNumParticles, baseNumPartciles); + } + + protected: virtual ~ConstantRateCounter() {} diff --git a/include/osgParticle/Counter b/include/osgParticle/Counter index 071ebc708..dde87e1ad 100644 --- a/include/osgParticle/Counter +++ b/include/osgParticle/Counter @@ -30,8 +30,12 @@ namespace osgParticle virtual const char* className() const { return "Counter"; } virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj) != 0; } + /** get the number of particle of create for current frame.*/ virtual int numParticlesToCreate(double dt) const = 0; + /** get the esimated maximum number of particles that would be generated duration the lifetime of a particle before it expires.*/ + virtual int getEstimatedMaxNumOfParticles(double lifeTime) const = 0; + protected: ~Counter() {} Counter &operator=(const Counter &) { return *this; } diff --git a/include/osgParticle/Emitter b/include/osgParticle/Emitter index a433e6832..ff8a6a10e 100644 --- a/include/osgParticle/Emitter +++ b/include/osgParticle/Emitter @@ -42,6 +42,12 @@ namespace osgParticle virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj) != 0; } virtual void accept(osg::NodeVisitor& nv) { if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); } } + void setParticleSystem(ParticleSystem* ps); + + void setEstimatedMaxNumOfParticles(int num); + int getEstimatedMaxNumOfParticles() const { return _estimatedMaxNumOfParticles; } + + /// Get the particle template. inline const Particle& getParticleTemplate() const; @@ -67,6 +73,8 @@ namespace osgParticle bool _usedeftemp; Particle _ptemp; + + int _estimatedMaxNumOfParticles; }; // INLINE FUNCTIONS diff --git a/include/osgParticle/Particle b/include/osgParticle/Particle index 0d401651c..9c2937d0b 100644 --- a/include/osgParticle/Particle +++ b/include/osgParticle/Particle @@ -23,9 +23,6 @@ #include #include #include -#include -#include -#include namespace osgParticle { @@ -150,6 +147,13 @@ namespace osgParticle /// Get the t texture coordinate of the bottom left of the particle inline float getTTexCoord() const { return _t_coord; } + /// Get the texture coordinate width of the particle + inline float getSTexTile() const { return _s_tile; } + + /// Get the texture coordinate height of the particle + inline float getTTexTile() const { return _t_tile; } + + /// Get width of texture tile inline int getTileS() const; @@ -240,15 +244,6 @@ namespace osgParticle */ bool update(double dt, bool onlyTimeStamp); - /// Perform some pre-rendering tasks. Called automatically by particle systems. - inline void beginRender(osg::GLBeginEndAdapter* gl) const; - - /// Render the particle. Called automatically by particle systems. - void render(osg::GLBeginEndAdapter* gl, const osg::Vec3& xpos, const osg::Vec3& px, const osg::Vec3& py, float scale = 1.0f) const; - - /// Perform some post-rendering tasks. Called automatically by particle systems. - inline void endRender(osg::GLBeginEndAdapter* gl) const; - /// Get the current (interpolated) polygon size. Valid only after the first call to update(). inline float getCurrentSize() const; @@ -560,36 +555,6 @@ namespace osgParticle _massinv = 1 / m; } - inline void Particle::beginRender(osg::GLBeginEndAdapter* gl) const - { - switch (_shape) - { - case POINT: - gl->Begin(GL_POINTS); - break; - case QUAD: - gl->Begin(GL_QUADS); - break; - case LINE: - gl->Begin(GL_LINES); - break; - default: ; - } - } - - inline void Particle::endRender(osg::GLBeginEndAdapter* gl) const - { - switch (_shape) - { - case POINT: - case QUAD: - case LINE: - gl->End(); - break; - default: ; - } - } - inline float Particle::getCurrentSize() const { return _current_size; diff --git a/include/osgParticle/ParticleProcessor b/include/osgParticle/ParticleProcessor index 58f0cd7b6..e6424ea40 100644 --- a/include/osgParticle/ParticleProcessor +++ b/include/osgParticle/ParticleProcessor @@ -71,7 +71,7 @@ namespace osgParticle inline const ParticleSystem* getParticleSystem() const; /// Set the destination particle system. - inline void setParticleSystem(ParticleSystem* ps); + virtual void setParticleSystem(ParticleSystem* ps); /// Set the endless flag of this processor. inline void setEndless(bool type); @@ -148,7 +148,6 @@ namespace osgParticle virtual void process(double dt) = 0; - private: ReferenceFrame _rf; bool _enabled; double _t0; @@ -211,10 +210,6 @@ namespace osgParticle return _ps.get(); } - inline void ParticleProcessor::setParticleSystem(ParticleSystem* ps) - { - _ps = ps; - } inline void ParticleProcessor::setEndless(bool type) { diff --git a/include/osgParticle/ParticleSystem b/include/osgParticle/ParticleSystem index b1a1ac571..e3e76f46b 100644 --- a/include/osgParticle/ParticleSystem +++ b/include/osgParticle/ParticleSystem @@ -267,6 +267,11 @@ namespace osgParticle virtual osg::VertexArrayState* createVertexArrayState(osg::RenderInfo& renderInfo, bool usingVBOs) const; + void adjustEstimatedMaxNumOfParticles(int delta) { _estimatedMaxNumOfParticles += delta; } + + void setEstimatedMaxNumOfParticles(int num) { _estimatedMaxNumOfParticles = num; } + int getEstimatedMaxNumOfParticles() const { return _estimatedMaxNumOfParticles; } + protected: virtual ~ParticleSystem(); @@ -277,6 +282,8 @@ namespace osgParticle void single_pass_render(osg::RenderInfo& renderInfo, const osg::Matrix& modelview) const; void render_vertex_array(osg::RenderInfo& renderInfo) const; + void new_drawImplementation(osg::RenderInfo& renderInfo) const; + typedef std::vector Particle_vector; typedef std::stack Death_stack; @@ -315,23 +322,38 @@ namespace osgParticle SortMode _sortMode; double _visibilityDistance; - mutable int _draw_count; - mutable ReadWriterMutex _readWriteMutex; + int _estimatedMaxNumOfParticles; + struct ArrayData { ArrayData(); + void init(); + void init3(); + void reserve(unsigned int numVertices); void resize(unsigned int numVertices); void resizeGLObjectBuffers(unsigned int maxSize); void releaseGLObjects(osg::State* state); + void clear(); + void dirty(); + + void dispatchArrays(osg::State& state); + void dispatchPrimitives(); + osg::ref_ptr vertexBufferObject; osg::ref_ptr vertices; + osg::ref_ptr normals; osg::ref_ptr colors; - osg::ref_ptr texcoords; + osg::ref_ptr texcoords2; + osg::ref_ptr texcoords3; + + typedef std::pair ModeCount; + typedef std::vector Primitives; + Primitives primitives; }; typedef osg::buffered_object< ArrayData > BufferedArrayData; diff --git a/include/osgParticle/VariableRateCounter b/include/osgParticle/VariableRateCounter index 6b974973d..f54f99ee2 100644 --- a/include/osgParticle/VariableRateCounter +++ b/include/osgParticle/VariableRateCounter @@ -37,6 +37,8 @@ namespace osgParticle inline void setRateRange(const rangef& r); inline void setRateRange(float minrange, float maxrange); + virtual int getEstimatedMaxNumOfParticles(double lifeTime) const { return static_cast(_rate_range.maximum * lifeTime); } + protected: virtual ~VariableRateCounter() {} diff --git a/src/osgParticle/ConnectedParticleSystem.cpp b/src/osgParticle/ConnectedParticleSystem.cpp index 923315c8c..02eea9e33 100644 --- a/src/osgParticle/ConnectedParticleSystem.cpp +++ b/src/osgParticle/ConnectedParticleSystem.cpp @@ -114,14 +114,29 @@ void ConnectedParticleSystem::reuseParticle(int particleIndex) void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) const { - osg::State& state = *renderInfo.getState(); - osg::GLBeginEndAdapter& gl = state.getGLBeginEndAdapter(); - ScopedReadLock lock(_readWriteMutex); + osg::State& state = *renderInfo.getState(); + const Particle* particle = (_startParticle != Particle::INVALID_INDEX) ? &_particles[_startParticle] : 0; if (!particle) return; + ArrayData& ad = _bufferedArrayData[state.getContextID()]; + if (!ad.vertices.valid()) + { + ad.init(); + ad.reserve(_particles.capacity()*2); + } + + ad.clear(); + ad.dirty(); + + // set up arrays and primitives ready to fill in + osg::Vec3Array& vertices = *ad.vertices; + osg::Vec4Array& colors = *ad.colors; + osg::Vec2Array& texcoords = *ad.texcoords2; + ArrayData::Primitives& primitives = ad.primitives; + osg::Vec4 pixelSizeVector = osg::CullingSet::computePixelSizeVector(*state.getCurrentViewport(),state.getProjectionMatrix(),state.getModelViewMatrix()); float unitPixelSize = fabs(1.0/(particle->getPosition()*pixelSizeVector)); @@ -134,15 +149,14 @@ void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) co if (pixelSizeOfFirstParticle<1.0) { // draw the connected particles as a line - gl.Begin(GL_LINE_STRIP); while(particle != 0) { const osg::Vec4& color = particle->getCurrentColor(); const osg::Vec3& pos = particle->getPosition(); - gl.Color4f( color.r(), color.g(), color.b(), color.a() * particle->getCurrentAlpha()); - gl.TexCoord2f( particle->getSTexCoord(), 0.5f ); - gl.Vertex3fv(pos.ptr()); + colors.push_back(osg::Vec4( color.r(), color.g(), color.b(), color.a() * particle->getCurrentAlpha())); + texcoords.push_back(osg::Vec2( particle->getSTexCoord(), 0.5f )); + vertices.push_back(pos); const Particle* nextParticle = (particle->getNextParticle() != Particle::INVALID_INDEX) ? &_particles[particle->getNextParticle()] : 0; if (nextParticle) @@ -163,11 +177,11 @@ void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) co } particle = nextParticle; } - gl.End(); + + primitives.push_back(ArrayData::ModeCount(GL_LINE_STRIP, vertices.size())); } else { - // draw the connected particles as a quad stripped aligned to be orthogonal to the eye osg::Matrix eyeToLocalTransform; eyeToLocalTransform.invert(state.getModelViewMatrix()); @@ -175,7 +189,6 @@ void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) co osg::Vec3 delta(0.0f,0.0f,1.0f); - gl.Begin(GL_QUAD_STRIP); while(particle != 0) { const osg::Vec4& color = particle->getCurrentColor(); @@ -209,17 +222,20 @@ void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) co osg::Vec3 bottom(pos-normal); osg::Vec3 top(pos+normal); - gl.Color4f( color.r(), color.g(), color.b(), color.a() * particle->getCurrentAlpha()); + colors.push_back(osg::Vec4( color.r(), color.g(), color.b(), color.a() * particle->getCurrentAlpha())); + texcoords.push_back( osg::Vec2( particle->getSTexCoord(), 0.0f )); + vertices.push_back(bottom); - gl.TexCoord2f( particle->getSTexCoord(), 0.0f ); - gl.Vertex3fv(bottom.ptr()); - - gl.TexCoord2f( particle->getSTexCoord(), 1.0f ); - gl.Vertex3fv(top.ptr()); + colors.push_back(colors.back()); + texcoords.push_back( osg::Vec2( particle->getSTexCoord(), 1.0f )); + vertices.push_back(top); particle = nextParticle; } - gl.End(); - } -} + primitives.push_back(ArrayData::ModeCount(GL_QUAD_STRIP, vertices.size())); + } + + ad.dispatchArrays(state); + ad.dispatchPrimitives(); +} diff --git a/src/osgParticle/Emitter.cpp b/src/osgParticle/Emitter.cpp index d01c6bf10..4f0697897 100644 --- a/src/osgParticle/Emitter.cpp +++ b/src/osgParticle/Emitter.cpp @@ -5,13 +5,31 @@ osgParticle::Emitter::Emitter() : ParticleProcessor(), - _usedeftemp(true) + _usedeftemp(true), + _estimatedMaxNumOfParticles(0) { } osgParticle::Emitter::Emitter(const Emitter& copy, const osg::CopyOp& copyop) : ParticleProcessor(copy, copyop), _usedeftemp(copy._usedeftemp), - _ptemp(copy._ptemp) + _ptemp(copy._ptemp), + _estimatedMaxNumOfParticles(0) { } + +void osgParticle::Emitter::setParticleSystem(ParticleSystem* ps) +{ + if (_ps==ps) return; + + ParticleProcessor::setParticleSystem(ps); + + if (_ps) _ps->adjustEstimatedMaxNumOfParticles(_estimatedMaxNumOfParticles); +} + +void osgParticle::Emitter::setEstimatedMaxNumOfParticles(int num) +{ + if (_ps) _ps->adjustEstimatedMaxNumOfParticles(num-_estimatedMaxNumOfParticles); + + _estimatedMaxNumOfParticles = num; +} diff --git a/src/osgParticle/ModularEmitter.cpp b/src/osgParticle/ModularEmitter.cpp index 0cd708f88..8ca573d3a 100644 --- a/src/osgParticle/ModularEmitter.cpp +++ b/src/osgParticle/ModularEmitter.cpp @@ -33,6 +33,15 @@ void osgParticle::ModularEmitter::emitParticles(double dt) worldToPs = osg::Matrix::inverse(psToWorld); } + const Particle& particleTemplate = getUseDefaultTemplate() ? getParticleSystem()->getDefaultParticleTemplate() : getParticleTemplate(); + + double duration = particleTemplate.getLifeTime(); + if (!getEndless() && getLifeTime()getEstimatedMaxNumOfParticles(duration); + float esimateMaxNumScale = 1.1f; + if (getReferenceFrame() == RELATIVE_RF) { const osg::Matrix& ltw = getLocalToWorldMatrix(); @@ -45,26 +54,41 @@ void osgParticle::ModularEmitter::emitParticles(double dt) if (_numParticleToCreateMovementCompensationRatio>0.0f) { // compute the distance moved between frames - const osg::Vec3d controlPosition - = osg::Vec3d(_placer->getControlPosition()); + const osg::Vec3d controlPosition = osg::Vec3d(_placer->getControlPosition()); osg::Vec3d previousPosition = controlPosition * previous_ltw; osg::Vec3d currentPosition = controlPosition * ltw; float distance = (currentPosition-previousPosition).length(); - float size = getUseDefaultTemplate() ? - getParticleSystem()->getDefaultParticleTemplate().getSizeRange().minimum : - getParticleTemplate().getSizeRange().minimum; + float size = particleTemplate.getSizeRange().minimum; float num_extra_samples = _numParticleToCreateMovementCompensationRatio*distance/size; float rounded_down = floor(num_extra_samples); float remainder = num_extra_samples-rounded_down; n = osg::maximum(n, int(rounded_down) + (((float) rand() < remainder * (float)RAND_MAX) ? 1 : 0)); + + unsigned int num_for_duration = static_cast((num_extra_samples/dt) * duration); + if (num_for_duration>num_before_end_of_lifetime) + { + num_before_end_of_lifetime = num_for_duration; + } + + } + num_before_end_of_lifetime = static_cast( ceilf(static_cast(num_before_end_of_lifetime) * esimateMaxNumScale)); + + setEstimatedMaxNumOfParticles(num_before_end_of_lifetime); + + + // double num_per_second = (static_cast(n)/dt); + // OSG_NOTICE<<"emitParticle count="<<_counter->className()<<" ps="< #include +#include #include #define USE_LOCAL_SHADERS @@ -54,7 +55,7 @@ osgParticle::ParticleSystem::ParticleSystem() _detail(1), _sortMode(NO_SORT), _visibilityDistance(-1.0), - _draw_count(0) + _estimatedMaxNumOfParticles(0) { // we don't support display lists because particle systems // are dynamic, and they always changes between frames @@ -86,18 +87,20 @@ osgParticle::ParticleSystem::ParticleSystem(const ParticleSystem& copy, const os _detail(copy._detail), _sortMode(copy._sortMode), _visibilityDistance(copy._visibilityDistance), - _draw_count(0) + _estimatedMaxNumOfParticles(0) { } osgParticle::ParticleSystem::~ParticleSystem() { +// OSG_NOTICE<<"ParticleSystem::~ParticleSystem() "<getGLBeginEndAdapter()); - - float scale = sqrtf(static_cast(_detail)); - - osg::Vec3 xAxis = _align_X_axis; - osg::Vec3 yAxis = _align_Y_axis; - - osg::Vec3 scaled_aligned_xAxis = _align_X_axis; - osg::Vec3 scaled_aligned_yAxis = _align_Y_axis; - - float xScale = 1.0f; - float yScale = 1.0f; - - if (_alignment==BILLBOARD) - { - xAxis = osg::Matrix::transform3x3(modelview,_align_X_axis); - yAxis = osg::Matrix::transform3x3(modelview,_align_Y_axis); - - float lengthX2 = xAxis.length2(); - float lengthY2 = yAxis.length2(); - - if (_particleScaleReferenceFrame==LOCAL_COORDINATES) - { - xScale = 1.0f/sqrtf(lengthX2); - yScale = 1.0f/sqrtf(lengthY2); - } - else - { - xScale = 1.0f/lengthX2; - yScale = 1.0f/lengthY2; - } - - scaled_aligned_xAxis *= xScale; - scaled_aligned_yAxis *= yScale; - - xAxis *= xScale; - yAxis *= yScale; - } - - bool requiresEndRender = false; - const Particle* startParticle = &_particles[0]; - - startParticle->beginRender(gl); - requiresEndRender = true; - - for(unsigned int i=0; i<_particles.size(); i+=_detail) - { - const Particle* currentParticle = &_particles[i]; - - bool insideDistance = true; - if (_sortMode != NO_SORT && _visibilityDistance>0.0) - insideDistance = (currentParticle->getDepth()>=0.0 && currentParticle->getDepth()<=_visibilityDistance); - - if (currentParticle->isAlive() && insideDistance) - { - if (currentParticle->getShape() != startParticle->getShape()) - { - startParticle->endRender(gl); - startParticle = currentParticle; - - currentParticle->beginRender(gl); - requiresEndRender = true; - glDepthMask(GL_FALSE); - } - ++_draw_count; - - const osg::Vec3& angle = currentParticle->getAngle(); - bool requiresRotation = (angle.x()!=0.0f || angle.y()!=0.0f || angle.z()!=0.0f); - if (requiresRotation) - { - osg::Matrix R; - R.makeRotate( - angle.x(), osg::Vec3(1, 0, 0), - angle.y(), osg::Vec3(0, 1, 0), - angle.z(), osg::Vec3(0, 0, 1)); - - if (_alignment==BILLBOARD) - { - xAxis = osg::Matrix::transform3x3(R,scaled_aligned_xAxis); - xAxis = osg::Matrix::transform3x3(modelview,xAxis); - - yAxis = osg::Matrix::transform3x3(R,scaled_aligned_yAxis); - yAxis = osg::Matrix::transform3x3(modelview,yAxis); - - currentParticle->render(gl,currentParticle->getPosition(), xAxis, yAxis, scale); - } - else - { - xAxis = osg::Matrix::transform3x3(R, scaled_aligned_xAxis); - yAxis = osg::Matrix::transform3x3(R, scaled_aligned_yAxis); - - currentParticle->render(gl,currentParticle->getPosition(), xAxis, yAxis, scale); - } - } - else - { - currentParticle->render(gl,currentParticle->getPosition(), xAxis, yAxis, scale); - } - } - } - - if (requiresEndRender) - startParticle->endRender(gl); -} - -void osgParticle::ParticleSystem::render_vertex_array(osg::RenderInfo& renderInfo) const -{ - if (_particles.size() <= 0) return; - - // Compute the pointer and offsets - Particle_vector::const_iterator itr = _particles.begin(); - float* ptr = (float*)(&(*itr)); - GLsizei stride = 0; - if (_particles.size() > 1) - { - float* ptr1 = (float*)(&(*(itr+1))); - stride = ptr1 - ptr; - } - GLsizei posOffset = (float*)(&(itr->_position)) - ptr; // Position - GLsizei colorOffset = (float*)(&(itr->_current_color)) - ptr; // Color - GLsizei velOffset = (float*)(&(itr->_velocity)) - ptr; // Velocity - GLsizei propOffset = (float*)(&(itr->_alive)) - ptr; // Alive, size & alpha - - // Draw particles as arrays - osg::State& state = *renderInfo.getState(); - state.lazyDisablingOfVertexAttributes(); - state.setColorPointer(4, GL_FLOAT, stride * sizeof(float), ptr + colorOffset); - state.setVertexPointer(3, GL_FLOAT, stride * sizeof(float), ptr + posOffset); - if (_useShaders) - { - state.setNormalPointer(GL_FLOAT, stride * sizeof(float), ptr + velOffset); - state.setTexCoordPointer(0, 3, GL_FLOAT, stride * sizeof(float), ptr + propOffset); - } - state.applyDisablingOfVertexAttributes(); - glDrawArrays(GL_POINTS, 0, _particles.size()); -} - osg::BoundingBox osgParticle::ParticleSystem::computeBoundingBox() const { if (!_bounds_computed) @@ -567,35 +659,21 @@ void osgParticle::ParticleSystem::releaseGLObjects(osg::State* state) const osg::VertexArrayState* osgParticle::ParticleSystem::createVertexArrayState(osg::RenderInfo& renderInfo, bool usingVBOs) const { - OSG_NOTICE<<"osgParticle::ParticleSystem::createVertexArrayState() "<assignVertexArrayDispatcher(); - if (ad.colors.valid()) vas->assignColorArrayDispatcher(); - if (ad.texcoords.valid()) vas->assignTexCoordArrayDispatcher(1); + vas->assignVertexArrayDispatcher(); + vas->assignNormalArrayDispatcher(); + vas->assignColorArrayDispatcher(); + vas->assignTexCoordArrayDispatcher(1); if (state.useVertexArrayObject(_useVertexArrayObject)) { - OSG_NOTICE<<" Setup VertexArrayState to use VAO "<generateVertexArrayObject(); } - else - { - OSG_NOTICE<<" Setup VertexArrayState to without using VAO "<setUsage(GL_DYNAMIC_DRAW); + + vertices = new osg::Vec3Array(osg::Array::BIND_PER_VERTEX); vertices->setBufferObject(vertexBufferObject.get()); + vertices->setDataVariance(osg::Object::DYNAMIC); - colors = new osg::Vec4Array; + colors = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); colors->setBufferObject(vertexBufferObject.get()); + colors->setDataVariance(osg::Object::DYNAMIC); - texcoords = new osg::Vec2Array; - texcoords->setBufferObject(vertexBufferObject.get()); + texcoords2 = new osg::Vec2Array(osg::Array::BIND_PER_VERTEX); + texcoords2->setBufferObject(vertexBufferObject.get()); + texcoords2->setDataVariance(osg::Object::DYNAMIC); +} + +void osgParticle::ParticleSystem::ArrayData::init3() +{ + vertexBufferObject = new osg::VertexBufferObject; + vertexBufferObject->setUsage(GL_DYNAMIC_DRAW); + + vertices = new osg::Vec3Array(osg::Array::BIND_PER_VERTEX); + vertices->setBufferObject(vertexBufferObject.get()); + vertices->setDataVariance(osg::Object::DYNAMIC); + + normals = new osg::Vec3Array(osg::Array::BIND_PER_VERTEX); + normals->setBufferObject(vertexBufferObject.get()); + normals->setDataVariance(osg::Object::DYNAMIC); + + colors = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); + colors->setBufferObject(vertexBufferObject.get()); + colors->setDataVariance(osg::Object::DYNAMIC); + + texcoords3 = new osg::Vec3Array(osg::Array::BIND_PER_VERTEX); + texcoords3->setBufferObject(vertexBufferObject.get()); + texcoords3->setDataVariance(osg::Object::DYNAMIC); } void osgParticle::ParticleSystem::ArrayData::reserve(unsigned int numVertices) { - vertices->reserve(numVertices); - colors->reserve(numVertices); - texcoords->reserve(numVertices); + unsigned int vertex_size = 0; + + if (vertices.valid()) { vertices->reserve(numVertices); vertex_size += 12; } + if (normals.valid()) { normals->reserve(numVertices); vertex_size += 12; } + if (colors.valid()) { colors->reserve(numVertices); vertex_size += 16; } + if (texcoords2.valid()) { texcoords2->reserve(numVertices); vertex_size += 8; } + if (texcoords3.valid()) { texcoords3->reserve(numVertices); vertex_size += 12; } + + vertexBufferObject->getProfile()._size = numVertices * vertex_size; } void osgParticle::ParticleSystem::ArrayData::resize(unsigned int numVertices) { - vertices->resize(numVertices); - colors->resize(numVertices); - texcoords->resize(numVertices); + if (vertices.valid()) vertices->resize(numVertices); + if (normals.valid()) normals->resize(numVertices); + if (colors.valid()) colors->resize(numVertices); + if (texcoords2.valid()) texcoords2->resize(numVertices); + if (texcoords3.valid()) texcoords3->resize(numVertices); } void osgParticle::ParticleSystem::ArrayData::resizeGLObjectBuffers(unsigned int maxSize) { - OSG_NOTICE<<"osgParticle::ParticleSystem::resizeGLObjectBuffers("<resizeGLObjectBuffers(maxSize); - vertices->resizeGLObjectBuffers(maxSize); - colors->resizeGLObjectBuffers(maxSize); - texcoords->resizeGLObjectBuffers(maxSize); + if (vertexBufferObject.valid()) vertexBufferObject->resizeGLObjectBuffers(maxSize); + + if (vertices.valid()) vertices->resizeGLObjectBuffers(maxSize); + if (normals.valid()) normals->resizeGLObjectBuffers(maxSize); + if (colors.valid()) colors->resizeGLObjectBuffers(maxSize); + if (texcoords2.valid()) texcoords2->resizeGLObjectBuffers(maxSize); + if (texcoords3.valid()) texcoords3->resizeGLObjectBuffers(maxSize); } void osgParticle::ParticleSystem::ArrayData::releaseGLObjects(osg::State* state) { - OSG_NOTICE<<"osgParticle::ParticleSystem::releaseGLObjects("<releaseGLObjects(state); - vertices->releaseGLObjects(state); - colors->releaseGLObjects(state); - texcoords->releaseGLObjects(state); -} \ No newline at end of file + if (vertexBufferObject.valid()) vertexBufferObject->releaseGLObjects(state); + + if (vertices.valid()) vertices->releaseGLObjects(state); + if (normals.valid()) normals->releaseGLObjects(state); + if (colors.valid()) colors->releaseGLObjects(state); + if (texcoords2.valid()) texcoords2->releaseGLObjects(state); + if (texcoords3.valid()) texcoords3->releaseGLObjects(state); +} + +void osgParticle::ParticleSystem::ArrayData::clear() +{ + if (vertices.valid()) vertices->clear(); + if (normals.valid()) normals->clear(); + if (colors.valid()) colors->clear(); + if (texcoords2.valid()) texcoords2->clear(); + if (texcoords3.valid()) texcoords3->clear(); + primitives.clear(); +} + +void osgParticle::ParticleSystem::ArrayData::dirty() +{ + if (vertices.valid()) vertices->dirty(); + if (normals.valid()) normals->dirty(); + if (colors.valid()) colors->dirty(); + if (texcoords2.valid()) texcoords2->dirty(); + if (texcoords3.valid()) texcoords3->dirty(); +} + +void osgParticle::ParticleSystem::ArrayData::dispatchArrays(osg::State& state) +{ + osg::VertexArrayState* vas = state.getCurrentVertexArrayState(); + + vas->lazyDisablingOfVertexAttributes(); + + if (vertices.valid()) vas->setVertexArray(state, vertices.get()); + if (normals.valid()) vas->setNormalArray(state, normals.get()); + if (colors.valid()) vas->setColorArray(state, colors.get()); + if (texcoords2.valid()) vas->setTexCoordArray(state, 0, texcoords2.get()); + if (texcoords3.valid()) vas->setTexCoordArray(state, 0, texcoords3.get()); + + vas->applyDisablingOfVertexAttributes(state); +} + +void osgParticle::ParticleSystem::ArrayData::dispatchPrimitives() +{ + unsigned int base = 0; + for(ArrayData::Primitives::iterator itr = primitives.begin(); + itr != primitives.end(); + ++itr) + { + ArrayData::ModeCount& mc = *itr; + glDrawArrays(mc.first, base, mc.second); + base += mc.second; + } +} diff --git a/src/osgParticle/SmokeEffect.cpp b/src/osgParticle/SmokeEffect.cpp index f4edee973..1743f3ab8 100644 --- a/src/osgParticle/SmokeEffect.cpp +++ b/src/osgParticle/SmokeEffect.cpp @@ -132,7 +132,7 @@ void SmokeEffect::setUpEmitterAndProgram() osgParticle::RandomRateCounter* counter = dynamic_cast(_emitter->getCounter()); if (counter) { - counter->setRateRange(3*_intensity,5*_intensity); + counter->setRateRange(3.0f*_intensity,5.0f*_intensity); } osgParticle::SectorPlacer* placer = dynamic_cast(_emitter->getPlacer()); diff --git a/src/osgWrappers/serializers/osgParticle/Particle.cpp b/src/osgWrappers/serializers/osgParticle/Particle.cpp index ccbd795ad..42493997e 100644 --- a/src/osgWrappers/serializers/osgParticle/Particle.cpp +++ b/src/osgWrappers/serializers/osgParticle/Particle.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include