void PUParticleSystem3D::emitParticles( ParticlePool &pool, PUEmitter* emitter, unsigned requested, float elapsedTime )
{
    Vec3 scale = getDerivedScale();
    Mat4 rotMat;
    Mat4::createRotation(getDerivedOrientation(), &rotMat);
    float timePoint = 0.0f;
    float timeInc = elapsedTime / requested;
    for (unsigned short i = 0; i < requested; ++i)
    {
        PUParticle3D *particle = static_cast<PUParticle3D *>(pool.createData());
        if (!particle) 
            return;

        particle->initForEmission();
        emitter->initParticleForEmission(particle);

        particle->direction = (rotMat * Vec3(particle->direction.x, particle->direction.y, particle->direction.z));
        particle->originalDirection = (rotMat * Vec3(particle->originalDirection.x, particle->originalDirection.y, particle->originalDirection.z));

        for (auto& it : _affectors) {
            if (it->isEnabled())
            {
                (static_cast<PUAffector*>(it))->initParticleForEmission(particle);
            }
        }

        initParticleForEmission(particle);

        particle->position.add(particle->direction.x * scale.x * _particleSystemScaleVelocity * timePoint
                                 , particle->direction.y * scale.y * _particleSystemScaleVelocity * timePoint
                                 , particle->direction.z * scale.z * _particleSystemScaleVelocity * timePoint);
        // Increment time fragment
        timePoint += timeInc;
    }
}
Esempio n. 2
0
// Get transform in world space.
const Matrix4& Node::Transform::getFullWorldTransform(const Node* parent) const {
    if (mCachedTransformOutOfDate) {
        mCachedTransform.makeTransform(getDerivedTranslate(parent),
                                       getDerivedScale(parent),
                                       getDerivedRotate(parent));
        mCachedTransformOutOfDate = false;
    }
    return mCachedTransform;
}
void PUParticleSystem3D::processMotion( PUParticle3D* particle, float timeElapsed, bool firstParticle )
{
    if (particle->isFreezed())
    return;


    /** Because everything is calculated in worldspace we recalculate it back to the techniques' origin (the result is still 
        worldspace) just by adding a relative offset of the particle system, technique, emitter or visual particle.
        Change in V1.4:
        The additional PEF_EMITTED check fixes the problem with scenenodese moving forward at extremely fast speeds 
        The bug is due to how PU code processes keep_local, and the calculation shouldn't be applied to newly emitted particles.
    */
    if (!particle->hasEventFlags(PUParticle3D::PEF_EMITTED))
    {
        if (!particle->parentEmitter->makeParticleLocal(particle))
        {
            if (!makeParticleLocal(particle))
            {
                _parentParticleSystem->makeParticleLocal(particle);
            }
        }
    }

    /** Adjust position of the particle if the parent has rotated (only in case of particle system with 'keep local').
        PU 1.4: Added check that technique may not be local, otherwise particles are rotated twice as fast.
    */
    if (_parentParticleSystem->isKeepLocal() && !_keepLocal)
    {
        /** Ignore some rendersystems, because they are rotated by Ogre itself.
            Entities for example are always rotated (even if not local), based on the node orientation. A Billboard not.
        */
        if (_render && !static_cast<PURender *>(_render)->autoRotate)
        {
            _parentParticleSystem->rotationOffset(particle->position);
        }
    }

    // Added for 1.3
    if (particle->hasEventFlags(PUParticle3D::PEF_EMITTED))
        return;

    // Adjust the velocity to the allowed maximum.
    if (_maxVelocitySet && particle->calculateVelocity() > _maxVelocity)
    {
        particle->direction *= (_maxVelocity / particle->direction.length());
    }

    Vec3 scale = getDerivedScale();
    // Update the position with the direction.
    particle->position.add(particle->direction.x * scale.x * _particleSystemScaleVelocity * timeElapsed
                             , particle->direction.y * scale.y * _particleSystemScaleVelocity * timeElapsed
                             , particle->direction.z * scale.z * _particleSystemScaleVelocity * timeElapsed);
}
Esempio n. 4
0
	Point3r SceneNode::getDerivedScale()const
	{
		Point3r result( m_scale );
		auto parent = getParent();

		if ( parent )
		{
			result *= parent->getDerivedScale();
		}

		return result;
	}
void PUParticleSystem3D::prepared()
{
    if (!_prepared){
        //if (_emitter && _emitter->isEnabled())
        //{
        //    auto emitter = static_cast<PUEmitter*>(_emitter);
        //    emitter->prepare();
        //}

        if (_render)
            static_cast<PURender *>(_render)->prepare();

        for (auto it : _behaviourTemplates) {
            it->prepare();
        }

        for (auto it : _emitters) {
            //if (it->isEnabled())
                (static_cast<PUEmitter*>(it))->prepare();
        }

        for (auto it : _affectors) {
            //if (it->isEnabled())
                (static_cast<PUAffector*>(it))->prepare();
        }
        
        if (!_poolPrepared){
            for (auto it : _emitters) {
                //if (it->isEnabled())
                PUEmitter *emitter = static_cast<PUEmitter*>(it);
                if (emitter->getEmitsType() == PUParticle3D::PT_EMITTER){
                    PUEmitter *emitted = static_cast<PUEmitter*>(emitter->getEmitsEntityPtr());
                    for (unsigned int i = 0; i < _emittedEmitterQuota; ++i){
                        auto p = new (std::nothrow) PUParticle3D();
                        p->particleType = PUParticle3D::PT_EMITTER;
                        p->particleEntityPtr = emitted->clone();
                        p->particleEntityPtr->retain();
                        p->copyBehaviours(_behaviourTemplates);
                        _emittedEmitterParticlePool[emitted->getName()].addData(p);
                    }
                }
                else if (emitter->getEmitsType() == PUParticle3D::PT_TECHNIQUE){
                    PUParticleSystem3D *emitted = static_cast<PUParticleSystem3D*>(emitter->getEmitsEntityPtr());
                    for (unsigned int i = 0; i < _emittedSystemQuota; ++i){
                        PUParticleSystem3D *clonePS = emitted->clone();
                        auto p = new (std::nothrow) PUParticle3D();
                        p->particleType = PUParticle3D::PT_TECHNIQUE;
                        p->particleEntityPtr = clonePS;
                        p->particleEntityPtr->retain();
                        p->copyBehaviours(_behaviourTemplates);
                        _emittedSystemParticlePool[emitted->getName()].addData(p);
                        clonePS->prepared();
                    }
                    //emitted->stopParticle();
                }

            }

            for (unsigned int i = 0; i < _particleQuota; ++i){
                auto p = new (std::nothrow) PUParticle3D();
                p->copyBehaviours(_behaviourTemplates);
                _particlePool.addData(p);
            }
            _poolPrepared = true;
        }

        _prepared = true;
        _timeElapsedSinceStart = 0.0f;
        if (_parentParticleSystem){
            _particleSystemScaleVelocity = _parentParticleSystem->getParticleSystemScaleVelocity();
        }
    }

    notifyRescaled(getDerivedScale());
}
void PUParticleSystem3D::processParticle( ParticlePool &pool, bool &firstActiveParticle, bool &firstParticle, float elapsedTime )
{
    Vec3 scale = getDerivedScale();
    PUParticle3D *particle = static_cast<PUParticle3D *>(pool.getFirst());
    //Mat4 ltow = getNodeToWorldTransform();
    //Vec3 scl;
    //Quaternion rot;
    //ltow.decompose(&scl, &rot, nullptr);
    while (particle){

        if (!isExpired(particle, elapsedTime)){
            particle->process(elapsedTime);

            //if (_emitter && _emitter->isEnabled())
            //    _emitter->updateEmitter(particle, elapsedTime);

            for (auto it : _emitters) {
                if (it->isEnabled() && !it->isMarkedForEmission()){
                    (static_cast<PUEmitter*>(it))->updateEmitter(particle, elapsedTime);
                }
            }

            for (auto& it : _affectors) {
                if (it->isEnabled()){
                    (static_cast<PUAffector*>(it))->process(particle, elapsedTime, firstActiveParticle);
                }
            }

            if (_render)
                static_cast<PURender *>(_render)->updateRender(particle, elapsedTime, firstActiveParticle);

            if (_isEnabled && particle->particleType != PUParticle3D::PT_VISUAL){
                if (particle->particleType == PUParticle3D::PT_EMITTER){
                    auto emitter = static_cast<PUEmitter *>(particle->particleEntityPtr);
                    emitter->setLocalPosition(particle->position);
                    executeEmitParticles(emitter, emitter->calculateRequestedParticles(elapsedTime), elapsedTime);
                }else if (particle->particleType == PUParticle3D::PT_TECHNIQUE){
                    auto system = static_cast<PUParticleSystem3D *>(particle->particleEntityPtr);
                    system->setPosition3D(particle->position);
                    system->setRotationQuat(particle->orientation);
                    //system->setScaleX(scl.x);system->setScaleY(scl.y);system->setScaleZ(scl.z);
                    system->forceUpdate(elapsedTime);
                }
            }

            firstActiveParticle = false;
            // Keep latest position
            particle->latestPosition = particle->position;

            //if (_maxVelocitySet && particle->calculateVelocity() > _maxVelocity)
            //{
            //    particle->direction *= (_maxVelocity / particle->direction.length());
            //}

            //// Update the position with the direction.
            //particle->position += (particle->direction * _particleSystemScaleVelocity * elapsedTime);
            //particle->positionInWorld = particle->position;
            //particle->orientationInWorld = particle->orientation;
            //particle->widthInWorld = particle->width;
            //particle->heightInWorld = particle->height;
            //particle->depthInWorld = particle->depth;

            //bool keepLocal = _keepLocal;
            //PUParticleSystem3D *parent = dynamic_cast<PUParticleSystem3D *>(getParent());
            //if (parent) keepLocal = keepLocal || parent->isKeepLocal();

            //if (keepLocal){
            //    ltow.transformPoint(particle->positionInWorld, &particle->positionInWorld);
            //    Vec3 ori;
            //    ltow.transformVector(Vec3(particle->orientation.x, particle->orientation.y, particle->orientation.z), &ori);
            //    particle->orientationInWorld.x = ori.x; particle->orientationInWorld.y = ori.y; particle->orientationInWorld.z = ori.z;
            //    particle->widthInWorld = scl.x * particle->width;
            //    particle->heightInWorld = scl.y * particle->height;
            //    particle->depthInWorld = scl.z * particle->depth;
            //}
            processMotion(particle, elapsedTime, scale, firstActiveParticle);
        }
        else{
            initParticleForExpiration(particle, elapsedTime);
            pool.lockLatestData();
        }

        for (auto it : _observers){
            if (it->isEnabled()){
                it->updateObserver(particle, elapsedTime, firstParticle);
            }
        }

        if (particle->hasEventFlags(PUParticle3D::PEF_EXPIRED))
        {
            particle->setEventFlags(0);
            particle->addEventFlags(PUParticle3D::PEF_EXPIRED);
        }
        else
        {
            particle->setEventFlags(0);
        }

        particle->timeToLive -= elapsedTime;
        firstParticle = false;
        particle = static_cast<PUParticle3D *>(pool.getNext());
    }
}