Refactored osgParticle so that it natives support vertex arrays, vertex buffer objects and vertex array objects
This commit is contained in:
parent
cd3a5f8097
commit
5a4754deef
@ -63,6 +63,15 @@ namespace osgParticle
|
||||
return osg::maximum(_minimumNumberOfParticlesToCreate, i);
|
||||
}
|
||||
|
||||
|
||||
virtual int getEstimatedMaxNumOfParticles(double lifeTime) const
|
||||
{
|
||||
int minNumParticles = static_cast<int>(_minimumNumberOfParticlesToCreate*60.0f*lifeTime);
|
||||
int baseNumPartciles = static_cast<int>(_numberOfParticlesPerSecondToCreate * lifeTime);
|
||||
return osg::maximum(minNumParticles, baseNumPartciles);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual ~ConstantRateCounter() {}
|
||||
|
||||
|
@ -30,8 +30,12 @@ namespace osgParticle
|
||||
virtual const char* className() const { return "Counter"; }
|
||||
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const Counter* >(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; }
|
||||
|
@ -42,6 +42,12 @@ namespace osgParticle
|
||||
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const Emitter*>(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
|
||||
|
@ -23,9 +23,6 @@
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Drawable>
|
||||
#include <osg/GL>
|
||||
#include <osg/GLBeginEndAdapter>
|
||||
|
||||
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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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> Particle_vector;
|
||||
typedef std::stack<Particle*> 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<osg::BufferObject> vertexBufferObject;
|
||||
osg::ref_ptr<osg::Vec3Array> vertices;
|
||||
osg::ref_ptr<osg::Vec3Array> normals;
|
||||
osg::ref_ptr<osg::Vec4Array> colors;
|
||||
osg::ref_ptr<osg::Vec2Array> texcoords;
|
||||
osg::ref_ptr<osg::Vec2Array> texcoords2;
|
||||
osg::ref_ptr<osg::Vec3Array> texcoords3;
|
||||
|
||||
typedef std::pair<GLenum, unsigned int> ModeCount;
|
||||
typedef std::vector<ModeCount> Primitives;
|
||||
Primitives primitives;
|
||||
};
|
||||
|
||||
typedef osg::buffered_object< ArrayData > BufferedArrayData;
|
||||
|
@ -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<int>(_rate_range.maximum * lifeTime); }
|
||||
|
||||
protected:
|
||||
virtual ~VariableRateCounter() {}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()<duration) duration = getLifeTime();
|
||||
// duration += 5.0f/60.0f;
|
||||
|
||||
unsigned int num_before_end_of_lifetime = _counter->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<unsigned int>((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<unsigned int>( ceilf(static_cast<float>(num_before_end_of_lifetime) * esimateMaxNumScale));
|
||||
|
||||
setEstimatedMaxNumOfParticles(num_before_end_of_lifetime);
|
||||
|
||||
|
||||
// double num_per_second = (static_cast<double>(n)/dt);
|
||||
// OSG_NOTICE<<"emitParticle count="<<_counter->className()<<" ps="<<std::hex<<getParticleSystem()<<std::dec<<", n="<<n<<", num_per_second="<<num_per_second<<", num_before_end_of_lifetime="<<num_before_end_of_lifetime<<std::endl;
|
||||
// if (getEndless()) { OSG_NOTICE<<" Emitter::getLifeTime()=ENDLESS particle.getLifeTime()="<<particleTemplate.getLifeTime()<<" duration="<<duration<<std::endl; }
|
||||
// else { OSG_NOTICE<<" Emitter::getLifeTime()="<<getLifeTime()<<" particle.getLifeTime()="<<particleTemplate.getLifeTime()<<" duration="<<duration<<std::endl; }
|
||||
|
||||
for (int i=0; i<n; ++i)
|
||||
{
|
||||
Particle* P = getParticleSystem()->createParticle(getUseDefaultTemplate()? 0: &getParticleTemplate());
|
||||
Particle* P = getParticleSystem()->createParticle(&particleTemplate);
|
||||
if (P)
|
||||
{
|
||||
_placer->place(P);
|
||||
@ -87,9 +111,19 @@ void osgParticle::ModularEmitter::emitParticles(double dt)
|
||||
else
|
||||
{
|
||||
int n = _counter->numParticlesToCreate(dt);
|
||||
|
||||
num_before_end_of_lifetime = static_cast<unsigned int>( ceilf(static_cast<float>(num_before_end_of_lifetime) * esimateMaxNumScale));
|
||||
|
||||
setEstimatedMaxNumOfParticles(num_before_end_of_lifetime);
|
||||
|
||||
// double num_per_second = (static_cast<double>(n)/dt);
|
||||
// OSG_NOTICE<<"emitParticle ps="<<std::hex<<getParticleSystem()<<std::dec<<", num_per_second="<<num_per_second<<", num_before_end_of_lifetime="<<num_before_end_of_lifetime<<std::endl;
|
||||
// if (getEndless()) { OSG_NOTICE<<" Emitter::getLifeTime()=ENDLESS particle.getLifeTime()="<<particleTemplate.getLifeTime()<<" duration="<<duration<<std::endl; }
|
||||
// else { OSG_NOTICE<<" Emitter::getLifeTime()="<<getLifeTime()<<" particle.getLifeTime()="<<particleTemplate.getLifeTime()<<" duration="<<duration<<std::endl; }
|
||||
|
||||
for (int i=0; i<n; ++i)
|
||||
{
|
||||
Particle* P = getParticleSystem()->createParticle(getUseDefaultTemplate()? 0: &getParticleTemplate());
|
||||
Particle* P = getParticleSystem()->createParticle(&particleTemplate);
|
||||
if (P)
|
||||
{
|
||||
_placer->place(P);
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/GL>
|
||||
#include <osg/Notify>
|
||||
|
||||
namespace
|
||||
@ -129,57 +128,6 @@ bool osgParticle::Particle::update(double dt, bool onlyTimeStamp)
|
||||
return true;
|
||||
}
|
||||
|
||||
void osgParticle::Particle::render(osg::GLBeginEndAdapter* gl, const osg::Vec3& xpos, const osg::Vec3& px, const osg::Vec3& py, float scale) const
|
||||
{
|
||||
gl->Color4f( _current_color.x(),
|
||||
_current_color.y(),
|
||||
_current_color.z(),
|
||||
_current_color.w() * _current_alpha);
|
||||
|
||||
osg::Vec3 p1(px * _current_size * scale);
|
||||
osg::Vec3 p2(py * _current_size * scale);
|
||||
|
||||
switch (_shape)
|
||||
{
|
||||
case POINT:
|
||||
gl->Vertex3f(xpos.x(), xpos.y(), xpos.z());
|
||||
break;
|
||||
|
||||
case USER:
|
||||
case QUAD_TRIANGLESTRIP:
|
||||
case HEXAGON:
|
||||
case QUAD:
|
||||
gl->TexCoord2f(_s_coord, _t_coord);
|
||||
gl->Vertex3fv((xpos-(p1+p2)).ptr());
|
||||
gl->TexCoord2f(_s_coord+_s_tile, _t_coord);
|
||||
gl->Vertex3fv((xpos+(p1-p2)).ptr());
|
||||
gl->TexCoord2f(_s_coord+_s_tile, _t_coord+_t_tile);
|
||||
gl->Vertex3fv((xpos+(p1+p2)).ptr());
|
||||
gl->TexCoord2f(_s_coord, _t_coord+_t_tile);
|
||||
gl->Vertex3fv((xpos-(p1-p2)).ptr());
|
||||
break;
|
||||
|
||||
case LINE:
|
||||
{
|
||||
// Get the normalized direction of the particle, to be used in the
|
||||
// calculation of one of the linesegment endpoints.
|
||||
float vl = _velocity.length();
|
||||
if (vl != 0) {
|
||||
osg::Vec3 v = _velocity * _current_size * scale / vl;
|
||||
|
||||
gl->TexCoord1f(0);
|
||||
gl->Vertex3f(xpos.x(), xpos.y(), xpos.z());
|
||||
gl->TexCoord1f(1);
|
||||
gl->Vertex3f(xpos.x() + v.x(), xpos.y() + v.y(), xpos.z() + v.z());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
OSG_WARN << "Invalid shape for particles\n";
|
||||
}
|
||||
}
|
||||
|
||||
void osgParticle::Particle::setUpTexCoordsAsPartOfConnectedParticleSystem(ParticleSystem* ps)
|
||||
{
|
||||
if (getPreviousParticle()!=Particle::INVALID_INDEX)
|
||||
|
@ -52,6 +52,11 @@ osgParticle::ParticleProcessor::ParticleProcessor(const ParticleProcessor& copy,
|
||||
{
|
||||
}
|
||||
|
||||
void osgParticle::ParticleProcessor::setParticleSystem(ParticleSystem* ps)
|
||||
{
|
||||
_ps = ps;
|
||||
}
|
||||
|
||||
void osgParticle::ParticleProcessor::traverse(osg::NodeVisitor& nv)
|
||||
{
|
||||
// typecast the NodeVisitor to CullVisitor
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
#include <osgUtil/CullVisitor>
|
||||
|
||||
#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() "<<std::dec<<this<<std::dec<<" _particles.size()="<<_particles.size()<<", _particles.capacity()="<<_particles.capacity()<<" _estimatedMaxNumOfParticles="<<_estimatedMaxNumOfParticles<<std::endl;
|
||||
}
|
||||
|
||||
osgParticle::Particle* osgParticle::ParticleSystem::createParticle(const osgParticle::Particle* ptemplate)
|
||||
{
|
||||
// is there any dead particle?
|
||||
if (!_deadparts.empty()) {
|
||||
if (!_deadparts.empty())
|
||||
{
|
||||
|
||||
// retrieve a pointer to the last dead particle
|
||||
Particle* P = _deadparts.top();
|
||||
@ -109,7 +112,17 @@ osgParticle::Particle* osgParticle::ParticleSystem::createParticle(const osgPart
|
||||
_deadparts.pop();
|
||||
return P;
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (_particles.size()==_particles.capacity())
|
||||
{
|
||||
if (_estimatedMaxNumOfParticles > static_cast<int>(_particles.capacity()))
|
||||
{
|
||||
_particles.reserve(_estimatedMaxNumOfParticles);
|
||||
}
|
||||
}
|
||||
|
||||
// add a new particle to the vector
|
||||
_particles.push_back(ptemplate? *ptemplate: _def_ptemp);
|
||||
@ -198,10 +211,12 @@ void osgParticle::ParticleSystem::update(double dt, osg::NodeVisitor& nv)
|
||||
|
||||
void osgParticle::ParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) const
|
||||
{
|
||||
osg::State& state = *renderInfo.getState();
|
||||
if (_particles.size() <= 0) return;
|
||||
|
||||
ScopedReadLock lock(_readWriteMutex);
|
||||
|
||||
osg::State& state = *renderInfo.getState();
|
||||
|
||||
// update the frame count, so other objects can detect when
|
||||
// this particle system is culled
|
||||
_last_frame = state.getFrameStamp()->getFrameNumber();
|
||||
@ -213,6 +228,237 @@ void osgParticle::ParticleSystem::drawImplementation(osg::RenderInfo& renderInfo
|
||||
// get the current modelview matrix
|
||||
osg::Matrix modelview = state.getModelViewMatrix();
|
||||
|
||||
ArrayData& ad = _bufferedArrayData[state.getContextID()];
|
||||
|
||||
if (_useVertexArray)
|
||||
{
|
||||
// note from Robert Osfield, September 2016, this block implementated for backwards compatibility but is pretty way vertex array/shaders were hacked into osgParticle
|
||||
|
||||
// set up arrays and primitives ready to fill in
|
||||
if (!ad.vertices.valid())
|
||||
{
|
||||
ad.init3();
|
||||
ad.reserve(_particles.capacity());
|
||||
}
|
||||
|
||||
ad.clear();
|
||||
ad.dirty();
|
||||
|
||||
osg::Vec3Array& vertices = *ad.vertices;
|
||||
osg::Vec3Array& normals = *ad.normals;
|
||||
osg::Vec4Array& colors = *ad.colors;
|
||||
osg::Vec3Array& texcoords = *ad.texcoords3;
|
||||
ArrayData::Primitives& primitives = ad.primitives;
|
||||
|
||||
for(unsigned int i=0; i<_particles.size(); i+=_detail)
|
||||
{
|
||||
const Particle* particle = &_particles[i];
|
||||
const osg::Vec4& color = particle->getCurrentColor();
|
||||
const osg::Vec3& pos = particle->getPosition();
|
||||
const osg::Vec3& vel = particle->getVelocity();
|
||||
colors.push_back( color );
|
||||
texcoords.push_back( osg::Vec3(particle->_alive, particle->_current_size, particle->_current_alpha) );
|
||||
normals.push_back(vel);
|
||||
vertices.push_back(pos);
|
||||
}
|
||||
|
||||
primitives.push_back(ArrayData::ModeCount(GL_POINTS, vertices.size()));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// set up arrays and primitives ready to fill in
|
||||
if (!ad.vertices.valid())
|
||||
{
|
||||
ad.init();
|
||||
ad.reserve(_particles.capacity()*4);
|
||||
}
|
||||
|
||||
ad.clear();
|
||||
ad.dirty();
|
||||
|
||||
osg::Vec3Array& vertices = *ad.vertices;
|
||||
osg::Vec4Array& colors = *ad.colors;
|
||||
osg::Vec2Array& texcoords = *ad.texcoords2;
|
||||
ArrayData::Primitives& primitives = ad.primitives;
|
||||
|
||||
float scale = sqrtf(static_cast<float>(_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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
xAxis = osg::Matrix::transform3x3(R, scaled_aligned_xAxis);
|
||||
yAxis = osg::Matrix::transform3x3(R, scaled_aligned_yAxis);
|
||||
}
|
||||
}
|
||||
|
||||
osg::Vec4 color = currentParticle->getCurrentColor();
|
||||
color.a() *= currentParticle->getCurrentAlpha();
|
||||
|
||||
float currentSize = currentParticle->getCurrentSize();
|
||||
|
||||
const osg::Vec3& xpos = currentParticle->getPosition();
|
||||
const float s_coord = currentParticle->getSTexCoord();
|
||||
const float t_coord = currentParticle->getTTexCoord();
|
||||
const float s_tile = currentParticle->getSTexTile();
|
||||
const float t_tile = currentParticle->getTTexTile();
|
||||
|
||||
osg::Vec3 p1(xAxis * currentSize * scale);
|
||||
osg::Vec3 p2(yAxis * currentSize * scale);
|
||||
|
||||
switch (currentParticle->getShape())
|
||||
{
|
||||
case osgParticle::Particle::POINT:
|
||||
{
|
||||
vertices.push_back(currentParticle->getPosition());
|
||||
colors.push_back(color);
|
||||
texcoords.push_back(osg::Vec2(0.5f,0.5f));
|
||||
|
||||
if (!primitives.empty() && primitives.back().first==GL_POINTS)
|
||||
{
|
||||
primitives.back().second++;
|
||||
}
|
||||
else
|
||||
{
|
||||
primitives.push_back(ArrayData::ModeCount(GL_POINTS,1));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case osgParticle::Particle::USER:
|
||||
case osgParticle::Particle::QUAD_TRIANGLESTRIP:
|
||||
case osgParticle::Particle::HEXAGON:
|
||||
case osgParticle::Particle::QUAD:
|
||||
{
|
||||
vertices.push_back(xpos-p1-p2);
|
||||
colors.push_back(color);
|
||||
texcoords.push_back(osg::Vec2(s_coord, t_coord));
|
||||
|
||||
vertices.push_back(xpos+p1-p2);
|
||||
colors.push_back(color);
|
||||
texcoords.push_back(osg::Vec2(s_coord+s_tile, t_coord));
|
||||
|
||||
vertices.push_back(xpos+p1+p2);
|
||||
colors.push_back(color);
|
||||
texcoords.push_back(osg::Vec2(s_coord+s_tile, t_coord+t_tile));
|
||||
|
||||
vertices.push_back(xpos-p1+p2);
|
||||
colors.push_back(color);
|
||||
texcoords.push_back(osg::Vec2(s_coord, t_coord+t_tile));
|
||||
|
||||
if (!primitives.empty() && primitives.back().first==GL_QUADS)
|
||||
{
|
||||
primitives.back().second+=4;
|
||||
}
|
||||
else
|
||||
{
|
||||
primitives.push_back(ArrayData::ModeCount(GL_QUADS,4));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case osgParticle::Particle::LINE:
|
||||
{
|
||||
// Get the normalized direction of the particle, to be used in the
|
||||
// calculation of one of the linesegment endpoints.
|
||||
const osg::Vec3& velocity = currentParticle->getVelocity();
|
||||
float vl = velocity.length();
|
||||
if (vl != 0)
|
||||
{
|
||||
osg::Vec3 v = velocity * currentSize * scale / vl;
|
||||
|
||||
vertices.push_back(currentParticle->getPosition());
|
||||
colors.push_back(color);
|
||||
texcoords.push_back(osg::Vec2(0.0f,0.0f));
|
||||
|
||||
vertices.push_back(currentParticle->getPosition()+v);
|
||||
colors.push_back(color);
|
||||
texcoords.push_back(osg::Vec2(1.0f,1.0f));
|
||||
|
||||
if (!primitives.empty() && primitives.back().first==GL_LINES)
|
||||
{
|
||||
primitives.back().second+=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
primitives.push_back(ArrayData::ModeCount(GL_LINES,2));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
OSG_WARN << "Invalid shape for particles\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// set up depth mask for first rendering pass
|
||||
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
|
||||
glPushAttrib(GL_DEPTH_BUFFER_BIT);
|
||||
@ -220,11 +466,8 @@ void osgParticle::ParticleSystem::drawImplementation(osg::RenderInfo& renderInfo
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
// render, first pass
|
||||
if (_useVertexArray)
|
||||
render_vertex_array(renderInfo);
|
||||
else
|
||||
single_pass_render(renderInfo, modelview);
|
||||
ad.dispatchArrays(state);
|
||||
ad.dispatchPrimitives();
|
||||
|
||||
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
|
||||
// restore depth mask settings
|
||||
@ -232,29 +475,21 @@ void osgParticle::ParticleSystem::drawImplementation(osg::RenderInfo& renderInfo
|
||||
#endif
|
||||
|
||||
// render, second pass
|
||||
if (_doublepass) {
|
||||
if (_doublepass)
|
||||
{
|
||||
// set up color mask for second rendering pass
|
||||
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
|
||||
glPushAttrib(GL_COLOR_BUFFER_BIT);
|
||||
#endif
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
|
||||
// render the particles onto the depth buffer
|
||||
if (_useVertexArray)
|
||||
render_vertex_array(renderInfo);
|
||||
else
|
||||
single_pass_render(renderInfo, modelview);
|
||||
ad.dispatchPrimitives();
|
||||
|
||||
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
|
||||
// restore color mask settings
|
||||
glPopAttrib();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
|
||||
OSG_NOTICE<<"Warning: ParticleSystem::drawImplementation(..) not fully implemented."<<std::endl;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void osgParticle::ParticleSystem::setDefaultAttributes(const std::string& texturefile, bool emissive_particles, bool lighting, int texture_unit)
|
||||
@ -386,149 +621,6 @@ void osgParticle::ParticleSystem::setDefaultAttributesUsingShaders(const std::st
|
||||
setUseShaders(true);
|
||||
}
|
||||
|
||||
|
||||
void osgParticle::ParticleSystem::single_pass_render(osg::RenderInfo& renderInfo, const osg::Matrix& modelview) const
|
||||
{
|
||||
_draw_count = 0;
|
||||
if (_particles.size() <= 0) return;
|
||||
|
||||
osg::GLBeginEndAdapter* gl = &(renderInfo.getState()->getGLBeginEndAdapter());
|
||||
|
||||
float scale = sqrtf(static_cast<float>(_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() "<<this<<std::endl;
|
||||
#if 0
|
||||
return osg::Drawable::createVertexArrayState(renderInfo, usingVBOs);
|
||||
#else
|
||||
osg::State& state = *renderInfo.getState();
|
||||
|
||||
ArrayData& ad = _bufferedArrayData[state.getContextID()];
|
||||
|
||||
osg::VertexArrayState* vas = new osg::VertexArrayState(&state);
|
||||
|
||||
OSG_NOTICE<<" Creating new osg::VertexArrayState "<< vas<<std::endl;
|
||||
|
||||
if (ad.vertices.valid()) vas->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 "<<vas<<std::endl;
|
||||
|
||||
vas->generateVertexArrayObject();
|
||||
}
|
||||
else
|
||||
{
|
||||
OSG_NOTICE<<" Setup VertexArrayState to without using VAO "<<vas<<std::endl;
|
||||
}
|
||||
|
||||
return vas;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -605,48 +683,139 @@ osg::VertexArrayState* osgParticle::ParticleSystem::createVertexArrayState(osg::
|
||||
//
|
||||
osgParticle::ParticleSystem::ArrayData::ArrayData()
|
||||
{
|
||||
OSG_NOTICE<<"osgParticle::ParticleSystem::ArrayData() "<<this<<std::endl;
|
||||
}
|
||||
|
||||
void osgParticle::ParticleSystem::ArrayData::init()
|
||||
{
|
||||
vertexBufferObject = new osg::VertexBufferObject;
|
||||
vertices = new osg::Vec3Array;
|
||||
vertexBufferObject->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("<<maxSize<<") "<<this<<std::endl;
|
||||
// OSG_NOTICE<<"osgParticle::ParticleSystem::resizeGLObjectBuffers("<<maxSize<<") "<<this<<std::endl;
|
||||
|
||||
vertexBufferObject->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("<<state<<") "<<this<<std::endl;
|
||||
// OSG_NOTICE<<"osgParticle::ParticleSystem::releaseGLObjects("<<state<<") "<<this<<std::endl;
|
||||
|
||||
vertexBufferObject->releaseGLObjects(state);
|
||||
vertices->releaseGLObjects(state);
|
||||
colors->releaseGLObjects(state);
|
||||
texcoords->releaseGLObjects(state);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ void SmokeEffect::setUpEmitterAndProgram()
|
||||
osgParticle::RandomRateCounter* counter = dynamic_cast<osgParticle::RandomRateCounter*>(_emitter->getCounter());
|
||||
if (counter)
|
||||
{
|
||||
counter->setRateRange(3*_intensity,5*_intensity);
|
||||
counter->setRateRange(3.0f*_intensity,5.0f*_intensity);
|
||||
}
|
||||
|
||||
osgParticle::SectorPlacer* placer = dynamic_cast<osgParticle::SectorPlacer*>(_emitter->getPlacer());
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <osgParticle/Particle>
|
||||
#include <osg/Drawable>
|
||||
#include <osgDB/ObjectWrapper>
|
||||
#include <osgDB/InputStream>
|
||||
#include <osgDB/OutputStream>
|
||||
|
Loading…
Reference in New Issue
Block a user