void ComParticle::UpdateFire()
{
	for (size_t i = 0; i < m_vecParticles.size(); ++i)
	{
		Attribute* att = m_vecParticles[i];
		att->age += CClock::GetInstance()->GetFrameDuration();
		att->position.x += att->velocity.x;
		att->position.z -= att->velocity.z;
		att->position.y += att->velocity.y;
		//att->color.r += 0.01f;
		att->color.g -= 0.01f;
		att->color.b -= 0.01f;

		if (att->position.x > 1.0f || att->position.x < -1.0f)
			InitParticle(att);
		if (att->position.z > 2.0f || att->position.z < -2.0f)
			InitParticle(att);
		if (att->position.y > 2.0f)
			InitParticle(att);

		//if (att->color.g <= 0)
		//	att->color.g = 1.0f;
		//if (att->color.b <= 0)
		//	att->color.b = 153 / 255.0f;
	}
}
Exemple #2
0
void render()
{
	int i, active_particles = 0;

	//Clear color buffer
	glClear( GL_COLOR_BUFFER_BIT );
	
	glBegin(GL_POINTS);
	for(i=0;i<NUM_PARTICLES;i++)
	{
		if(particles[i].lifetime) 
		{
			active_particles++;
			particles[i].veloc_y -= GRAVITY;
			particles[i].x += particles[i].veloc_x;
			particles[i].y += particles[i].veloc_y;
			particles[i].lifetime--;

			glVertex3f( particles[i].x, particles[i].y, 0.0f); // draw pixel
		}
	}
	glEnd();

	if(!active_particles) InitParticle(1);
}
Exemple #3
0
void ParticleSystem::Update(ulong frame, float dt, Vector gravity)
{
  //avoid multiple updates within the same frame
  if (frame != m_frame)
  {
    //update all particles
    for (uint i = 0; i < m_count; ++i)
    {
      Particle &particle = m_aParticles[i];
      //reduce particle life
      particle.life -= particle.fade * dt;
      if (particle.life < 0.0f)
      {
        //respawn dead particle
        InitParticle(particle, true);
      }
      else
      {
        //update particle position
        particle.pX += particle.vX * dt;
        particle.pY += particle.vY * dt;
        particle.pZ += particle.vZ * dt;
        //update particle velocity
        //particles are not afected by world gravity in y-direction
        particle.vX += (m_aX + gravity[CX]) * dt;
        particle.vY +=  m_aY * dt;
        particle.vZ += (m_aZ + gravity[CZ]) * dt;
      }
    }
    //update current frame
    m_frame = frame;
  }
}
Exemple #4
0
void ParticleSystem::Reset(bool random)
{
  for (uint i = 0; i < m_count; ++i)
  {
    InitParticle(m_aParticles[i], random);
  }
}
int ParticleSystem::InitGL(GLvoid)
{
	//texture = LoadGLTextures("Data\\Particle.png");

	glShadeModel(GL_SMOOTH);							// Enable Smooth Shading
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);					
	glClearDepth(1.0f);									
	//glDisable(GL_DEPTH_TEST);						
	//glEnable(GL_BLEND);							
	glBlendFunc(GL_SRC_ALPHA, GL_ONE);		
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	
	glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);			
	glEnable(GL_TEXTURE_2D);				
	//glEnable(GL_CULL_FACE);
	//glCullFace(GL_BACK);

	float perColorIndex = 12.0 / MAX_PARTICLES;
	for (int loop = 0; loop < MAX_PARTICLES; loop++)		
	{
		particles[loop].active = true;								// Make All The Particles Active
		InitParticle(particles[loop]);
		particles[loop].grav = Vector(0.0f, -1.98f, 0.0f);
	}

	return TRUE;
}
Exemple #6
0
void CParticleSystem::Update(const float dt, const uint32_t ticks, const vec3_t& ownerpos)
{
    const float gravity = GetGravity();

    std::vector<particle_t>::iterator iter;
    for(iter = m_particles.begin();iter != m_particles.end(); ++iter)
    {
        if(iter->lifetime < 0.0f)
        {
            if(iter->respawn)
            {
                InitParticle(*iter, ownerpos);
            }
            else
            {
                continue;
            }
        }

        iter->origin = iter->origin + iter->vel*dt - vec3_t(0,dt*dt*0.5f*gravity,0);
        iter->vel.y -= gravity*dt;
        iter->lifetime -= dt;
        const float f = iter->lifetime / iter->totallifetime;
        const float scale = sin(f * lynxmath::PI);
        iter->alpha = iter->startalpha * scale;
        iter->size = scale * iter->startsize + 0.1f;
    }
}
Exemple #7
0
void SplitterSystem::UpdateEmitter(const float dt) {
	for (int particleIndex = 0; particleIndex < emitter.mParticleCount; ++particleIndex) {
		Particle *part = emitter.mParticles + particleIndex;
		part->mTime -= dt;

		//Game physics!
		part->mAcc += { 10.f, 10.f };
		part->mPos.y -= 2.5f;
		
		if (part->mDir.x > 0) {
			part->mPos.x -= part->mDir.x;
		} else {
			part->mPos.x -= part->mDir.x;
		}
		
		part->mVel += part->mAcc * dt;
		part->mOrientation += part->mAngularVelocity;
		part->mScale += { .02f, .02f };

		//Recycling particles(resetting values).
		if (part->mTime < 0) {
			getParams();
			InitParticle(part);
		}
	}
}
Exemple #8
0
void Particles::Init()
{
	glBindVertexArray(arrayObject);
	InitParams();
	InitMemory();
	InitParticle();
	glBindVertexArray(0);
}
HRESULT CPartEmitter::UpdateInternal(uint32 CurrentTime, uint32 TimerDelta) {
	int NumLive = 0;

	for (int i = 0; i < m_Particles.GetSize(); i++) {
		m_Particles[i]->Update(this, CurrentTime, TimerDelta);

		if (!m_Particles[i]->m_IsDead) NumLive++;
	}


	// we're understaffed
	if (NumLive < m_MaxParticles) {
		bool NeedsSort = false;
		if (CurrentTime - m_LastGenTime > m_GenInterval) {
			m_LastGenTime = CurrentTime;
			m_BatchesGenerated++;

			if (m_MaxBatches > 0 && m_BatchesGenerated > m_MaxBatches) {
				return S_OK;
			}

			int ToGen = std::min(m_GenAmount, m_MaxParticles - NumLive);
			while (ToGen > 0) {
				int FirstDeadIndex = -1;
				for (int i = 0; i < m_Particles.GetSize(); i++) {
					if (m_Particles[i]->m_IsDead) {
						FirstDeadIndex = i;
						break;
					}
				}

				CPartParticle *Particle;
				if (FirstDeadIndex >= 0) Particle = m_Particles[FirstDeadIndex];
				else {
					Particle = new CPartParticle(Game);
					m_Particles.Add(Particle);
				}
				InitParticle(Particle, CurrentTime, TimerDelta);
				NeedsSort = true;

				ToGen--;
			}
		}
		if (NeedsSort && (m_ScaleZBased || m_VelocityZBased || m_LifeTimeZBased))
			SortParticlesByZ();

		// we actually generated some particles and we're not in fast-forward mode
		if (NeedsSort && m_OverheadTime == 0) {
			if (m_Owner && m_EmitEvent) m_Owner->ApplyEvent(m_EmitEvent);
		}
	}

	return S_OK;
}
Exemple #10
0
particle* ParticleType::CreateParticle(ParticleSystem *pSys)//particle *pPart)
{
	if (!pSys) return NULL;

	particle *pPart = pSys->ActivateParticle();
	if (!pPart) return NULL;

	pPart->age = 0.0;
	pPart->age_death = m_Life.GetInstance();

	InitParticle(pPart, pSys);

	return pPart;
}
Exemple #11
0
ToolbarPanel::ToolbarPanel(wxWindow* parent, ee::LibraryPanel* library,
						   StagePanel* stage)
	: ee::ToolbarPanel(parent, stage->GetStageImpl())
	, m_stage(stage)
	, m_image(NULL)
{
	SetScrollbars(1,1, 200, 100, 0, 0);
	SetSizer(InitLayout());	
	InitParticle();

	SetDropTarget(new DropTarget(library, stage, this));

	RegistSubject(ee::ClearPanelSJ::Instance());
}
Exemple #12
0
//------------------------------------------------------------------------
// Purpose  : Add particle
//------------------------------------------------------------------------
void	ParticleSystem::AddParticle()
{
	// check if we have any dead particles
	if (m_DeadParticles.size() > 0)
	{
		// Reinitialize a particle
		Particle* p = m_DeadParticles.back();
		InitParticle(*p);

		// Now its not dead
		m_DeadParticles.pop_back();
		m_AliveParticles.push_back(p);
	}
}
Exemple #13
0
void ParticleEngine( double t, float dt )
{
    int      i;
    float    dt2;

    // Update particles (iterated several times per frame if dt is too
    // large)
    while( dt > 0.0f )
    {
        // Calculate delta time for this iteration
        dt2 = dt < MIN_DELTA_T ? dt : MIN_DELTA_T;

        // Update particles
        for( i = 0; i < MAX_PARTICLES; i ++ )
        {
            UpdateParticle( &particles[ i ], dt2 );
        }

        // Increase minimum age
        min_age += dt2;

        // Should we create any new particle(s)?
        while( min_age >= BIRTH_INTERVAL )
        {
            min_age -= BIRTH_INTERVAL;

            // Find a dead particle to replace with a new one
            for( i = 0; i < MAX_PARTICLES; i ++ )
            {
                if( !particles[ i ].active )
                {
                    InitParticle( &particles[ i ], t + min_age );
                    UpdateParticle( &particles[ i ], min_age );
                    break;
                }
            }
        }

        // Decrease frame delta time
        dt -= dt2;
    }
}
void ParticleSystem::Draw(void)
{
	glBindTexture(GL_TEXTURE_2D, texture);

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	//std::ofstream fout("out.txt", std::ios_base::trunc);

	glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)modeviewMatrix);
	for (int loop = 0;loop < MAX_PARTICLES; loop++)				
	{
		if (particles[loop].active)					
		{
			float x = particles[loop].pos.x;		
			float y = particles[loop].pos.y;		
			float z = particles[loop].pos.z;		

			// Draw The Particle Using Our RGB Values, Fade The Particle Based On It's Life
			//glColor4f(particles[loop].color.r, particles[loop].color.g, particles[loop].color.b, particles[loop].life);

			//glBegin(GL_TRIANGLE_STRIP);				
			//glTexCoord2d(1, 1); glVertex3f(x + parSize, y + parSize, z); // 右上
			//glTexCoord2d(0, 1); glVertex3f(x - parSize, y + parSize, z); // 左上
			//glTexCoord2d(1, 0); glVertex3f(x + parSize, y - parSize, z); // 右下
			//glTexCoord2d(0, 0); glVertex3f(x - parSize, y - parSize, z); // 左下
			//glEnd();

			//std::cout << x << "    " << y << "    " << z << std::endl;

			particles[loop].pos += particles[loop].speed / (slowdown * 1000);
			particles[loop].speed += (particles[loop].grav - particles[loop].speed * airFric);
			particles[loop].life -= particles[loop].fade;

			if (particles[loop].life < 0.0f)					// 当一个粒子生命周期到了时,重新给它赋值
			{
				InitParticle(particles[loop]);	
			}
		}
	}
	//fout.close();
}
Exemple #15
0
CParticleSystemBlood::CParticleSystemBlood(const PROPERTYMAP& properties, CResourceManager* resman, const vec3_t& ownerpos)
{
    const int particles = 8;
    m_particles.reserve(particles);

    m_texture = resman->GetTexture(CLynx::GetBaseDirFX() + "blood.tga");

    GetProperty(properties, "dx", &m_dir.x, 0);
    GetProperty(properties, "dy", &m_dir.y, 0);
    GetProperty(properties, "dz", &m_dir.z, -1.0f);
    GetProperty(properties, "size", &m_size, 4.8f);

    if(m_dir.AbsSquared() > 0.1f) // dir might be zero
        m_dir = m_dir.Normalized() * 6.0f;

    for(int i=0;i<particles;i++)
    {
        particle_t p;
        InitParticle(p, ownerpos);
        m_particles.push_back(p);
    }
}
void CDisintegrationEffect::OnUpdate (SUpdateCtx &Ctx, Metric rSecondsPerTick)

//	OnUpdate
//
//	Update the effect

	{
	int i;

	//	See if the effect has faded out

	m_iTick++;
	if (m_iTick >= LIFETIME)
		{
		Destroy(removedFromSystem, CDamageSource());
		return;
		}

	//	Otherwise, update the particles

	SParticle *pParticle = m_pParticles;
	for (i = 0; i < m_iParticleCount; i++, pParticle++)
		{
		pParticle->iTicksLeft--;
		pParticle->x += pParticle->xV;
		pParticle->y += pParticle->yV;

		if (m_iTick < DISPERSE_POINT)
			{
			if (pParticle->iTicksLeft <= 0)
				InitParticle(pParticle);
			}
		}

	//	If we're moving, slow down

	SetVel(CVector(GetVel().GetX() * g_SpaceDragFactor, GetVel().GetY() * g_SpaceDragFactor));
	}
Exemple #17
0
void Emitter::Play() {

	if(particles.empty() && maxParticles > 0) return;

	for(int i = 0; i < emissionRate && (!particles.empty() || maxParticles == 0); i++) {

		ParticlePtr particle;

		if(maxParticles > 0) {

			particle = particles.front();
			particles.pop_front();

		} else {
			particle = ParticlePtr(new Particle());
		}

		InitParticle(particle);
		emittedParticles.push_front(particle);
		particle->SetIsVisible(true);
	}

}
Exemple #18
0
void SplitterSystem::InitEmitter(float metersToPixels, float screenH, float screenW) {
	emitter.mPosition.x = screenW / 2;
	emitter.mPosition.y = screenH - 10;

	emitter.mParams = params;

	emitter.mParticleCapacity = params.mMaxParticles;
	emitter.mParticles = DBG_NEW Particle[emitter.mParticleCapacity];
	emitter.mParticleCount = emitter.mParams.mMinParticles;

	emitter.mMetersToPixels = metersToPixels;

	//set number of particles.
	int numberOfParticles = InRange(emitter.mParams.mMinParticles, emitter.mParams.mMaxParticles);

	//set particle lifetime.
	float lifetime = InRange(emitter.mParams.mMinLifeTimeMs, emitter.mParams.mMaxLifeTimeMs);
	// create particles.
	for (int i = 0; i != numberOfParticles; ++i) {
		emitter.mParticles[i].mTime = lifetime;
		InitParticle(emitter.mParticles + i);
	}
}
void dfParticleSystem::CreateParticle()
{
	ParticleInfo p;
	InitParticle(p);
	if(sInfo.useSpawnRect)
	{
		p.pos = vec2(
			(dfRand() * sInfo.spawnRect.width) + sInfo.spawnRect.left,
			(dfRand() * sInfo.spawnRect.height) + sInfo.spawnRect.top);
	}
	else
	{
		p.pos = vec2(sInfo.spawnPoint.x, sInfo.spawnPoint.y);
	}
	p.acc = sInfo.minAcc + (dfRand() * (sInfo.maxAcc - sInfo.minAcc));
	int colorIndex = rand() % sInfo.startColors.size();
	p.startColor = sInfo.startColors[colorIndex];
	p.color = p.startColor;
	p.dead = false;
	p.maxSize = sInfo.minParticleSize + (dfRand() * (sInfo.maxParticleSize - sInfo.minParticleSize));
	p.w = p.maxSize;
	p.h = p.maxSize;
	p.lifespan = sInfo.minLifespan + (dfRand() * (sInfo.maxLifespan - sInfo.minLifespan));
	p.lifetime = 0;
	p.rotation = sInfo.minStartRotation + (dfRand() * (sInfo.maxStartRotation - sInfo.minStartRotation));
	p.rotationSpd = sInfo.minRotationSpd + (dfRand() * (sInfo.maxRotationSpd - sInfo.minRotationSpd));
	float newVeloc = dfRand() * (sInfo.maxVeloc - sInfo.minVeloc);
	float xComp = cos((Pi32 / 180.f) * p.rotation) * newVeloc;
	float yComp = sin((Pi32 / 180.f) * p.rotation) * newVeloc;
	p.veloc = vec2(xComp, yComp);

	dfAssert(sInfo.textures.size() > 0); // need a texture to attatch to particle, dawg!
	int textureIndex = rand() % sInfo.textures.size();
	//p.texture = textures[textureIndex];
	p.renderRect = new Rect();
	RectSet(p.pos.x - (p.w / 2.f), p.pos.y - (p.h / 2.f), p.w, p.h, p.renderRect);

	for(int i = 0; i < currentParticleCap + 1 < MAX_PARTICLES ? currentParticleCap + 1 : MAX_PARTICLES; i++)
	{
		if(particles[i].dead)
		{
			particles[i] = p;
			
			particleRenderers[i].renderRect = p.renderRect;
			particleRenderers[i].SetTexture(sInfo.textures[textureIndex]);
			particleRenderers[i].renderInfo.active = true;
			particleRenderers[i].renderInfo.depth = layer;

			for(int cIndex = 0; cIndex < particleRenderers[i].renderInfo.uniforms.size(); cIndex++)
			{
				if(dfStrCmp("rect", particleRenderers[i].renderInfo.uniforms[cIndex].name))
				{
					particleRenderers[i].renderInfo.uniforms[cIndex].valueRect = p.renderRect;
					break;
				}
			}

			numParticles++;
			if(i == currentParticleCap)
				currentParticleCap++;

			return;
		}
	}

	dfWarn("Could not create particle. Max particles!");
}
Exemple #20
0
__private_extern__ void DrawParticle(Particle *p) // the math was easier in 2D - so 2D it is
{
    float screenx = (p->x * info->sys_glWidth / p->z) + info->sys_glWidth * 0.5f;
    float screeny = (p->y * info->sys_glWidth / p->z) + info->sys_glHeight * 0.5f;
    float oldscreenx = (p->oldx * info->sys_glWidth / p->oldz) + info->sys_glWidth * 0.5f;
    float oldscreeny = (p->oldy * info->sys_glWidth / p->oldz) + info->sys_glHeight * 0.5f;
    
    // near clip
    if(p->z < 100.0f) {
        InitParticle(p);
        return;
    }
    
    // side clip
    if(screenx > info->sys_glWidth + 100.0f || screenx < -100.0f) {
        InitParticle(p);
        return;
    }
    
    // vertical clip
    if(screeny > info->sys_glHeight + 100.0f || screeny < -100.0f) {
        InitParticle(p);
        return;
    }
    
    info->starfieldColor[info->starfieldColorIndex++] = p->r;
    info->starfieldColor[info->starfieldColorIndex++] = p->g;
    info->starfieldColor[info->starfieldColorIndex++] = p->b;
    info->starfieldColor[info->starfieldColorIndex++] = 1.0f;
    info->starfieldColor[info->starfieldColorIndex++] = p->r;
    info->starfieldColor[info->starfieldColorIndex++] = p->g;
    info->starfieldColor[info->starfieldColorIndex++] = p->b;
    info->starfieldColor[info->starfieldColorIndex++] = 1.0f;
    info->starfieldColor[info->starfieldColorIndex++] = p->r;
    info->starfieldColor[info->starfieldColorIndex++] = p->g;
    info->starfieldColor[info->starfieldColorIndex++] = p->b;
    info->starfieldColor[info->starfieldColorIndex++] = 1.0f;
    info->starfieldColor[info->starfieldColorIndex++] = p->r;
    info->starfieldColor[info->starfieldColorIndex++] = p->g;
    info->starfieldColor[info->starfieldColorIndex++] = p->b;
    info->starfieldColor[info->starfieldColorIndex++] = 1.0f;
    
    p->animFrame++;
    if (p->animFrame == 64) {
        p->animFrame = 0;
    }
    
    {
        float dx = (screenx-oldscreenx);
        float dy = (screeny-oldscreeny);
        float m = FastDistance2D(dx, dy);
        float u0 = (p->animFrame&&7) * 0.125f;
        float v0 = (p->animFrame>>3) * 0.125f;
        float u1 = u0 + 0.125f;
        float v1 = v0 + 0.125f;
        float size = (3500.0f*(info->sys_glWidth/1024.0f));
        float w = max(1.5f,size/p->z);
        float ow = max(1.5f,size/p->oldz);
        float d = FastDistance2D(dx, dy);
        float s, os, dxs, dys, dxos, dyos, dxm, dym;
        
        if(d) {
            s = w/d;
        } else {
            s = 0.0f;
        }
        
        if(d) {
            os = ow/d;
        } else {
            os = 0.0f;
        }
        
        m = 2.0f + s; 
        
        dxs = dx*s;
        dys = dy*s;
        dxos = dx*os;
        dyos = dy*os;
        dxm = dx*m;
        dym = dy*m;
                
        info->starfieldTextures[info->starfieldTexturesIndex++] = u0;
        info->starfieldTextures[info->starfieldTexturesIndex++] = v0;
        info->starfieldVertices[info->starfieldVerticesIndex++] = screenx+dxm-dys;
        info->starfieldVertices[info->starfieldVerticesIndex++] = screeny+dym+dxs;
        info->starfieldTextures[info->starfieldTexturesIndex++] = u0;
        info->starfieldTextures[info->starfieldTexturesIndex++] = v1;
        info->starfieldVertices[info->starfieldVerticesIndex++] = screenx+dxm+dys;
        info->starfieldVertices[info->starfieldVerticesIndex++] = screeny+dym-dxs;
        info->starfieldTextures[info->starfieldTexturesIndex++] = u1;
        info->starfieldTextures[info->starfieldTexturesIndex++] = v1;
        info->starfieldVertices[info->starfieldVerticesIndex++] = oldscreenx-dxm+dyos;
        info->starfieldVertices[info->starfieldVerticesIndex++] = oldscreeny-dym-dxos;
        info->starfieldTextures[info->starfieldTexturesIndex++] = u1;
        info->starfieldTextures[info->starfieldTexturesIndex++] = v0;
        info->starfieldVertices[info->starfieldVerticesIndex++] = oldscreenx-dxm-dyos;
        info->starfieldVertices[info->starfieldVerticesIndex++] = oldscreeny-dym+dxos;
    }
}
Exemple #21
0
void
CreateDistribution (cluster_type cluster, model_type model)
{
    particle *particle_array;
    int global_num_particles;
    particle *new_particle;
    char particle_state[RANDOM_SIZE];
    real charge;
    real r_scale;
    real v_scale;
    vector r_sum;
    vector v_sum;
    int end_limit;
    int i;
    int j;
    real temp_r;
    real radius;
    real x_vel;
    real y_vel;
    real vel;
    real offset;
    particle *twin_particle;

    particle_array = (particle *) G_MALLOC(Total_Particles * sizeof(particle));

    Particle_List = (particle **) G_MALLOC(Total_Particles * sizeof(particle *));
    for (i = 0; i < Total_Particles; i++)
        Particle_List[i] = &particle_array[i];

    r_scale = 3 * M_PI / 16;
    v_scale = (real) sqrt(1.0 / (double) r_scale);
    r_sum.x = (real) 0.0;
    r_sum.y = (real) 0.0;
    v_sum.x = (real) 0.0;
    v_sum.y = (real) 0.0;
    initstate(0, particle_state, RANDOM_SIZE);

    switch (cluster) {
    case ONE_CLUSTER:
        end_limit = Total_Particles;
        switch (model) {
        case UNIFORM:
            printf("Creating a one cluster, uniform distribution for %d ",
                   Total_Particles);
            printf("particles\n");
            break;
        case PLUMMER:
            printf("Creating a one cluster, non uniform distribution for %d ",
                   Total_Particles);
            printf("particles\n");
            break;
        }
        break;
    case TWO_CLUSTER:
        end_limit = (Total_Particles / 2) + (Total_Particles & 0x1);
        switch (model) {
        case UNIFORM:
            printf("Creating a two cluster, uniform distribution for %d ",
                   Total_Particles);
            printf("particles\n");
            break;
        case PLUMMER:
            printf("Creating a two cluster, non uniform distribution for %d ",
                   Total_Particles);
            printf("particles\n");
            break;
        }
        break;
    }
    setstate(particle_state);
    global_num_particles = 0;
    charge = 1.0 / Total_Particles;
    charge /= Total_Particles;
    for (i = 0; i < end_limit; i++) {
        new_particle = InitParticle(charge, charge);
        switch (model) {
        case UNIFORM:
            do {
                new_particle->pos.x = XRand(-1.0, 1.0);
                new_particle->pos.y = XRand(-1.0, 1.0);
                temp_r = DOT_PRODUCT((new_particle->pos), (new_particle->pos));
            }
            while (temp_r > (real) 1.0);
            radius = sqrt(temp_r);
            break;
        case PLUMMER:
            do
                radius = (real) 1.0 / (real) sqrt(pow(XRand(0.0, MAX_FRAC),
                                                      -2.0/3.0) - 1);
            while (radius > 9.0);
            PickShell(&(new_particle->pos), r_scale * radius);
            break;
        }
        VECTOR_ADD(r_sum, r_sum, (new_particle->pos));

        do {
            x_vel = XRand(0.0, 1.0);
            y_vel = XRand(0.0, 0.1);
        }
        while (y_vel > x_vel * x_vel * (real) pow(1.0 - (x_vel * x_vel), 3.5));
        vel = (real) sqrt(2.0) * x_vel / pow(1.0 + (radius * radius), 0.25);
        PickShell(&(new_particle->vel), v_scale * vel);
        VECTOR_ADD(v_sum, v_sum, (new_particle->vel));
    }

    if (cluster == TWO_CLUSTER) {
        switch (model) {
        case UNIFORM:
            offset = 1.5;
            break;
        case PLUMMER:
            offset = 2.0;
            break;
        }
        for (i = end_limit; i < Total_Particles; i++) {
            new_particle = InitParticle(charge, charge);
            twin_particle = Particle_List[i - end_limit];
            new_particle->pos.x = twin_particle->pos.x + offset;
            new_particle->pos.y = twin_particle->pos.y + offset;
            VECTOR_ADD(r_sum, r_sum, (new_particle->pos));
            new_particle->vel.x = twin_particle->vel.x;
            new_particle->vel.y = twin_particle->vel.y;
            VECTOR_ADD(v_sum, v_sum, (new_particle->vel));
        }
    }

    VECTOR_DIV(r_sum, r_sum, (real) Total_Particles);
    VECTOR_DIV(v_sum, v_sum, (real) Total_Particles);
    for (i = 0; i < Total_Particles; i++) {
        new_particle = Particle_List[i];
        VECTOR_SUB((new_particle->pos), (new_particle->pos), r_sum);
        VECTOR_SUB((new_particle->vel), (new_particle->vel), v_sum);
    }
}