예제 #1
0
void PUParticleSystem3D::executeEmitParticles( PUEmitter* emitter, unsigned requested, float elapsedTime )
{
    if (_state == State::STOP) return;
    if (emitter->getEmitsType() == PUParticle3D::PT_VISUAL){
        emitParticles(_particlePool, emitter, requested, elapsedTime);
    }else if (emitter->getEmitsType() == PUParticle3D::PT_EMITTER){
        emitParticles(_emittedEmitterParticlePool[emitter->getEmitsName()], emitter, requested, elapsedTime);
    }else if (emitter->getEmitsType() == PUParticle3D::PT_TECHNIQUE){
        emitParticles(_emittedSystemParticlePool[emitter->getEmitsName()], emitter, requested, elapsedTime);
    }
}
ParticleExplosionNode2::ParticleExplosionNode2(QVector3D pos,Primitive *p,std::string name)
    :SceneGraph(p,name)
{
    this->emitterPos=pos;
    nParticles=20;
    for(int i=0;i<nParticles;i++){
        Particle temp=Particle();
        particles.push_back(temp);
    }
    //erzeugt ale Partikel
    emitParticles();
    buildVertexBuffer();

    std::string fileName = ":/img/sprites/smoke.png";
    QImage tex;
    QString fileQT = QString(fileName.c_str());

    tex.load(fileQT);
    tex = QGLWidget::convertToGLFormat(tex);

    glGenTextures(1, &sprite);
    glBindTexture(GL_TEXTURE_2D, sprite);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, 0);

	glGenBuffers(1, &alphaBufferObject);
	glGenBuffers(1, &texCoordsBufferObject);
	glGenBuffers(1, &vertexBufferObject);
}
예제 #3
0
void ParticleComponent::update(sf::Time dt)
{
	if (mEmitting)
	{
		emitParticles(computeParticleCount(dt));
	}

	mNeedsVertexUpdate = true;

	for (std::size_t i = 0; i < mParticles.size();)
	{
		updateParticle(mParticles[i], dt); // lifetime, move, rotate

		if (mParticles[i].passedLifetime < mParticles[i].totalLifetime)
		{
			for (std::size_t j = 0; j < mAffectors.size(); ++j)
			{
				if (mAffectors[j])
				{
					mAffectors[j](mParticles[i], dt);
				}
			}
			++i;
		}
		else
		{
			mParticles.erase(mParticles.begin() + i);
		}
	}
}
예제 #4
0
void ParticleSystem::emitWithRate(float dt) {
	m_dt += dt;

	int maxNewParticles = 0;

	if (m_dt * emitRate > 1.0f) {
		maxNewParticles = static_cast<int>(m_dt * emitRate);
		m_dt -= maxNewParticles / emitRate;
	}

	if (maxNewParticles == 0) return;

	emitParticles(maxNewParticles);
}
예제 #5
0
void GameLayer::onCollision(CollisionManager::Type type, const Point& point) {
  switch (type) {
    case CollisionManager::Type::BALL_WITH_PADDLE_LEFT:
    case CollisionManager::Type::BALL_WITH_PADDLE_RIGHT:
      playSoundCollision();
      emitParticles(point);
      increaseVelocity();
      break;
    case CollisionManager::Type::BALL_WITH_GOAL_LEFT:
      playSoundPoint();
      scoreRight();
      restartToLeft();
      break;
    case CollisionManager::Type::BALL_WITH_GOAL_RIGHT:
      playSoundPoint();
      scoreLeft();
      restartToRight();
      break;
    default:
      playSoundCollision();
      emitParticles(point);
      break;
  }
}
예제 #6
0
void EmitterNode::updateCurrent(sf::Time dt, CommandQueue& commands) {
    if (mParticleSystem) { emitParticles(dt); }
    else {
        // Find particle node with the same type as emitter node
        auto finder = [this] (ParticleNode& container, sf::Time) {
            if (container.getParticleType() == mType)
                mParticleSystem = &container;
        };

        Command command;
        command.category = Category::ParticleSystem;
        command.action = derivedAction<ParticleNode>(finder);

        commands.push(command);
    }
}
예제 #7
0
void PUParticleSystem3D::forceUpdate( float delta )
{
    if (!_emitters.empty()){
        calulateRotationOffset();
        prepared();
        emitParticles(delta);
        preUpdator(delta);
        updator(delta);
        postUpdator(delta);
    }

    Vec3 currentPos = getDerivedPosition();
    _latestPositionDiff = currentPos - _latestPosition;
    _latestPosition = currentPos;
    _latestOrientation = getDerivedOrientation();
    _timeElapsedSinceStart += delta;
}
예제 #8
0
void CudaSystem::update()
{
    // emit particles
    emitParticles();

    reinitCells(grid);
    storeParticles(grid,m_dPos[1],particles.size());
    searchNeighbooring(m_dPos[1],m_dInteractionRadius, grid, 1, voisines, particles.size());

    // evaluate forces
    evaluateForcesExt();

    // integrate
    integrate();

    // Collision
    collide();
}
예제 #9
0
void EmitterNode::updateCurrent(sf::Time dt, CommandQueue& commands)
{
	if (particle_system)
	{
		emitParticles(dt);
	}
	else
	{
		auto finder = [this](ParticleNode& container, sf::Time)
		{
			if (container.getParticleType() == type)
				particle_system = &container;
		};

		Command command;
		command.category = Category::Particle;
		command.action = derivedAction<ParticleNode>(finder);

		commands.push(command);
	}
}
예제 #10
0
void UniversalEmitterNode::updateCurrent(sf::Time dt, CommandQueue& commands)
{
    if(mParticleSystem)
	{
	    if(mEnabled)
		{
	        if(mTimeBound)
		    {
		        mLifetime += dt;
			
			    if(mLifetime > mTotalLife)
			    {
			        mEnabled = false;
			    	return;
			    }
		    }
	        emitParticles(dt);
		}
	}
	else
	{
	    // Find particle node with the same type as emitter node
		auto finder = [this] (ParticleNode& container, sf::Time)
		{
		    if(container.getParticleType() == mType)
			{
			    mParticleSystem = &container;
			}
		};
		
		Command command;
		command.category = Category::ParticleSystem;
		command.action = derivedAction<ParticleNode>(finder);
		
		commands.push(command);
	}
}
예제 #11
0
void Projectile::simulate( F32 dt )
{         
   if ( isServerObject() && mCurrTick >= mDataBlock->lifetime )
   {
      deleteObject();
      return;
   }
   
   if ( mHasExploded )
      return;

   // ... otherwise, we have to do some simulation work.
   RayInfo rInfo;
   Point3F oldPosition;
   Point3F newPosition;

   oldPosition = mCurrPosition;
   if ( mDataBlock->isBallistic )
      mCurrVelocity.z -= 9.81 * mDataBlock->gravityMod * dt;

   newPosition = oldPosition + mCurrVelocity * dt;

   // disable the source objects collision reponse for a short time while we
   // determine if the projectile is capable of moving from the old position
   // to the new position, otherwise we'll hit ourself
   bool disableSourceObjCollision = (mSourceObject.isValid() && mCurrTick <= SourceIdTimeoutTicks);
   if ( disableSourceObjCollision )
      mSourceObject->disableCollision();
   disableCollision();

   // Determine if the projectile is going to hit any object between the previous
   // position and the new position. This code is executed both on the server
   // and on the client (for prediction purposes). It is possible that the server
   // will have registered a collision while the client prediction has not. If this
   // happens the client will be corrected in the next packet update.

   // Raycast the abstract PhysicsWorld if a PhysicsPlugin exists.
   bool hit = false;

   if ( mPhysicsWorld )
      hit = mPhysicsWorld->castRay( oldPosition, newPosition, &rInfo, Point3F( newPosition - oldPosition) * mDataBlock->impactForce );            
   else 
      hit = getContainer()->castRay(oldPosition, newPosition, csmDynamicCollisionMask | csmStaticCollisionMask, &rInfo);

   if ( hit )
   {
      // make sure the client knows to bounce
      if ( isServerObject() && ( rInfo.object->getTypeMask() & csmStaticCollisionMask ) == 0 )
         setMaskBits( BounceMask );

      MatrixF xform( true );
      xform.setColumn( 3, rInfo.point );
      setTransform( xform );
      mCurrPosition    = rInfo.point;

      // Get the object type before the onCollision call, in case
      // the object is destroyed.
      U32 objectType = rInfo.object->getTypeMask();

      // re-enable the collision response on the source object since
      // we need to process the onCollision and explode calls
      if ( disableSourceObjCollision )
         mSourceObject->enableCollision();

      // Ok, here is how this works:
      // onCollision is called to notify the server scripts that a collision has occurred, then
      // a call to explode is made to start the explosion process. The call to explode is made
      // twice, once on the server and once on the client.
      // The server process is responsible for two things:
      //    1) setting the ExplosionMask network bit to guarantee that the client calls explode
      //    2) initiate the explosion process on the server scripts
      // The client process is responsible for only one thing:
      //    1) drawing the appropriate explosion

      // It is possible that during the processTick the server may have decided that a hit
      // has occurred while the client prediction has decided that a hit has not occurred.
      // In this particular scenario the client will have failed to call onCollision and
      // explode during the processTick. However, the explode function will be called
      // during the next packet update, due to the ExplosionMask network bit being set.
      // onCollision will remain uncalled on the client however, therefore no client
      // specific code should be placed inside the function!
      onCollision( rInfo.point, rInfo.normal, rInfo.object );
      // Next order of business: do we explode on this hit?
      if ( mCurrTick > mDataBlock->armingDelay || mDataBlock->armingDelay == 0 )
      {
         mCurrVelocity    = Point3F::Zero;
         explode( rInfo.point, rInfo.normal, objectType );
      }

      if ( mDataBlock->isBallistic )
      {
         // Otherwise, this represents a bounce.  First, reflect our velocity
         //  around the normal...
         Point3F bounceVel = mCurrVelocity - rInfo.normal * (mDot( mCurrVelocity, rInfo.normal ) * 2.0);
         mCurrVelocity = bounceVel;

         // Add in surface friction...
         Point3F tangent = bounceVel - rInfo.normal * mDot(bounceVel, rInfo.normal);
         mCurrVelocity  -= tangent * mDataBlock->bounceFriction;

         // Now, take elasticity into account for modulating the speed of the grenade
         mCurrVelocity *= mDataBlock->bounceElasticity;

         // Set the new position to the impact and the bounce
         // will apply on the next frame.
         //F32 timeLeft = 1.0f - rInfo.t;
         newPosition = oldPosition = rInfo.point + rInfo.normal * 0.05f;
      }
      else
      {
         mCurrVelocity    = Point3F::Zero;
      }
   }

   // re-enable the collision response on the source object now
   // that we are done processing the ballistic movement
   if ( disableSourceObjCollision )
      mSourceObject->enableCollision();
   enableCollision();

   if ( isClientObject() )
   {
      emitParticles( mCurrPosition, newPosition, mCurrVelocity, U32( dt * 1000.0f ) );
      updateSound();
   }

   mCurrDeltaBase = newPosition;
   mCurrBackDelta = mCurrPosition - newPosition;
   mCurrPosition = newPosition;

   MatrixF xform( true );
   xform.setColumn( 3, mCurrPosition );
   setTransform( xform );
}
void QQuickTrailEmitter::emitWindow(int timeStamp)
{
    if (m_system == 0)
        return;
    if (!m_enabled && !m_pulseLeft && m_burstQueue.isEmpty())
        return;
    if (m_followCount != m_system->groupData[m_system->groupIds[m_follow]]->size()){
        qreal oldPPS = m_particlesPerSecond;
        recalcParticlesPerSecond();
        if (m_particlesPerSecond != oldPPS)
            return;//system may need to update
    }

    if (m_pulseLeft){
        m_pulseLeft -= timeStamp - m_lastTimeStamp * 1000.;
        if (m_pulseLeft < 0){
            timeStamp += m_pulseLeft;
            m_pulseLeft = 0;
        }
    }

    //TODO: Implement startTime and velocityFromMovement
    qreal time = timeStamp / 1000.;
    qreal particleRatio = 1. / m_particlesPerParticlePerSecond;
    qreal pt;
    qreal maxLife = (m_particleDuration + m_particleDurationVariation)/1000.0;

    //Have to map it into this system, because particlesystem automaps it back
    QPointF offset = m_system->mapFromItem(this, QPointF(0, 0));
    qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;

    int gId = m_system->groupIds[m_follow];
    int gId2 = m_system->groupIds[m_group];
    for (int i=0; i<m_system->groupData[gId]->data.count(); i++) {
        QQuickParticleData *d = m_system->groupData[gId]->data[i];
        if (!d->stillAlive()){
            m_lastEmission[i] = time; //Should only start emitting when it returns to life
            continue;
        }
        pt = m_lastEmission[i];
        if (pt < d->t)
            pt = d->t;
        if (pt + maxLife < time)//We missed so much, that we should skip emiting particles that are dead by now
            pt = time - maxLife;

        if ((width() || height()) && !effectiveExtruder()->contains(QRectF(offset.x(), offset.y(), width(), height()),QPointF(d->curX(), d->curY()))){
            m_lastEmission[d->index] = time;//jump over this time period without emitting, because it's outside
            continue;
        }

        QList<QQuickParticleData*> toEmit;

        while (pt < time || !m_burstQueue.isEmpty()){
            QQuickParticleData* datum = m_system->newDatum(gId2, !m_overwrite);
            if (datum){//else, skip this emission
                datum->e = this;//###useful?

                // Particle timestamp
                datum->t = pt;
                datum->lifeSpan =
                        (m_particleDuration
                         + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
                        / 1000.0;

                // Particle position
                // Note that burst location doesn't get used for follow emitter
                qreal followT =  pt - d->t;
                qreal followT2 = followT * followT * 0.5;
                qreal eW = m_emitterXVariation < 0 ? d->curSize() : m_emitterXVariation;
                qreal eH = m_emitterYVariation < 0 ? d->curSize() : m_emitterYVariation;
                //Subtract offset, because PS expects this in emitter coordinates
                QRectF boundsRect(d->x - offset.x() + d->vx * followT + d->ax * followT2 - eW/2,
                                  d->y - offset.y() + d->vy * followT + d->ay * followT2 - eH/2,
                                  eW, eH);

                QQuickParticleExtruder* effectiveEmissionExtruder = m_emissionExtruder ? m_emissionExtruder : m_defaultEmissionExtruder;
                const QPointF &newPos = effectiveEmissionExtruder->extrude(boundsRect);
                datum->x = newPos.x();
                datum->y = newPos.y();

                // Particle velocity
                const QPointF &velocity = m_velocity->sample(newPos);
                datum->vx = velocity.x()
                    + m_velocity_from_movement * d->vx;
                datum->vy = velocity.y()
                    + m_velocity_from_movement * d->vy;

                // Particle acceleration
                const QPointF &accel = m_acceleration->sample(newPos);
                datum->ax = accel.x();
                datum->ay = accel.y();

                // Particle size
                float sizeVariation = -m_particleSizeVariation
                        + rand() / float(RAND_MAX) * m_particleSizeVariation * 2;

                float size = qMax((qreal)0.0, m_particleSize + sizeVariation);
                float endSize = qMax((qreal)0.0, sizeAtEnd + sizeVariation);

                datum->size = size * float(m_enabled);
                datum->endSize = endSize * float(m_enabled);

                toEmit << datum;

                m_system->emitParticle(datum);
            }
            if (!m_burstQueue.isEmpty()){
                m_burstQueue.first().first--;
                if (m_burstQueue.first().first <= 0)
                    m_burstQueue.pop_front();
            }else{
                pt += particleRatio;
            }
        }

        foreach (QQuickParticleData* d, toEmit)
            m_system->emitParticle(d);

        if (isEmitConnected() || isEmitFollowConnected()) {
            v8::HandleScope handle_scope;
            v8::Context::Scope scope(QQmlEnginePrivate::getV8Engine(qmlEngine(this))->context());
            v8::Handle<v8::Array> array = v8::Array::New(toEmit.size());
            for (int i=0; i<toEmit.size(); i++)
                array->Set(i, toEmit[i]->v8Value().toHandle());

            if (isEmitFollowConnected())
                emitFollowParticles(QQmlV8Handle::fromHandle(array), d->v8Value());//A chance for many arbitrary JS changes
            else if (isEmitConnected())
                emitParticles(QQmlV8Handle::fromHandle(array));//A chance for arbitrary JS changes
        }
        m_lastEmission[d->index] = pt;
    }

    m_lastTimeStamp = time;
}