예제 #1
0
void RenderingEngine::DrawTouchTrail(){
    long length = _touchTrails->size();
    if(length == 0) return;
    if(length > _touchTrailArraysLength){
        if(_touchTrailArrays != NULL){
            delete _touchTrailArrays;
        }
        length *= 2;
        _touchTrailArrays = CreateParticlePointArrays(length*2);
        _touchTrailArraysLength = length;
    }
    glUniform1f(_uniforms.PointSize, _factory->particleWidth);
    DrawParticles(_touchTrails, _touchTrails->size(), _touchTrailArrays);
}
예제 #2
0
void ParticleRender::drawParticles(const ParticleList &particles) {
	ci::gl::ScopedTextureBind	stb(mTexture);
	// Prevent writing to the depth buffer, which will block out
	// pixels that are supposed to be transparent.
	ci::gl::ScopedDepthWrite	sdw(false);
	ci::gl::ScopedBlendAlpha	sba;
	ci::gl::color(1.0f, 1.0f, 1.0f, 1.0f);

	size_t						k = 0, size = particles.size();
	while (size >= BUFFER_SIZE) {
		drawParticles(k, k + BUFFER_SIZE, particles);
		k += BUFFER_SIZE;
		size -= BUFFER_SIZE;
	}
	drawParticles(k, particles.size(), particles);
}
void AdvanceTime(ParticleList& list, float dt, float timeStep)
{
    Time += dt;

    for (size_t i = 0; i < list.size(); ++i) {
        Point3 p(list[i].Px, list[i].Py, list[i].Pz);
        Vector3 v = ComputeCurl(p);
        Point3 midx = p + 0.5f * timeStep * v;
        p += timeStep * ComputeCurl(midx);
        list[i].Px = p.getX();
        list[i].Py = p.getY();
        list[i].Pz = p.getZ();
        list[i].Vx = v.getX();
        list[i].Vy = v.getY();
        list[i].Vz = v.getZ();
    }

    for (ParticleList::iterator i = list.begin(); i != list.end();) {
        if (i->Py > PlumeCeiling) {
            i = list.erase(i);
        } else {
            ++i;
        }
    }

   noise.set_time(0.5f*NoiseGain[0]/NoiseLengthScale[0]*Time);

   if (!ShowStreamlines || Time < 0.1f)
        SeedParticles(list, dt);
}
void beforeResort(ParticleList &pl, OutBuffer& out) {
  if (pl.size() == 1) {
    beforeResortCalled = true;
    int res = 42;
    out.write(res);
  }
}
void afterResort(ParticleList &pl, InBuffer& inbuf) {
  if (pl.size() == 1) {
    afterResortCalled = true;
    int res;
    inbuf.read(res);
    BOOST_CHECK_EQUAL(res, 42);
  }
}
예제 #6
0
  void FixedSingleList::afterRecvParticles(ParticleList &pl, InBuffer& buf) {
	longint size = pl.size();
    std::vector< longint > received(size);
    buf.read(received);
    for (std::vector< longint >::iterator it=received.begin(); it!=received.end(); it++) {
    	globalSingles.insert(*it);
    }
    LOG4ESPP_INFO(theLogger, "received fixed single list after receive particles");
  }
예제 #7
0
void ParticleRender::drawParticles(size_t start, size_t end, const ParticleList &particles) {
	if (start >= particles.size()) return;
	if (end > particles.size()) end = particles.size();

	// update our instance positions; map our instance data VBO, write new positions, unmap
	glm::vec4 *data = (glm::vec4*)mInstanceDataVbo->mapReplace();
	for (size_t k=start; k<end; ++k) {
		const Particle&			p(particles[k]);
		data->x = p.mPosition.x;
		data->y = p.mPosition.y;
		data->z = p.mPosition.z;
		data->w = p.mAlpha;
		*data++;
	}
	mInstanceDataVbo->unmap();

	// and draw
	mBatch->drawInstanced(end-start);
}
예제 #8
0
  void FixedSingleList::beforeSendParticles(ParticleList& pl, OutBuffer& buf) {
	std::vector< longint > toSend(pl.size());
    // loop over the particle list
    for (ParticleList::Iterator pit(pl); pit.isValid(); ++pit) {
      longint pid = pit->id();
      toSend.push_back(pid);
      globalSingles.erase(pid);
      LOG4ESPP_DEBUG(theLogger, "erase and send particle with pid from FixedSingleList" << pid);
    }
    // send the list
    buf.write(toSend);
    LOG4ESPP_INFO(theLogger, "prepared fixed single list before send particles");
  }
예제 #9
0
void  VarianceDiffusionStrategy<StateType>::diffuse(const ParticleList &_src, ParticleList &_dest)
{
	if(_src.size() == 0) return;
	if(_dest.size() != _src.size()) _dest = _src;

	const unsigned numDofs = _src[0].state.size();

	unsigned index = 0;
	StateType noise = _dest[0].state;

	if(mVariance.size() != noise.size())
	{
		TRACE("------------- variance has wrong size. (should not be possible) ---------- ABORTING");
		return;
	}

	if(mVarianceFactor.size() != noise.size())
	{
		TRACE("----------resizing variance factors. (should not happen) -------------- ");
		mVarianceFactor.resize(noise.size(), 1);
	}

	// iterate over all source particles
	for(ParticleListConstIterator it = _src.begin(); it != _src.end(); it++)
	{
		// for every dof
		for(unsigned i=0; i < numDofs; i++)
		{
			noise[i] = this->mNormDistGenerator() *  mVariance[i] * mVarianceFactor[i];
		}

		_dest[index].state = noise;
		_dest[index].state += _src[index].state;

		index++;
	}
}
static void SeedParticles(ParticleList& list, float dt)
{
    static float time = 0;
    time += dt;
    unsigned int num_new = (unsigned int) (time * ParticlesPerSecond);
    if (num_new == 0)
        return;

    time = 0;
    list.reserve(list.size() + num_new);
    for (unsigned int i = 0; i < num_new; ++i) {
        float theta = randhashf(Seed++, 0, M_PI * 2);
        float r = randhashf(Seed++, 0, SeedRadius);
        float y = randhashf(Seed++, 0, InitialBand);
        Particle p;
        p.Px = r*std::cos(theta);
        p.Py = PlumeBase + y;
        p.Pz = r*std::sin(theta) + 0.125f; // Nudge the emitter towards the viewer
        p.ToB = Time;
        list.push_back(p);
    }
}
예제 #11
0
int main( int argc, char **argv )
{    
    //
    //  process command line parameters
    //
    if( find_option( argc, argv, "-h" ) >= 0 )
    {
        printf( "Options:\n" );
        printf( "-h to see this help\n" );
        printf( "-n <int> to set the number of particles\n" );
        printf( "-o <filename> to specify the output file name\n" );
        return 0;
    }
    
    int n = read_int( argc, argv, "-n", 1000 );
    char *savename = read_string( argc, argv, "-o", NULL );
    
    //
    //  set up MPI
    //
    int n_proc, rank;
    set_size(n);
    int num_cells = get_num_cells();
    MPI_Init( &argc, &argv );
    MPI_Comm_size( MPI_COMM_WORLD, &n_proc );
    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
    
    //
    //  allocate generic resources
    //

    // FILE *fsave = savename && rank == 0 ? fopen( savename, "w" ) : NULL;
    FILE *fsave = savename ? fopen( savename, "w" ) : NULL;
    particle_t *particles = (particle_t*) malloc( n * sizeof(particle_t) );
    
    MPI_Datatype PARTICLE;
    MPI_Type_contiguous( 6, MPI_DOUBLE, &PARTICLE );
    MPI_Type_commit( &PARTICLE );
    

    ParticleList reference_particles; // the particles needed to compute correct forces on my_particles.
    ParticleList my_particles;        // the particles that this process is responsible for updating.

    CellMatrix cells(num_cells);
   
    // dummy particle
    particle_t dummy;
    dummy.x = -1;
    dummy.y = -1;

    //
    //  set up the data partitioning across processors
    //
    int *partition_offsets = (int*) malloc( (n_proc+1) * sizeof(int) );
    int *partition_sizes = (int*) malloc( n_proc * sizeof(int) );
    

    //
    //  allocate storage for local partition
    //
    int rows_per_thread = (num_cells + n_proc - 1) / n_proc;
    int top_row     = min(  rank     * rows_per_thread, num_cells); // the top row that the process is responsible for.
    int bottom_row  = min( (rank+1)  * rows_per_thread, num_cells); // the bottow row that this process needs but is not responsible for
    
    int my_amount;
    
    //
    //  initialize and distribute the particles (that's fine to leave it unoptimized)
    //
    ParticleList all_particles;
    all_particles.clear();
    init_cell_matrix(cells);
    if( rank == 0 )
    {
        all_particles.clear();
        init_particles( n, particles );
        
        update_cells(particles, cells, n);
        for(int rankId = 0; rankId < n_proc; rankId++) 
        {
            partition_offsets[rankId] = all_particles.size();
            int first_row = min(  rankId     * rows_per_thread, num_cells);
            int last_row  = min( (rankId+1)  * rows_per_thread, num_cells);

            ParticleList tmp;
            tmp.clear();
            get_particles_from_rows(first_row, last_row, &tmp, cells);
            all_particles.insert(all_particles.end(), tmp.begin(), tmp.end());
            partition_sizes[rankId] = tmp.size();

        }
       partition_offsets[n_proc] = n;
    }
    // broadcast all offsets and sizes so we can scatter later.
    MPI_Bcast(partition_offsets, n_proc+1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(partition_sizes, n_proc, MPI_INT, 0, MPI_COMM_WORLD);

    // get my_amount from the partition sizes array and rezise the my_particles vector.
    my_amount = partition_sizes[rank];
    my_particles.resize(my_amount);
    
    MPI_Scatterv( &all_particles.front(), partition_sizes, partition_offsets, PARTICLE, &my_particles.front(), my_amount, PARTICLE, 0, MPI_COMM_WORLD );   
    
    
    clear_cells(top_row-1, bottom_row+1, cells); 
    add_particles_mpi(my_particles, cells);

    //
    //  simulate a number of time steps
    //
    double simulation_time = read_timer( );
    for( int step = 0; step < NSTEPS; step++ )
    {

        //
        //  save current step if necessary (slightly different semantics than in other codes)
        //
        if( fsave && (step%SAVEFREQ) == 0 )
        {


            if(rank == 0) // root saves to file. First it recieves particles from other processes then write to file
            {
                int num_waiting = n - my_particles.size();
                int i;
                int count = num_waiting;
                // put root particles in particles array
                for(i = 0; i < my_particles.size(); i++)
                {
                    particles[i] = my_particles[i];
                }
                particle_t other;
                // recieve particles from other processes.
                while(num_waiting > 0)
                {
                    MPI_Status stat;
                    MPI_Recv(&other, 1, PARTICLE, MPI_ANY_SOURCE, SAVE, MPI_COMM_WORLD, &stat);
                    particles[i] = other;                    
                    i++;
                    num_waiting--;
                    
                }
                
                save( fsave, n, particles );
            }
            else  // all other processes will send their particles to root(0)
            {
                for(int i = 0; i  < my_particles.size(); i++)
                {
                    MPI_Request req;
                    MPI_Isend(&my_particles[i], 1 , PARTICLE, 0, SAVE, MPI_COMM_WORLD, &req );
                }
            }

            
        }
        
        //
        //  compute all forces
        //
        
        ParticleList::iterator iter = my_particles.begin();
        while(iter != my_particles.end())
        {
            
            particle_t *curr_particle = &(*iter);
            curr_particle->ax = 0;
            curr_particle->ay = 0;
            
             apply_force(curr_particle, cells);
             ++iter;

        }

        reference_particles.clear();
        ParticleList out_of_bounds;
        out_of_bounds.clear();
        ParticleList bounds;
        bounds.clear();
        iter = my_particles.begin();
        /*
            Iterate through all my particles and send all particles that are not our responsibility
            any longer to other processes. Send first and last row particles as references to other
            processes aswell.
        */
        while(iter != my_particles.end())
        {
            
           
            move(*iter);
            Point p = get_cell_index(*iter);
            if(p.y < top_row || p.y >= bottom_row) // check if out of bounds
            {
                particle_t tmp = (*iter);
                int index = out_of_bounds.size();
                out_of_bounds.push_back(tmp);
                iter = my_particles.erase(iter);

                // send to process above or below
                int target = (p.y < top_row)? rank-1 : rank+1;
                MPI_Request request;
                MPI_Isend(&out_of_bounds[index], 1, PARTICLE, target, NEW, MPI_COMM_WORLD, &request ); // non blocking send
                continue;
            }
            else if(p.y == top_row && top_row > 0) // send our top row particles to the process above except if we are root
            {
                
            
                particle_t tmp = (*iter);
                int index = bounds.size();
                bounds.push_back(tmp);

                
                MPI_Request request;
                MPI_Isend(&bounds[index], 1, PARTICLE, rank-1, BOUND, MPI_COMM_WORLD, &request ); // non blocking send
            }
            else if(p.y == bottom_row-1 && rank < n_proc-1) // send our top row particles to the process below except if we are last
            {
                particle_t tmp = (*iter);
                int index = bounds.size();
                bounds.push_back(tmp);

                
                MPI_Request request;
                MPI_Isend(&bounds[index], 1, PARTICLE, rank+1, BOUND, MPI_COMM_WORLD, &request ); // non blocking send
            }

            ++iter;
             
        }
        MPI_Request req;

        // send message to process below and above that we are done sending particles.
        if(top_row > 0) MPI_Isend(&dummy, 1, PARTICLE, rank - 1, DONE, MPI_COMM_WORLD, &req);
        if(bottom_row < num_cells) MPI_Isend(&dummy, 1, PARTICLE, rank + 1, DONE, MPI_COMM_WORLD, &req);

        // get ready to recieve new particles from other processes.
        int isDone = 2;
        if(top_row  == 0) isDone--; // we are root, should only recieve from process below.
        if(bottom_row == num_cells) isDone--; // we are last process, we should only recieve from process above.

        particle_t new_particle;
        while(isDone > 0)
        {
            MPI_Status status;
            MPI_Recv(&new_particle, 1, PARTICLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);

            // check what sort of particle was recieved.
            if(status.MPI_TAG == DONE)
            {
                isDone--;
                continue;
            }
            else if(status.MPI_TAG == NEW)
            {
                my_particles.push_back(new_particle);
            }
            else if(status.MPI_TAG == BOUND)
            {
                reference_particles.push_back(new_particle);
            }

        }

        MPI_Barrier(MPI_COMM_WORLD); // wait in order to synchronize with same frame.  
        // update our cells with my particles and the reference particles. 
        clear_cells(top_row-1, bottom_row+1, cells); 
        add_particles_mpi(my_particles, cells);
        add_particles_mpi(reference_particles, cells);
    }

    simulation_time = read_timer( ) - simulation_time;
    
    if( rank == 0 )
        printf( "n = %d, n_procs = %d, simulation time = %g s\n", n, n_proc, simulation_time );
    
    //
    //  release resources
    //
    free( partition_offsets );
    free( partition_sizes );
    free( particles );
    if( fsave )
        fclose( fsave );
    
    MPI_Finalize( );
    
    return 0;
}
예제 #12
0
void ParticleEmitter::spawn(float delta, const AnimationTime& at, ParticleList& ps, const Matrix& m)
{
	if (!mVisibility.getFrame(at.current))
	{
		return;
	}
	//换算成秒
	float timeFactor = delta / 1000.0f;
	mCurrentEmission += mEmitRate.getFrame(at) * timeFactor;
	while(mCurrentEmission >= 1.0f)
	{
		if (ps.size() >= mLimitNumber /*|| !ps.empty()*/)
		{
			return;
		}
		Particle p;
		p.mEmitter = this;
		float		speed;
		float		width;
		float		length;
		float		height;
		float		latitude;
		float		variation;

		p.mVertices[0].texture_.x = 0;
		p.mVertices[0].texture_.y = 0;

		p.mVertices[1].texture_.x = 0;
		p.mVertices[1].texture_.y = 1;

		p.mVertices[2].texture_.x = 1;
		p.mVertices[2].texture_.y = 1;

		p.mVertices[3].texture_.x = 1;
		p.mVertices[3].texture_.y = 0;

		p.mStopMove = false;

		p.mColorStart = mColorStart;
		p.mColorMiddle = mColorMiddle;
		p.mColorEnd = mColorEnd;
		p.mAlpha = mAlpha;
		speed = mSpeedKFs.getFrame(at);
		width = mWidth.getFrame(at);
		length = mLength.getFrame(at);
		height = mHeigth.getFrame(at);
		latitude = mLatitude.getFrame(at);
		variation = mVariationKFs.getFrame(at);
		speed *= (1.0f + randomReal(0.0f, variation));

		p.mPosition = Vector3(randomReal(-width,width), randomReal(-height,height), randomReal(-length,length));
		p.mPosition = m.applyVector(p.mPosition);
		p.mOriginalPosition = p.mPosition;
		p.mNodeOriginalPosition = m.applyToOrigin();
		Matrix mtxX;
		{
			Quaternion q;
			q.fromAngleAxis(randomReal(0,latitude * TwoPI / 360.f), Vector3::AxisX);
			mtxX.make(Vector3::Zero, Vector3::One, q);
		}
		
		Matrix mtxY;
		{
			Quaternion q;
			q.fromAngleAxis(randomReal(0,TwoPI), Vector3::AxisY);
			mtxY.make(Vector3::Zero, Vector3::One, q);
		}
		Matrix rot;
		rot.multiply(mtxX, mtxY);
		p.mVelocity = rot.applyVector(Vector3(0,1,0));
		p.mVelocity.normalise();
		p.mVelocity = m.applyVectorNormal(p.mVelocity);

		p.mVelocity *= speed;

		p.mAge = 0.0f;
		if(mLifeSpan < mLifeVar)
			p.mLife = mLifeSpan;
		else
			p.mLife= randomReal(mLifeSpan - mLifeVar, mLifeSpan + mLifeVar);

		p.mGravity = mGravity.getFrame(at);
		p.mExplosiveForce = mExplosiveForce.getFrame(at);

		//每个粒子的缩放比例都可能不同
		p.mScale.x = randomReal(mScale.x - mScaleVar.x, mScale.x + mScaleVar.x);
		if(mFixedSize)
		{
			p.mScale.y = p.mScale.z = p.mScale.x;
		}
		else
		{
			p.mScale.y = randomReal(mScale.y - mScaleVar.y, mScale.y + mScaleVar.y);
			p.mScale.z = randomReal(mScale.z - mScaleVar.z, mScale.z + mScaleVar.z);
		}

		//粒子旋转的角度
		p.mAngle = randomReal(mInitAngleBegin, mInitAngleEnd);
		p.mRotateSpeed = randomReal(mRotateSpeed - mRotateSpeedVar, mRotateSpeed + mRotateSpeedVar) * timeFactor * 15.0f;

		if(mHead)
		{
			p.mHeadFramesNum = ((mHeadLifeSpan.y - mHeadLifeSpan.x + 1.0f) * mHeadLifeSpan.z);
			p.mHeadDecalFramesNum = ((mHeadDecay.y - mHeadDecay.x + 1.0f) * mHeadDecay.z);
		}
		else
		{
			p.mHeadFramesNum = 0;
			p.mHeadDecalFramesNum = 0;
		}

		if(mTail)
		{
			p.mTailFramesNum = ((mTailLifeSpan.y - mTailLifeSpan.x + 1.0f) * mTailLifeSpan.z);
			p.mTailDecalFramesNum = ((mTailDecay.y - mTailDecay.x + 1.0f) * mTailDecay.z);
		}
		else
		{
			p.mTailFramesNum = 0;
			p.mTailDecalFramesNum = 0;
		}

		if(mWander)
		{
			p.mWanderRadius = mWanderRadius;
			p.mWanderSpeed = mWanderSpeed;
			p.mWander = true;
			p.mWanderS = 0.0f;
			Matrix m1,m2;
			for(int i = 0;i < 4;i++)
			{
				{
					Quaternion q;
					q.fromAngleAxis(randomReal(0,TwoPI), Vector3::AxisX);
					m1.make(Vector3::Zero, Vector3::One, q);
				}
				{
					Quaternion q;
					q.fromAngleAxis(randomReal(0,TwoPI), Vector3::AxisY);
					m2.make(Vector3::Zero, Vector3::One, q);
				}
				Matrix mt;
				mt.multiply(m1, m2);
				p.mWanderCatmullRom[i] = mWanderRadius * (mt.applyVector(Vector3::AxisZ));
			}
		}
		//
		ps.push_back(p);
		//
		mCurrentEmission -= 1.0f;
	}
}
    /* recieve and rebuild global tuple information */
    void FixedTupleListAdress::afterRecvParticles
                                    (ParticleList &pl, InBuffer& buf) {

        //std::cout << "afterRecvParticles\n";

        /*
        std::vector<longint> received, pids;
        int n;
        longint pidK;
        GlobalTuples::iterator it = globalTuples.begin();


        // receive the tuple list
        buf.read(received);
        int size = received.size();

        int i = 0;
        while (i < size) {
            // unpack the list
            pidK = received[i++];
            //std::cout << "receive pidK "<< pidK << "\n";

            n = received[i++];
            //std::cout << "receive n "<< n << "\n";

            for (; n > 0; --n) {
            	LOG4ESPP_DEBUG(theLogger, "received vector for pid " << pidK);
                storage->addAdrATParticleFTPL(received[i]); // add AT particle to storage
                pids.push_back(received[i++]);
            }

            // add pids vector to global tuples
            it = globalTuples.insert(it, std::make_pair(pidK, pids));
            pids.clear();
        }

        if (i != size) {
            LOG4ESPP_ERROR(theLogger,
                    "recv particles might have read garbage\n");
        }

        LOG4ESPP_INFO(theLogger,
                "received fixed particle list after receive particles");
        */


        std::vector<longint> pids;
		int size, i, n;
		longint pidK;
		GlobalTuples::iterator it = globalTuples.begin();

		size = pl.size();

		for (i = 0; i < size; ++i) {
		    //std::cout << "i: " << i << "\n";

            // receive the tuple list
            //std::cout << "receive pidK: ";
            buf.read(pidK);
            //std::cout << pidK << " at ";


            /*
            // testing
            Particle* vp = storage->lookupRealParticle(pidK);
            Real3D vpp = vp->position();

            // see where VP is folded
            Real3D vpp_old = vpp;
            Real3D vpp_new = vpp;
            Real3D moved;
            int dir;
            Int3D image(0,0,0);

            for (dir = 0; dir < 3; ++dir) {
                storage->getSystem()->bc->foldCoordinate(vpp_new, image, dir);
                if (vpp_new[dir] != vpp_old[dir]) {
                    moved[dir] = vpp_old[dir] - vpp_new[dir];
                    break; // do not continue looping
                }
            }
            */


            //std::cout << "receive n: ";
            buf.read(n);
            //std::cout << n << "\n";

            //std::cout << storage->getRank() << ": add AT particles ";
            for (; n > 0; --n) {
                LOG4ESPP_DEBUG(theLogger, "received vector for pid " << pidK);
                /*storage->addAdrATParticleFTPL(received[i]); // add AT particle to storage
                pids.push_back(received[i++]);
                Particle *p = storage->addAdrATParticleFTPL();*/

                Particle p;
                //std::cout << " read *p : ";
                buf.read(p);

                //std::cout << " AT particle " << p.id() << " at " << p.position() << " ";
                //p.position()[dir] = p.position()[dir] - moved[dir];
                //std::cout << "--> moved to " << p.position() << "\n";

                storage->addAdrATParticleFTPL(p);

                //std::cout << p.getId() << " at " << p.position() << "\n";
                pids.push_back(p.id());
            }
            //std::cout << "\n";

            // add pids vector to global tuples
            it = globalTuples.insert(it, std::make_pair(pidK, pids));
            pids.clear();
		}

    }