//---------------------------------------------------- // run the physics for all the particles //---------------------------------------------------- private void simulateParticlesCPU(float deltaTime) { if (_useMultithreading) { if (_parallelForeach == null) { _parallelForeach = new ParallelForeach((a, b) => particleSimulationLogic(a, b, deltaTime)); } _parallelForeach.Dispatch(NUM_PARTICLES); _parallelForeach.Wait(); } else { particleSimulationLogic(0, NUM_PARTICLES, deltaTime); } //---------------------------- // swap back and front buffer //---------------------------- var temp = _backBuffer; _backBuffer = _particles; _particles = temp; }
protected virtual void Awake() { _stopwatch.Start(); int cores = SystemInfo.processorCount; _integrationForeach = new ParallelForeach(integrateParticles, cores); _resolveCollisionsForeach = new ParallelForeach(resolveCollisionsNaive, cores); _integrationForeach.OnComplete += () => { System.Array.Copy(_particlesFront, _particlesBack, _aliveParticles); _resolveCollisionsForeach.Dispatch(_aliveParticles); }; ResetSimulation(); _randomColors = new Color[maxParticles]; for (int i = 0; i < maxParticles; i++) { _randomColors[i] = new Color(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value); } }
protected virtual void Update() { _deltaTime = 1f / 5f; RuntimeGizmoManager.TryGetGizmoDrawer(out drawer); BeforeParticleUpdate(); Array.Clear(collisionTimes, 0, collisionTimes.Length); for (int i = 0; i < _workerData.Length; i++) { _workerData[i].collisionChunkCounts.Clear(); _workerData[i].socialChunkCounts.Clear(); } using (new ProfilerSample("Destroy Particles")) { destroyParticles(); } using (new ProfilerSample("Emit Particles")) { emitParticles(); } if (_useMultithreading) { using (new ProfilerSample("Dispatch Simulation Jobs")) { _integrationForeach.Dispatch(_aliveParticles); } } else { using (new ProfilerSample("Integrate Particles")) { integrateParticles(0, 0, _aliveParticles); } Array.Copy(_particlesFront, _particlesBack, _aliveParticles); if (_useCollisionChunking) { using (new ProfilerSample("Accumulate And Sort")) { sortIntoChunks(isCollision: true); } using (new ProfilerSample("Resolve Collisions")) { resolveCollisionsChunked(); } } else { using (new ProfilerSample("Resolve Collisions")) { resolveCollisionsNaive(0, 0, _aliveParticles); } } if (_useSocialChunking) { using (new ProfilerSample("Accumulate And Sort")) { sortIntoChunks(isCollision: false); } using (new ProfilerSample("Apply Forces")) { doSocialForcesChunked(); } } else { using (new ProfilerSample("Apply Forces")) { doSocialForcesNaive(0, 0, _aliveParticles); } } using (new ProfilerSample("Apply Global Forces")) { applyGlobalForces(0, 0, _aliveParticles); } } if (Input.GetKeyDown(KeyCode.M)) { useKMeans = true; } if (useKMeans) { int LEN = 20; if (_means == null) { _means = new Vector3[LEN]; _raddii = new float[LEN]; for (int i = 0; i < LEN; i++) { _means[i] = _particlesFront[UnityEngine.Random.Range(0, _aliveParticles)].position; } } var newMeans = new Vector3[LEN]; var newCounts = new int[LEN]; _raddii = new float[LEN]; for (int i = 0; i < _aliveParticles; i++) { Particle p = _particlesFront[i]; float closestDist = float.MaxValue; int index = 0; for (int j = 0; j < LEN; j++) { float dist = Vector3.Distance(p.position, _means[j]); if (dist < closestDist) { closestDist = dist; index = j; } } drawer.color = _randomColors[index]; drawer.DrawWireSphere(p.position, 0.05f); newMeans[index] += p.position; newCounts[index] += 1; _raddii[index] = Mathf.Max(_raddii[index], closestDist); } for (int i = 0; i < LEN; i++) { if (newCounts[i] == 0) { _means[i] = UnityEngine.Random.insideUnitSphere; } else { _means[i] = newMeans[i] / newCounts[i]; } drawer.color = _randomColors[i]; drawer.DrawWireSphere(_means[i], _raddii[i]); } int totalInteractions = 0; for (int i = 0; i < _aliveParticles; i++) { Particle p = _particlesFront[i]; float closestDist = float.MaxValue; int index = 0; for (int j = 0; j < LEN; j++) { float dist = Vector3.Distance(p.position, _means[j]); if (dist < closestDist) { closestDist = dist; index = j; } } totalInteractions += newCounts[index]; for (int j = 0; j < LEN; j++) { if (j == index) { continue; } if (Vector3.Distance(p.position, _means[j]) < (0.5f + _raddii[j])) { totalInteractions += newCounts[j]; } } } Debug.Log(totalInteractions + " : " + (1024 * 1024)); } }