#include #include #include #include osgParticle::ModularEmitter::ModularEmitter() : Emitter(), _numParticleToCreateMovementCompensationRatio(0.0f), _counter(new RandomRateCounter), _placer(new PointPlacer), _shooter(new RadialShooter) { } osgParticle::ModularEmitter::ModularEmitter(const ModularEmitter& copy, const osg::CopyOp& copyop): Emitter(copy, copyop), _numParticleToCreateMovementCompensationRatio(copy._numParticleToCreateMovementCompensationRatio), _counter(static_cast(copyop(copy._counter.get()))), _placer(static_cast(copyop(copy._placer.get()))), _shooter(static_cast(copyop(copy._shooter.get()))) { } 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::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 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)); } for (int i=0; icreateParticle(getUseDefaultTemplate()? 0: &getParticleTemplate()); if (P) { _placer->place(P); _shooter->shoot(P); // Now need to transform the position and velocity because we having a moving model. float r = ((float)rand()/(float)RAND_MAX); P->transformPositionVelocity(emitterToPs, prevEmitterToPs, r); //P->transformPositionVelocity(ltw); if (cps) P->setUpTexCoordsAsPartOfConnectedParticleSystem(cps); } else { osg::notify(osg::NOTICE)<<"run out of particle"<numParticlesToCreate(dt); for (int i=0; icreateParticle(getUseDefaultTemplate()? 0: &getParticleTemplate()); 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); } } } }