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); }
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); } } }
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); }
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; } }
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); } }
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; }
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(); }
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); } }
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); } }
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; }