private void UpdateThread(object numThread) { float lifetime; Vector2 position; Vector2 velocity; float rotation; Rectangle rect; byte alpha; float floatAlpha; int numthread = (int)numThread; int particleperthread = (int)((float)numParticles / numThreads)+1; int startparticle = particleperthread * numthread; int endparticle = (int)MathHelper.Clamp( startparticle + particleperthread,0,positions.GetLength(0)); DateTime last= DateTime.Now; DateTime start; Vector2 grav; while (running) { if (newframe[numthread] == true) { #if DEBUG start = DateTime.Now; #endif Vector2 newpos; //(float)gametime.ElapsedGameTime.TotalSeconds; float elapsed = (float)gametime.ElapsedGameTime.TotalSeconds; //float elapsed = 0.003f; //int length = particles.GetLength(0); for (int i = startparticle; i < endparticle; i++) { // Save Particle information into a single Variable to avoid Array Bounds checks. lifetime = lifetimes[i]; velocity = velocities[i]; position = positions[i]; rotation = Rotations[i]; rect = rects[i]; alpha = alphas[i]; floatAlpha = floatalphas[i]; #region SingleParticleUpdateLogic lifetime += elapsed; if (lifetime < totallifetime) { if (gravtype == GravityType.OverallForce) { grav = gravity; } else if (gravtype == GravityType.Newton) { grav = new Vector2(); if (fixedMasses) { foreach (NewtonMass mass in masses) { grav += (mass.center - position) * (mass.weight * particleMass / (mass.center - position).LengthSquared()); } } else { for (int massIndex = 0; massIndex < masses.Count; massIndex++) { Vector2 Tempgrav = (masses[massIndex].center - position) * (masses[massIndex].weight * particleMass / (masses[massIndex].center - position).LengthSquared()); grav += Tempgrav / particleMass; masses[massIndex] = new NewtonMass() { center = masses[massIndex].center, velocity = masses[massIndex].velocity - Tempgrav / masses[massIndex].weight * elapsed * elapsed, weight = masses[massIndex].weight }; } } //grav /= 2; } else { grav = (gravity - position) * (1000 / (gravity - position).Length()); } velocity += grav * elapsed; velocity *= airFriction; newpos = position + velocity * elapsed; if (collisiontype == CollisionType.Collision) { #region ObjectCollision foreach (Rectangle colliderect in collisionrectangles) { //RightCollision if (position.X + size <= colliderect.X && newpos.X + size >= colliderect.X) { if (newpos.Y + size >= colliderect.Y && newpos.Y <= colliderect.Y + size) { velocity.X /= -1;//+ (float)(rand.NextDouble() / 10); velocity /= friction; newpos = position + velocity * elapsed; continue; } } //LeftCollision else if (position.X > colliderect.Right && newpos.X <= colliderect.Right) { if (newpos.Y + size >= colliderect.Y && newpos.Y <= colliderect.Y + size) { velocity.X /= -2;//+ (float)(rand.NextDouble() / 10); velocity /= friction; newpos = position + velocity * elapsed; continue; } } //BottomCollision else if (position.Y + size <= colliderect.Y && newpos.Y + size >= colliderect.Y) { if (position.X + size >= colliderect.X && position.X <= colliderect.Right) { velocity.Y /= -1;//+ (float)(rand.NextDouble() / 10); velocity /= friction; newpos = position + velocity * elapsed; continue; } } //UpCollision else if (position.Y >= colliderect.Y + size && newpos.Y <= colliderect.Y + size) { if (newpos.X + size >= colliderect.X && newpos.X <= colliderect.Right) { velocity.Y /= -1;//+ (float)(rand.NextDouble() / 10); velocity /= friction; newpos = position + velocity * elapsed; continue; } } } #endregion } if (BetweenParticleCollision) { for (int betweenParticlesIndex = 0; betweenParticlesIndex < positions.Length; betweenParticlesIndex++) { Vector2 tempVel; if (lifetimes[betweenParticlesIndex]<totallifetime) { if (position.X + size <= positions[betweenParticlesIndex].X && newpos.X + size >= positions[betweenParticlesIndex].X) { if (newpos.Y + size >= positions[betweenParticlesIndex].Y && newpos.Y <= positions[betweenParticlesIndex].Y + size) { //velocity.X /= -1;//+ (float)(rand.NextDouble() / 10); tempVel = velocity; velocity = velocities[betweenParticlesIndex]; velocities[betweenParticlesIndex] = tempVel; velocity /= friction; continue; } } //LeftCollision else if (position.X > positions[betweenParticlesIndex].X + size && newpos.X <= positions[betweenParticlesIndex].X + size) { if (newpos.Y + size >= positions[betweenParticlesIndex].Y && newpos.Y <= positions[betweenParticlesIndex].Y + size) { tempVel = velocity; velocity = velocities[betweenParticlesIndex]; velocities[betweenParticlesIndex] = tempVel; velocity /= friction; continue; } } //BottomCollision else if (position.Y + size <= positions[betweenParticlesIndex].Y && newpos.Y + size >= positions[betweenParticlesIndex].Y) { if (position.X + size >= positions[betweenParticlesIndex].X && position.X <= positions[betweenParticlesIndex].X + size) { tempVel = velocity; velocity = velocities[betweenParticlesIndex]; velocities[betweenParticlesIndex] = tempVel; velocity /= friction; continue; } } //UpCollision else if (position.Y >= positions[betweenParticlesIndex].Y + size && newpos.Y <= positions[betweenParticlesIndex].Y + size) { if (newpos.X + size >= positions[betweenParticlesIndex].X && newpos.X <= positions[betweenParticlesIndex].X + size) { tempVel = velocity; velocity = velocities[betweenParticlesIndex]; velocities[betweenParticlesIndex] = tempVel; velocity /= friction; continue; } } } } } Vector2 newVelocity = velocity * elapsed; position += newVelocity; rect.X = (int)position.X + size / 2; rect.Y = (int)position.Y + size / 2; if ((newVelocity).LengthSquared() > 1) { rotation = (float)Math.Acos(velocity.X / (velocity.Length())); if (velocity.Y < 0) rotation *= -1; } alpha = (byte)(255 - (255 * (lifetime / totallifetime))); floatAlpha = lifetime / totallifetime; } else if (Interlocked.Read(ref newSpawnCount) >= 0) { Interlocked.Decrement(ref newSpawnCount); ResetParticle(i); lifetime = lifetimes[i]; velocity = velocities[i]; position = positions[i]; rotation = Rotations[i]; rect = rects[i]; alpha = alphas[i]; floatAlpha = floatalphas[i]; } #endregion lifetimes[i] = lifetime; velocities[i] = velocity; positions[i] = position; Rotations[i] = rotation; rects[i] = rect; alphas[i] = alpha; floatalphas[i] = floatAlpha; } #if DEBUG duration[numthread] = DateTime.Now - start; last = start; #endif newframe[numthread] = false; } resetEvents[numthread].Set(); //Tell that this thread is ready barrier.SignalAndWait(); //Wait for Barrier to go on. } }
public void Update(GameTime gameTime) { if (initialized && enabled) { if (!fixedMasses) { for (int i = 0; i < masses.Count; i++) { masses[i] = new NewtonMass() { center = masses[i].center + (masses[i].velocity), velocity = masses[i].velocity, weight = masses[i].weight }; } } gametime = gameTime; if (spawntype == SpawnType.Fontaine) { newSpawners -= newSpawners - newSpawnCount; newSpawners += (spawnperS * (float)gametime.ElapsedGameTime.TotalSeconds); newSpawnCount = (long)newSpawners; } if (!useCuda) { for (int i = 0; i < numThreads; i++) { if (updatethread[i].ThreadState == ThreadState.Unstarted) updatethread[i].Start(i); newframe[i] = true; } } else { DateTime start = DateTime.Now; ParticleOptions options = CreateOptions((float)gametime.ElapsedGameTime.TotalSeconds); particleCuda.Run(CreateHolder(),options); duration[0] = DateTime.Now - start; } } }