From 0d74d508dfd6b4fb8d44096168d907bc570d538b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 18 Sep 2008 10:39:37 +0000 Subject: [PATCH] From Tim Moore, "his submission fixes a bug when the ModularEmitter and ParticleSystem are in different frames of reference. Specifically, it supports the case where the ParticleSystem is not in the world frame. One way this can come up is if your world coordinate system is Earth-centric; the float coordinates of particles don't have enough precision to avoid terrible jitter and other rendering artifacts, so it's convenient to root the particle systems in a local Z-up coordinate system that gets moved around from time to time. " Tweak from Robert Osfield, converted code to use new Drawable::getWorldMatrices method --- src/osgParticle/ModularEmitter.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/osgParticle/ModularEmitter.cpp b/src/osgParticle/ModularEmitter.cpp index 0b6d9b8f0..12b2f2b18 100644 --- a/src/osgParticle/ModularEmitter.cpp +++ b/src/osgParticle/ModularEmitter.cpp @@ -25,19 +25,30 @@ void osgParticle::ModularEmitter::emit(double dt) { ConnectedParticleSystem* cps = dynamic_cast(getParticleSystem()); + osg::Matrix worldToPs; + osg::MatrixList worldMats = getParticleSystem()->getWorldMatrices(); + if (!worldMats.empty()) + { + const osg::Matrix psToWorld = worldMats[0]; + worldToPs = osg::Matrix::inverse(psToWorld); + } + if (getReferenceFrame() == RELATIVE_RF) { const osg::Matrix& ltw = getLocalToWorldMatrix(); const osg::Matrix& previous_ltw = getPreviousLocalToWorldMatrix(); + const osg::Matrix emitterToPs = ltw * worldToPs; + const osg::Matrix prevEmitterToPs = previous_ltw * worldToPs; int n = _counter->numParticlesToCreate(dt); if (_numParticleToCreateMovementCompensationRatio>0.0f) { // compute the distance moved between frames - const osg::Vec3 controlPosition = _placer->getControlPosition(); - osg::Vec3 previousPosition = controlPosition * previous_ltw; - osg::Vec3 currentPosition = controlPosition * ltw; + 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() ? @@ -59,9 +70,9 @@ void osgParticle::ModularEmitter::emit(double dt) _placer->place(P); _shooter->shoot(P); - // now need to transform the position and velocity because we having a moving model. + // Now need to transform the position and velocity because we having a moving model. float r = ((float)rand()/(float)RAND_MAX); - P->transformPositionVelocity(ltw, previous_ltw, r); + P->transformPositionVelocity(emitterToPs, prevEmitterToPs, r); //P->transformPositionVelocity(ltw); if (cps) P->setUpTexCoordsAsPartOfConnectedParticleSystem(cps); @@ -82,7 +93,10 @@ void osgParticle::ModularEmitter::emit(double dt) if (P) { _placer->place(P); + P->setPosition(P->getPosition() * worldToPs); _shooter->shoot(P); + P->setVelocity(osg::Matrix::transform3x3(P->getVelocity(), + worldToPs)); if (cps) P->setUpTexCoordsAsPartOfConnectedParticleSystem(cps); }