private void InitSPH() { kernelComputeDensityPressure = shader.FindKernel("ComputeDensityPressure"); uint numThreadsX; shader.GetKernelThreadGroupSizes(kernelComputeDensityPressure, out numThreadsX, out _, out _); groupSize = Mathf.CeilToInt((float)particleCount / (float)numThreadsX); int amount = (int)numThreadsX * groupSize; particlesArray = new SPHParticle[amount]; float size = particleRadius * 1.1f; float center = rowSize * 0.5f; for (int i = 0; i < amount; i++) { Vector3 pos = new Vector3(); pos.x = (i % rowSize) + Random.Range(-0.1f, 0.1f) - center; pos.y = 2 + (float)((i / rowSize) / rowSize) * 1.1f; pos.z = ((i / rowSize) % rowSize) + Random.Range(-0.1f, 0.1f) - center; pos *= particleRadius; particlesArray[i] = new SPHParticle(pos); } }
private void Init() { particles = new KdTree <SPHParticle>(); for (int i = 0; i < amount; i++) { Vector3 pos = new Vector3( (i % rowSize) + UnityEngine.Random.Range(-0.1f, 0.1f), 2 + ((i / (float)rowSize) / rowSize) * 1.1f, ((i / rowSize) % rowSize) + UnityEngine.Random.Range(-0.1f, 0.1f) ); GameObject go = Instantiate(sphParticle, pos, Quaternion.identity) as GameObject; SPHParticle particle = go.GetComponent <SPHParticle>(); go.transform.localScale = parameters[parameterID].particleRadius * Vector3.one; particle.parameterID = parameterID; particles.Add(particle); } }
protected override JobHandle OnUpdate(JobHandle inputDeps) { if (cameraTransform == null) { cameraTransform = GameObject.Find("Main Camera").transform; } EntityManager.GetAllUniqueSharedComponentData(uniqueTypes); ComponentDataArray <SPHCollider> colliders = SPHColliderGroup.GetComponentDataArray <SPHCollider>(); int colliderCount = colliders.Length; for (int typeIndex = 1; typeIndex < uniqueTypes.Count; typeIndex++) { // Get the current chunk setting SPHParticle settings = uniqueTypes[typeIndex]; SPHCharacterGroup.SetFilter(settings); // Cache the data ComponentDataArray <Position> positions = SPHCharacterGroup.GetComponentDataArray <Position>(); ComponentDataArray <SPHVelocity> velocities = SPHCharacterGroup.GetComponentDataArray <SPHVelocity>(); int cacheIndex = typeIndex - 1; int particleCount = positions.Length; NativeMultiHashMap <int, int> hashMap = new NativeMultiHashMap <int, int>(particleCount, Allocator.TempJob); NativeArray <Position> particlesPosition = new NativeArray <Position>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <SPHVelocity> particlesVelocity = new NativeArray <SPHVelocity>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <float3> particlesForces = new NativeArray <float3>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <float> particlesPressure = new NativeArray <float>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <float> particlesDensity = new NativeArray <float>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <int> particleIndices = new NativeArray <int>(particleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <int> cellOffsetTableNative = new NativeArray <int>(cellOffsetTable, Allocator.TempJob); NativeArray <SPHCollider> copyColliders = new NativeArray <SPHCollider>(colliderCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); // Add new or dispose previous particle chunks PreviousParticle nextParticles = new PreviousParticle { hashMap = hashMap, particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, particlesForces = particlesForces, particlesPressure = particlesPressure, particlesDensity = particlesDensity, particleIndices = particleIndices, cellOffsetTable = cellOffsetTableNative, copyColliders = copyColliders }; if (cacheIndex > previousParticles.Count - 1) { previousParticles.Add(nextParticles); } else { previousParticles[cacheIndex].hashMap.Dispose(); previousParticles[cacheIndex].particlesPosition.Dispose(); previousParticles[cacheIndex].particlesVelocity.Dispose(); previousParticles[cacheIndex].particlesForces.Dispose(); previousParticles[cacheIndex].particlesPressure.Dispose(); previousParticles[cacheIndex].particlesDensity.Dispose(); previousParticles[cacheIndex].particleIndices.Dispose(); previousParticles[cacheIndex].cellOffsetTable.Dispose(); previousParticles[cacheIndex].copyColliders.Dispose(); } previousParticles[cacheIndex] = nextParticles; // Copy the component data to native arrays CopyComponentData <Position> particlesPositionJob = new CopyComponentData <Position> { Source = positions, Results = particlesPosition }; JobHandle particlesPositionJobHandle = particlesPositionJob.Schedule(particleCount, 64, inputDeps); CopyComponentData <SPHVelocity> particlesVelocityJob = new CopyComponentData <SPHVelocity> { Source = velocities, Results = particlesVelocity }; JobHandle particlesVelocityJobHandle = particlesVelocityJob.Schedule(particleCount, 64, inputDeps); CopyComponentData <SPHCollider> copyCollidersJob = new CopyComponentData <SPHCollider> { Source = colliders, Results = copyColliders }; JobHandle copyCollidersJobHandle = copyCollidersJob.Schedule(colliderCount, 64, inputDeps); MemsetNativeArray <float> particlesPressureJob = new MemsetNativeArray <float> { Source = particlesPressure, Value = 0.0f }; JobHandle particlesPressureJobHandle = particlesPressureJob.Schedule(particleCount, 64, inputDeps); MemsetNativeArray <float> particlesDensityJob = new MemsetNativeArray <float> { Source = particlesDensity, Value = 0.0f }; JobHandle particlesDensityJobHandle = particlesDensityJob.Schedule(particleCount, 64, inputDeps); MemsetNativeArray <int> particleIndicesJob = new MemsetNativeArray <int> { Source = particleIndices, Value = 0 }; JobHandle particleIndicesJobHandle = particleIndicesJob.Schedule(particleCount, 64, inputDeps); MemsetNativeArray <float3> particlesForcesJob = new MemsetNativeArray <float3> { Source = particlesForces, Value = new float3(0, 0, 0) }; JobHandle particlesForcesJobHandle = particlesForcesJob.Schedule(particleCount, 64, inputDeps); // Put positions into a hashMap HashPositions hashPositionsJob = new HashPositions { positions = particlesPosition, hashMap = hashMap.ToConcurrent(), cellRadius = settings.radius }; JobHandle hashPositionsJobHandle = hashPositionsJob.Schedule(particleCount, 64, particlesPositionJobHandle); JobHandle mergedPositionIndicesJobHandle = JobHandle.CombineDependencies(hashPositionsJobHandle, particleIndicesJobHandle); MergeParticles mergeParticlesJob = new MergeParticles { particleIndices = particleIndices }; JobHandle mergeParticlesJobHandle = mergeParticlesJob.Schedule(hashMap, 64, mergedPositionIndicesJobHandle); JobHandle mergedMergedParticlesDensityPressure = JobHandle.CombineDependencies(mergeParticlesJobHandle, particlesPressureJobHandle, particlesDensityJobHandle); // Compute density pressure ComputeDensityPressure computeDensityPressureJob = new ComputeDensityPressure { particlesPosition = particlesPosition, densities = particlesDensity, pressures = particlesPressure, hashMap = hashMap, cellOffsetTable = cellOffsetTableNative, settings = settings }; JobHandle computeDensityPressureJobHandle = computeDensityPressureJob.Schedule(particleCount, 64, mergedMergedParticlesDensityPressure); JobHandle mergeComputeDensityPressureVelocityForces = JobHandle.CombineDependencies(computeDensityPressureJobHandle, particlesForcesJobHandle, particlesVelocityJobHandle); // Compute forces ComputeForces computeForcesJob = new ComputeForces { particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, particlesForces = particlesForces, particlesPressure = particlesPressure, particlesDensity = particlesDensity, cellOffsetTable = cellOffsetTableNative, hashMap = hashMap, settings = settings }; JobHandle computeForcesJobHandle = computeForcesJob.Schedule(particleCount, 64, mergeComputeDensityPressureVelocityForces); // Integrate Integrate integrateJob = new Integrate { particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, particlesDensity = particlesDensity, particlesForces = particlesForces }; JobHandle integrateJobHandle = integrateJob.Schedule(particleCount, 64, computeForcesJobHandle); JobHandle mergedIntegrateCollider = JobHandle.CombineDependencies(integrateJobHandle, copyCollidersJobHandle); // Compute Colliders ComputeColliders computeCollidersJob = new ComputeColliders { particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, copyColliders = copyColliders, settings = settings }; JobHandle computeCollidersJobHandle = computeCollidersJob.Schedule(particleCount, 64, mergedIntegrateCollider); // Apply positions ApplyPositions applyPositionsJob = new ApplyPositions { particlesPosition = particlesPosition, particlesVelocity = particlesVelocity, positions = positions, velocities = velocities }; JobHandle applyPositionsJobHandle = applyPositionsJob.Schedule(particleCount, 64, computeCollidersJobHandle); inputDeps = applyPositionsJobHandle; } // Done uniqueTypes.Clear(); return(inputDeps); }