Introduce osgParticle::ParticleSystem::s/getParticleScaleReferenceFrame() to

help manage the scaling of particles, whether they should be relative to the
local coordiante frame of the particle system, or be in world coordinates.
This commit is contained in:
Robert Osfield 2008-03-17 12:09:05 +00:00
parent 7ec5673a7e
commit 00f161ca35
4 changed files with 68 additions and 15 deletions

View File

@ -75,6 +75,19 @@ namespace osgParticle
/// Set the alignment vectors. /// Set the alignment vectors.
inline void setAlignVectors(const osg::Vec3& X, const osg::Vec3& Y); 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 /// Get the default bounding box
inline const osg::BoundingBox& getDefaultBoundingBox() const; inline const osg::BoundingBox& getDefaultBoundingBox() const;
@ -188,7 +201,8 @@ namespace osgParticle
Alignment _alignment; Alignment _alignment;
osg::Vec3 _align_X_axis; osg::Vec3 _align_X_axis;
osg::Vec3 _align_Y_axis; osg::Vec3 _align_Y_axis;
ParticleScaleReferenceFrame _particleScaleReferenceFrame;
bool _doublepass; bool _doublepass;
bool _frozen; bool _frozen;

View File

@ -165,6 +165,8 @@ void ParticleEffect::buildEffect()
if (_useLocalParticleSystem) if (_useLocalParticleSystem)
{ {
particleSystem->setParticleScaleReferenceFrame(ParticleSystem::LOCAL_COORDINATES);
// add the geode to the scene graph // add the geode to the scene graph
osg::Geode* geode = new osg::Geode; osg::Geode* geode = new osg::Geode;
geode->addDrawable(particleSystem.get()); geode->addDrawable(particleSystem.get());

View File

@ -22,6 +22,7 @@ osgParticle::ParticleSystem::ParticleSystem()
_alignment(BILLBOARD), _alignment(BILLBOARD),
_align_X_axis(1, 0, 0), _align_X_axis(1, 0, 0),
_align_Y_axis(0, 1, 0), _align_Y_axis(0, 1, 0),
_particleScaleReferenceFrame(WORLD_COORDINATES),
_doublepass(false), _doublepass(false),
_frozen(false), _frozen(false),
_bmin(0, 0, 0), _bmin(0, 0, 0),
@ -45,6 +46,7 @@ osgParticle::ParticleSystem::ParticleSystem(const ParticleSystem& copy, const os
_alignment(copy._alignment), _alignment(copy._alignment),
_align_X_axis(copy._align_X_axis), _align_X_axis(copy._align_X_axis),
_align_Y_axis(copy._align_Y_axis), _align_Y_axis(copy._align_Y_axis),
_particleScaleReferenceFrame(copy._particleScaleReferenceFrame),
_doublepass(copy._doublepass), _doublepass(copy._doublepass),
_frozen(copy._frozen), _frozen(copy._frozen),
_bmin(copy._bmin), _bmin(copy._bmin),
@ -102,9 +104,6 @@ void osgParticle::ParticleSystem::drawImplementation(osg::RenderInfo& renderInfo
// get the current modelview matrix // get the current modelview matrix
osg::Matrix modelview = state.getModelViewMatrix(); osg::Matrix modelview = state.getModelViewMatrix();
if (_alignment == BILLBOARD)
state.applyModelViewMatrix(0);
// set up depth mask for first rendering pass // set up depth mask for first rendering pass
glPushAttrib(GL_DEPTH_BUFFER_BIT); glPushAttrib(GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
@ -174,10 +173,32 @@ void osgParticle::ParticleSystem::single_pass_render(osg::State& /*state*/, con
if (_particles.size() <= 0) return; if (_particles.size() <= 0) return;
float scale = sqrtf(static_cast<float>(_detail)); float scale = sqrtf(static_cast<float>(_detail));
const Particle* startParticle = &_particles[0]; const Particle* startParticle = &_particles[0];
startParticle->beginRender(); 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) for(unsigned int i=0; i<_particles.size(); i+=_detail)
{ {
const Particle* currentParticle = &_particles[i]; const Particle* currentParticle = &_particles[i];
@ -190,16 +211,8 @@ void osgParticle::ParticleSystem::single_pass_render(osg::State& /*state*/, con
startParticle = currentParticle; startParticle = currentParticle;
} }
++_draw_count; ++_draw_count;
switch (_alignment) { currentParticle->render(currentParticle->getPosition(), xAxis, yAxis, scale);
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:;
}
} }
} }

View File

@ -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")) { if (fr[0].matchWord("alignVectorX")) {
osg::Vec3 v; osg::Vec3 v;
if (fr[1].getFloat(v.x()) && fr[2].getFloat(v.y()) && fr[3].getFloat(v.z())) { 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; 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(); osg::Vec3 v = myobj.getAlignVectorX();
fw.indent() << "alignVectorX " << v.x() << " " << v.y() << " " << v.z() << std::endl; fw.indent() << "alignVectorX " << v.x() << " " << v.y() << " " << v.z() << std::endl;
v = myobj.getAlignVectorY(); v = myobj.getAlignVectorY();