diff --git a/include/osgParticle/ParticleSystem b/include/osgParticle/ParticleSystem index c8b9f0837..1012e4867 100644 --- a/include/osgParticle/ParticleSystem +++ b/include/osgParticle/ParticleSystem @@ -75,6 +75,19 @@ namespace osgParticle /// Set the alignment vectors. inline void setAlignVectors(const osg::Vec3& X, const osg::Vec3& Y); + + + enum ParticleScaleReferenceFrame + { + LOCAL_COORDINATES, + WORLD_COORDINATES + }; + + void setParticleScaleReferenceFrame(ParticleScaleReferenceFrame rf) { _particleScaleReferenceFrame = rf; } + ParticleScaleReferenceFrame getParticleScaleReferenceFrame() const { return _particleScaleReferenceFrame; } + + + /// Get the default bounding box inline const osg::BoundingBox& getDefaultBoundingBox() const; @@ -188,7 +201,8 @@ namespace osgParticle Alignment _alignment; osg::Vec3 _align_X_axis; osg::Vec3 _align_Y_axis; - + ParticleScaleReferenceFrame _particleScaleReferenceFrame; + bool _doublepass; bool _frozen; diff --git a/src/osgParticle/ParticleEffect.cpp b/src/osgParticle/ParticleEffect.cpp index 93255d2ea..40d6f66f0 100644 --- a/src/osgParticle/ParticleEffect.cpp +++ b/src/osgParticle/ParticleEffect.cpp @@ -165,6 +165,8 @@ void ParticleEffect::buildEffect() if (_useLocalParticleSystem) { + particleSystem->setParticleScaleReferenceFrame(ParticleSystem::LOCAL_COORDINATES); + // add the geode to the scene graph osg::Geode* geode = new osg::Geode; geode->addDrawable(particleSystem.get()); diff --git a/src/osgParticle/ParticleSystem.cpp b/src/osgParticle/ParticleSystem.cpp index d22a144e0..ad45a2190 100644 --- a/src/osgParticle/ParticleSystem.cpp +++ b/src/osgParticle/ParticleSystem.cpp @@ -22,6 +22,7 @@ osgParticle::ParticleSystem::ParticleSystem() _alignment(BILLBOARD), _align_X_axis(1, 0, 0), _align_Y_axis(0, 1, 0), + _particleScaleReferenceFrame(WORLD_COORDINATES), _doublepass(false), _frozen(false), _bmin(0, 0, 0), @@ -45,6 +46,7 @@ osgParticle::ParticleSystem::ParticleSystem(const ParticleSystem& copy, const os _alignment(copy._alignment), _align_X_axis(copy._align_X_axis), _align_Y_axis(copy._align_Y_axis), + _particleScaleReferenceFrame(copy._particleScaleReferenceFrame), _doublepass(copy._doublepass), _frozen(copy._frozen), _bmin(copy._bmin), @@ -102,9 +104,6 @@ void osgParticle::ParticleSystem::drawImplementation(osg::RenderInfo& renderInfo // get the current modelview matrix osg::Matrix modelview = state.getModelViewMatrix(); - if (_alignment == BILLBOARD) - state.applyModelViewMatrix(0); - // set up depth mask for first rendering pass glPushAttrib(GL_DEPTH_BUFFER_BIT); glDepthMask(GL_FALSE); @@ -174,10 +173,32 @@ void osgParticle::ParticleSystem::single_pass_render(osg::State& /*state*/, con if (_particles.size() <= 0) return; float scale = sqrtf(static_cast(_detail)); - + const Particle* startParticle = &_particles[0]; startParticle->beginRender(); + osg::Vec3 xAxis = _align_X_axis; + osg::Vec3 yAxis = _align_Y_axis; + + if (_alignment==BILLBOARD) + { + xAxis = osg::Matrix::transform3x3(modelview,xAxis); + yAxis = osg::Matrix::transform3x3(modelview,yAxis); + float scaleX = xAxis.length(); + float scaleY = yAxis.length(); + + if (_particleScaleReferenceFrame==LOCAL_COORDINATES) + { + xAxis /= scaleX; + yAxis /= scaleY; + } + else + { + xAxis /= (scaleX*scaleX); + yAxis /= (scaleX*scaleY); + } + } + for(unsigned int i=0; i<_particles.size(); i+=_detail) { const Particle* currentParticle = &_particles[i]; @@ -190,16 +211,8 @@ void osgParticle::ParticleSystem::single_pass_render(osg::State& /*state*/, con startParticle = currentParticle; } ++_draw_count; - - switch (_alignment) { - case BILLBOARD: - currentParticle->render(modelview.preMult(currentParticle->getPosition()), osg::Vec3(1, 0, 0), osg::Vec3(0, 1, 0), scale); - break; - case FIXED: - currentParticle->render(currentParticle->getPosition(), _align_X_axis, _align_Y_axis, scale); - break; - default:; - } + + currentParticle->render(currentParticle->getPosition(), xAxis, yAxis, scale); } } diff --git a/src/osgPlugins/osgParticle/IO_ParticleSystem.cpp b/src/osgPlugins/osgParticle/IO_ParticleSystem.cpp index 2a6d63851..869176fcc 100644 --- a/src/osgPlugins/osgParticle/IO_ParticleSystem.cpp +++ b/src/osgPlugins/osgParticle/IO_ParticleSystem.cpp @@ -43,6 +43,19 @@ bool ParticleSystem_readLocalData(osg::Object &obj, osgDB::Input &fr) } } + if (fr[0].matchWord("particleScaleReferenceFrame")) { + if (fr[1].matchWord("LOCAL_COORDINATES")) { + myobj.setParticleScaleReferenceFrame(osgParticle::ParticleSystem::LOCAL_COORDINATES); + fr += 2; + itAdvanced = true; + } + if (fr[1].matchWord("")) { + myobj.setParticleScaleReferenceFrame(osgParticle::ParticleSystem::WORLD_COORDINATES); + fr += 2; + itAdvanced = true; + } + } + if (fr[0].matchWord("alignVectorX")) { osg::Vec3 v; if (fr[1].getFloat(v.x()) && fr[2].getFloat(v.y()) && fr[3].getFloat(v.z())) { @@ -138,6 +151,17 @@ bool ParticleSystem_writeLocalData(const osg::Object &obj, osgDB::Output &fw) break; } + fw.indent() << "particleScaleReferenceFrame "; + switch (myobj.getParticleScaleReferenceFrame()) { + default: + case osgParticle::ParticleSystem::LOCAL_COORDINATES: + fw << "LOCAL_COORDINATES" << std::endl; + break; + case osgParticle::ParticleSystem::WORLD_COORDINATES: + fw << "WORLD_COORDINATES" << std::endl; + break; + } + osg::Vec3 v = myobj.getAlignVectorX(); fw.indent() << "alignVectorX " << v.x() << " " << v.y() << " " << v.z() << std::endl; v = myobj.getAlignVectorY();